Ver código fonte

real polling with chunked messages

Marius Schwarz 4 anos atrás
pai
commit
dfa63356c7
2 arquivos alterados com 90 adições e 68 exclusões
  1. 2 1
      src/main.rs
  2. 88 67
      src/server.rs

Diferenças do arquivo suprimidas por serem muito extensas
+ 2 - 1
src/main.rs


+ 88 - 67
src/server.rs

@@ -103,16 +103,23 @@ pub struct DnsTunnel {
     server: String,
     domain: String,
     port: u16,
+    server_buffer: String
 }
 
-impl DnsTunnel {
+impl<'a> DnsTunnel {
 
     /// Craft a new instance of a DNS Tunnel
     /// ip: IP of the DNS tunnel server
     /// port: port of the DNS tunnel server
     pub fn new(domain: String, server: String, port: u16) -> DnsTunnel {
-        DnsTunnel { server, port, domain }
+        DnsTunnel { server, port, domain, server_buffer: String::new() }
     }
+
+    /// keeps open a listener to transfer data via DNS tunneling
+    pub fn new_server(domain: String, port: u16) -> DnsTunnel {
+        DnsTunnel { server: String::new(), port, domain, server_buffer: String::new() }
+    }
+
     pub fn connect(&self) -> Result<(), &str> {
         if !self.check_connection() {
             println!("[-] DNS Tunnel not reachable");
@@ -122,6 +129,12 @@ impl DnsTunnel {
         Ok(())
     }
 
+    /// A function that can be called from the server side and lets the server send arbitrary
+    /// strings
+    pub fn server_send(&mut self, data: String) {
+        self.server_buffer.push_str(&data);
+    }
+
     pub fn send_string(&self, data: String) -> Result<(), &str> {
 
         if !self.init_send() {
@@ -142,7 +155,6 @@ impl DnsTunnel {
             for chunk in chunks {
                 // Send the actual DATA after the tunnel is established
                 println!("[DBG]: Sending Chunk: {}", chunk);
-
                 // send the chunk
                 self.send_chunk(chunk);
             }
@@ -160,89 +172,102 @@ impl DnsTunnel {
 
     }
 
-    /// keeps open a listener to transfer data via DNS tunneling
-    pub fn tunnel_server(port: u16) {
+    pub fn serve(&mut self) {
 
         let mut full_data: String = String::new();
 
         println!("[+] Started DNS tunnel, ready to receive data...");
-        let socket = UdpSocket::bind(("0.0.0.0", port)).unwrap();
+        let socket = UdpSocket::bind(("0.0.0.0", self.port)).unwrap();
 
         // starting main loop
         let mut poll_status = PollStatus::NONE;
 
-
+        let mut message = String::new();
+        // UFF
         loop {
             let mut response_buffer = BytePacketBuffer::new();
 
             // receive into response buffer
             let (_, src) = socket.recv_from(&mut response_buffer.buf).unwrap();
 
+            // decode the response as DNS packet
             let mut packet = DnsPacket::from_bytes(&mut response_buffer);
 
-            if packet.questions.len() >= 1 {
+            // if there is at least one question of the type TXT
+            if packet.questions.len() >= 1 && packet.questions[0].qtype == QueryType::TXT {
                 let quest = &packet.questions[0];
-                if quest.qtype == QueryType::TXT {
-
-                    let data = &quest.name;
-                    let mut data: Vec<&str> = data.split(".").collect();
-                    let data = data[0];
-
-                    let data = b64decode(data);
-                    let data = String::from_utf8_lossy(&xor(&data, 0xF5)).to_string();
-
-                    if !data.contains("INIT") &&
-                        !data.contains("START") &&
-                        !data.contains("POLL") &&
-                        !data.contains("END") {
-                        let mut data: Vec<&str> = data.split(".").collect();
-                        let data = data[0];
-                        full_data.push_str(data);
-
-                    } else if data.contains("END") {
-                        println!("[*] Message: {}", full_data);
-                        full_data = String::new();
-                    } else if data.contains("POLL") {
+
+
+                // Exfiltrate the Data
+                let data = &packet.questions[0].name;
+                let mut data: Vec<&str> = data.split(".").collect();
+                let data = data[0];
+
+                // Decode/Decrypt the data
+                let data = b64decode(data);
+                let data = String::from_utf8_lossy(&xor(&data, 0xF5)).to_string();
+
+
+                // Return DNS Packet
+                let mut return_packet = DnsPacket::empty();
+
+                match &data[..] {
+                    "INIT" => {
+                        return_packet = DnsTunnel::get_txt_response(&packet, "ACK".to_string());
+                    },
+                    "START" => {
+                        return_packet = DnsTunnel::get_txt_response(&packet, "ACK".to_string());
+                    },
+                    "END" => {
+                        println!("Full Message {}", message);
+                        message = String::new();
+                        return_packet = DnsTunnel::get_txt_response(&packet, "ACK".to_string());
+                    },
+                    "POLL" => {
                         match poll_status {
                             PollStatus::NONE => {
                                 // Enter Polling Mode
                                 println!("[*] Polling Recieved");
-                                let mut ret_pkt = DnsTunnel::get_txt_response(&packet, "START".to_string());
-                                let res_buffer = DnsTunnel::get_buffer(&mut ret_pkt);
-                                socket.send_to(res_buffer.get_range(0, res_buffer.pos()).unwrap(), src).unwrap();
+                                return_packet = DnsTunnel::get_txt_response(&packet, "START".to_string());
                                 poll_status = PollStatus::STARTED;
                             },
                             PollStatus::STARTED => {
-                                let data  = "DAFUQISTHISSHIT";
-                                // Send the data
-                                let mut ret_pkt = DnsTunnel::get_txt_response(&packet, data.to_string());
-                                let res_buffer = DnsTunnel::get_buffer(&mut ret_pkt);
-                                socket.send_to(res_buffer.get_range(0, res_buffer.pos()).unwrap(), src).unwrap();
-                                poll_status = PollStatus::FINISHED;
+
+                                let mut chunk = String::new();
+                                if self.server_buffer.len() >= 63 {
+                                    chunk = self.server_buffer[..63].to_string();
+                                    self.server_buffer = self.server_buffer[63..].to_string();
+                                } else {
+                                    chunk.push_str(&self.server_buffer);
+                                    self.server_buffer = String::new();
+                                }
+                                return_packet = DnsTunnel::get_txt_response(&packet, chunk);
+
+                                if self.server_buffer.len() == 0 {
+                                    poll_status = PollStatus::FINISHED;
+                                }
                             },
                             PollStatus::FINISHED => {
                                 // Send STOP message
-                                let mut ret_pkt = DnsTunnel::get_txt_response(&packet, "END".to_string());
-                                let res_buffer = DnsTunnel::get_buffer(&mut ret_pkt);
-                                socket.send_to(res_buffer.get_range(0, res_buffer.pos()).unwrap(), src).unwrap();
+                                return_packet = DnsTunnel::get_txt_response(&packet, "END".to_string());
                                 poll_status = PollStatus::NONE;
                             }
                         }
-
-
+                    },
+                    _ => {
+                        message.push_str(&data);
                     }
-                    // return ACk
-                    let mut ret_pkt = DnsTunnel::get_txt_response(&packet, "ACK".to_string());
-                    let res_buffer = DnsTunnel::get_buffer(&mut ret_pkt);
-                    socket.send_to(res_buffer.get_range(0, res_buffer.pos()).unwrap(), src).unwrap();
 
-                    //
-                    //let data = DnsServer::decode(data);
                 }
+                // return the response Packet
+                let res_buffer = DnsTunnel::get_buffer(&mut return_packet);
+                socket.send_to(res_buffer.get_range(0, res_buffer.pos()).unwrap(), src).unwrap();
             }
         }
     }
 
+
+
     /// this is not only checking for an `ACK` as answer, but gets the returned
     /// data
     fn send_recv(&self, message: &str) -> Result<String, ()> {
@@ -326,7 +351,7 @@ impl DnsTunnel {
         self.send_chunk("END")
     }
 
-    pub fn poll(&self) -> Result<String, ()> {
+    pub fn receive_msg(&self) -> Option<String> {
 
         let mut wait_for_data = false;
         let mut return_data = String::new();
@@ -339,9 +364,11 @@ impl DnsTunnel {
                         wait_for_data = true;
                     },
                     "END" => {
-                        println!("END");
                         wait_for_data = false;
-                        return Ok(return_data);
+                        return Some(return_data);
+                    },
+                    "NONE" => {
+                        return None;
                     },
                     _ => {
                         return_data.push_str(&data);
@@ -350,7 +377,7 @@ impl DnsTunnel {
                 }
             }
         }
-        Err(())
+        return None;
     }
 
     fn get_txt_response(ref_pkt: &DnsPacket, data: String) -> DnsPacket {
@@ -387,8 +414,10 @@ impl DnsTunnel {
         return res_buffer;
     }
 
-    /*
-    fn split_data(data: String) -> Vec<String> {
+    /// Function splits  String ref into many chunks and returns a
+    /// vector of those chunks
+    fn split_data(&self, data: &'a String) -> Vec<&'a str> {
+
         if data.len() > 63 {
             // split the data in chunks of 63 bytes
             let chunks = data.as_bytes()
@@ -396,20 +425,12 @@ impl DnsTunnel {
                 .map(str::from_utf8)
                 .collect::<Result<Vec<&str>, _>>()
                 .unwrap();
-
-            for chunk in chunks {
-                // Send the actual DATA after the tunnel is established
-                println!("[DBG]: Sending Chunk: {}", chunk);
-
-                // send the chunk
-                self.send_chunk(chunk);
-            }
-        } else {
-            self.send_chunk(&data);
+            return chunks;
         }
-
+        let mut ret = Vec::new();
+        ret.push(&data[..]);
+        return ret;
     }
-    */
 }
 
 

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff