Browse Source

US39: Bidirectional Covert Channel Protocol

Pflanzer, Jonas 4 years ago
parent
commit
920ea43ebe

+ 107 - 0
daemon/CovertProtocol.md

@@ -0,0 +1,107 @@
+# Covert Protocol
+The Covert Protocol is the protocol used to communicate over the covert channel. The communication over the covert channels aims mainly on file transfers.
+
+# Bidirectional Covert Protocol
+A bidirectional communication which uses commands to manage a file transfer.
+
+A packet is at least 2 bytes big. The first byte is the header followed by one or multiple data bytes.
+
+```
+|   1 byte   |       n bytes       |
+|   header   |        data         |
+```
+
+
+
+## Header
+A header contains a command and a segment number. Even if the `no operation` command is used the segment number must be counted.
+
+```
+|           8 bit           |
+|           header          |
+
+| 2 bit |  3 bit  |  3 bit  |
+|  seg  |    -    |   com   |
+```
+
+### Command
+Commands which indicate
+
+```
+0x0 no operation
+0x1 send file name size
+0x2 send file name
+0x3 send data size
+0x4 send data
+0x5 -
+0x6 cancel / reset
+0x7 error
+```
+
+The sending commands must be sent in the right order: lower number to higher number
+You can of course send a `no operation` or a `cancel / reset` command. If the order is not followed an `error` answer should be invoked.
+
+
+#### `0x0 no operation`
+No operation is the command which indicates to do nothing. It simply works as ACK to signal the packet was received.
+
+#### `0x1 send file name size`
+A file name size is a one byte number.
+```
+0 < file name size < 256
+```
+
+#### `0x2 send file name`
+A file name is a string which can be up to 255 bytes long.
+This command must be looped until the file name is fully transmitted!
+
+#### `0x3 send data size`
+A data size is a 4 byte unsigned int.
+This command must be looped until the data size is fully transmitted!
+
+#### `0x4 send data`
+Data are as much bytes as communicated in `send data size`.
+This command must be looped until the data is fully transmitted!
+
+#### `0x6 cancel / reset`
+This command resets the transmission. The following segment number is the segment number of the reset packet plus 1.
+
+#### `0x7 error`
+This command signals there was an error and the transmission is to be resetted. The following segment number is the segnemtn number of the error packet plus 1.
+
+
+### Segment
+The segment number is a counter for the packets in the covert channels. The segment number is increased on the passive server side.
+
+An example how the packet exchange might look like.
+```
+A                       B
+seg                   seg
+=========================
+1 -------------------->
+  <-------------------- 2
+2 -------------------->
+  <-------------------- 3
+3 --------- X                Packet lost
+
+3 -------------------->      Retransmission from A
+  <-------------------- 4
+4 -------------------->
+            X --------- 5    Packet lost
+
+            X --------- 5    Retransmission from B
+4 --------------------> 4    Retransmission from A
+  <-------------------- 5
+```
+
+
+
+It might happen that a server is not possible to answer or all the answers won't be transmitted. This case should be handled with the `cancel / reset` or `error` command upon reconnection. Maybe the session is recoverable without a reset.
+```
+A                       B
+seg                   seg
+=========================
+1 -------------------->
+1 -------------------->
+1 -------------------->
+```

+ 1 - 1
daemon/include/CovertChannel/CovertProtocol.hpp

@@ -261,7 +261,7 @@ public:
 
 			if (dataSize - dataPosition >= N) {
 				file.write((char *)data, N);
-				dataPosition += 2;
+				dataPosition += N;
 			} else {
 				file.write((char *)data, dataSize - dataPosition);
 				dataPosition = dataSize;

+ 162 - 0
daemon/include/CovertChannel/CovertProtocolBidirectional.hpp

@@ -0,0 +1,162 @@
+#ifndef COVERTPROTOCOLBIDIRECTIONAL_H
+#define COVERTPROTOCOLBIDIRECTIONAL_H
+
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <type_traits>
+
+#include "CovertProtocol.hpp"
+
+/**
+ * @class CovertProtocolBidirectional
+ *
+ * A bidirectional Covert Channel protocol with a variable size template.
+ *
+ * The protocol works bidirectional so the active side uses send to encode data to be sent and the passive side uses receive to extract data. And the passive
+ * side uses send to send ACKs and and the active side uses receive to receive ACKs.
+ *
+ * @param N number of bytes which can be used to transmit data
+ * @param PASSIVE passive mode
+ */
+template <int N, bool PASSIVE> class CovertProtocolBidirectional {
+	static_assert(N >= 2);
+
+public:
+	/**
+	 * CovertProtocolBidirectional constructor
+	 */
+	CovertProtocolBidirectional() : segment(PASSIVE ? 1 : 0) { lastData = new uint8_t[N](); }
+
+	/**
+	 * CovertProtocol destructor
+	 */
+	~CovertProtocolBidirectional() { delete[](lastData); }
+
+	/**
+	 * Starts sending a file.
+	 *
+	 * Starts sending a file if no transmission is running and the file exists.
+	 *
+	 * @param fileName name of the file in the file directory
+	 * @return true - file will be sent | false - file was not accepted
+	 */
+	bool sendFile(const std::string &fileName) {
+		if constexpr (PASSIVE) {
+			return false;
+		}
+
+		return protocol.sendFile(fileName);
+	}
+
+	/**
+	 * send encodes the data into the data array
+	 *
+	 * @param data must be an array of size N
+	 */
+	void send(uint8_t *const data) {
+		if (sendSegment()) {
+			std::memcpy(data, lastData, N);
+			return;
+		}
+
+		if constexpr (!PASSIVE) {
+			protocol.send(data + 1);
+		}
+
+		data[0] = (segment << 6);
+
+		// save data to lastData
+		std::memcpy(lastData, data, N);
+	}
+
+	/**
+	 * receive extracts data from the data array
+	 *
+	 * @param data must be an array of size N
+	 */
+	void receive(const uint8_t *const data) {
+		uint8_t seg = data[0] >> 6;
+
+		std::cerr << "segment: " << (int)segment << "\tack: " << (int)lastACKedSegment << "\tseg: " << (int)seg << std::endl;
+
+		if (receiveSegment(seg)) {
+			return;
+		}
+
+		if constexpr (PASSIVE) {
+			protocol.receive(data + 1);
+		}
+	}
+
+private:
+	/**
+	 * current segment counter
+	 */
+	uint8_t segment;
+
+	/**
+	 * last acknowledged segment counter
+	 */
+	uint8_t lastACKedSegment = 0;
+
+	/**
+	 * lastData sent
+	 */
+	uint8_t *lastData;
+
+	/**
+	 * Simple protocol
+	 */
+	CovertProtocol<N - 1, PASSIVE> protocol;
+
+	/**
+	 * Evaluates received segment number and increases own segment number if necessary
+	 *
+	 * @param seg received segment number
+	 * @return true if segment should discarded
+	 */
+	inline bool receiveSegment(uint8_t seg) {
+		if constexpr (PASSIVE) {
+
+			if (seg == segment && seg == increaseSegment(lastACKedSegment, 1)) {
+				lastACKedSegment = seg;
+				return false;
+			} else {
+				std::cerr << "Throwing this packet away" << std::endl;
+				return true;
+			}
+		} else {
+
+			if (seg == increaseSegment(segment, 1) && seg == increaseSegment(lastACKedSegment, 2)) {
+				lastACKedSegment = increaseSegment(lastACKedSegment, 1);
+				return false;
+			} else {
+				std::cerr << "Throwing this packet away" << std::endl;
+				return true;
+			}
+		}
+	}
+
+	/**
+	 * Returns true if the segment should be repeated.
+	 *
+	 * @return true if segment should be repeated
+	 */
+	inline bool sendSegment() {
+		if (segment == lastACKedSegment) {
+			segment = increaseSegment(segment, 1);
+			return false;
+		} else {
+			return true;
+		}
+	}
+
+	/**
+	 * Calculates seg + inc
+	 * @return seg + inc
+	 */
+	inline uint8_t increaseSegment(uint8_t seg, uint8_t inc) { return seg + inc & 0x3; }
+};
+
+#endif

+ 8 - 4
daemon/include/CovertChannel/TCPUrgencyChannel.hpp

@@ -3,7 +3,7 @@
 
 #include "CovertChannel.h"
 
-#include "CovertProtocol.hpp"
+#include "CovertProtocolBidirectional.hpp"
 
 /**
  * @class TCPUrgencyChannel
@@ -74,8 +74,9 @@ protected:
 			tcp.urg_ptr(0);
 			innerSender.send(pdu);
 		} else {
-			// uint16_t urg = tcp.urg_ptr();
-			// tcp.urg_ptr(0);
+			uint16_t data = tcp.urg_ptr();
+			protocol.receive((uint8_t *)(&data));
+			tcp.urg_ptr(0);
 			innerSender.send(pdu);
 		}
 		return true;
@@ -93,6 +94,9 @@ protected:
 	virtual bool handleChannelFromInner(Tins::PDU &pdu) {
 		Tins::TCP &tcp = pdu.rfind_pdu<Tins::TCP>();
 		if constexpr (PASSIVE) {
+			uint16_t data = 0;
+			protocol.send((uint8_t *)(&data));
+			tcp.urg_ptr(data);
 			outerSender.send(pdu);
 		} else {
 			uint16_t data = 0;
@@ -106,7 +110,7 @@ protected:
 	/**
 	 * protocol used to transmit data
 	 */
-	CovertProtocol<2, PASSIVE> protocol;
+	CovertProtocolBidirectional<2, PASSIVE> protocol;
 };
 
 #endif

+ 0 - 1
daemon/src/main.cpp

@@ -2,7 +2,6 @@
 
 #include "../include/Config.h"
 #include "../include/CovertChannel/CovertChannel.h"
-#include "../include/CovertChannel/CovertProtocol.hpp"
 #include "../include/CovertChannel/ForwardChannel.h"
 #include "../include/CovertChannel/TCPUrgencyChannel.hpp"
 #include "../include/Server.h"