1*8feac640Sbluhm#!/usr/local/bin/python3 23488794cSbluhm# send data from client via relay before server handshake is completed 33488794cSbluhm 43488794cSbluhmimport os 53488794cSbluhmimport sys 63488794cSbluhmimport threading 73488794cSbluhmfrom addr import * 83488794cSbluhmfrom scapy.all import * 93488794cSbluhm 103488794cSbluhmclient=os.getpid() & 0xffff 113488794cSbluhmrelay=int(sys.argv[2]) 123488794cSbluhmserver=int(sys.argv[1]) 133488794cSbluhm 143488794cSbluhmclass Sniff1(threading.Thread): 153488794cSbluhm filter = None 163488794cSbluhm captured = None 173488794cSbluhm packet = None 18925939b7Sbluhm def __init__(self): 19925939b7Sbluhm # clear packets buffered by scapy bpf 20925939b7Sbluhm sniff(iface=LOCAL_IF, timeout=1) 21925939b7Sbluhm super(Sniff1, self).__init__() 223488794cSbluhm def run(self): 233488794cSbluhm self.captured = sniff(iface=LOCAL_IF, filter=self.filter, 243488794cSbluhm count=1, timeout=5) 253488794cSbluhm if self.captured: 263488794cSbluhm self.packet = self.captured[0] 273488794cSbluhm 283488794cSbluhmip=IP(src=FAKE_NET_ADDR, dst=REMOTE_ADDR) 293488794cSbluhm 30*8feac640Sbluhmprint("Send SYN packet, receive SYN+ACK") 313488794cSbluhmsyn=TCP(sport=client, dport=relay, seq=0, flags='S', window=(2**16)-1) 323488794cSbluhmsynack=sr1(ip/syn, iface=LOCAL_IF, timeout=5) 333488794cSbluhm 343488794cSbluhmif synack is None: 35*8feac640Sbluhm print("ERROR: No matching SYN+ACK packet received") 363488794cSbluhm exit(1) 373488794cSbluhm 38*8feac640Sbluhmprint("Expect spliced SYN") 393488794cSbluhmsniffer = Sniff1(); 403488794cSbluhmsniffer.filter = "src %s and dst %s and tcp port %u " \ 413488794cSbluhm "and tcp[tcpflags] = tcp-syn" % (ip.dst, ip.src, server) 423488794cSbluhmsniffer.start() 433488794cSbluhmtime.sleep(1) 443488794cSbluhm 45*8feac640Sbluhmprint("Send ACK packet to finish handshake") 463488794cSbluhmack=TCP(sport=synack.dport, dport=synack.sport, 473488794cSbluhm seq=1, ack=synack.seq+1, flags='A') 483488794cSbluhmsend(ip/ack, iface=LOCAL_IF) 493488794cSbluhm 503488794cSbluhmsniffer.join(timeout=7) 513488794cSbluhmspliced_syn = sniffer.packet 523488794cSbluhm 533488794cSbluhmif spliced_syn is None: 54*8feac640Sbluhm print("ERROR: No spliced SYN packet received") 553488794cSbluhm exit(1) 563488794cSbluhm 57*8feac640Sbluhmprint("Send 10 bytes payload") 583488794cSbluhmdata="0123456789" 593488794cSbluhmpayload=TCP(sport=synack.dport, dport=synack.sport, 603488794cSbluhm seq=1, ack=synack.seq+1, flags='AP')/data 613488794cSbluhmpayload_ack=sr1(ip/payload, iface=LOCAL_IF) 623488794cSbluhm 633488794cSbluhmif payload_ack is None: 64*8feac640Sbluhm print("ERROR: No payload ACK packet received") 653488794cSbluhm exit(1) 663488794cSbluhmif payload_ack.ack != len(data)+1: 67*8feac640Sbluhm print("ERROR: Expected ack %d, got %d in payload ACK" % 68*8feac640Sbluhm (len(data)+1, payload_ack.ack)) 693488794cSbluhm exit(1) 703488794cSbluhm 713488794cSbluhmtime.sleep(1) 723488794cSbluhm 73*8feac640Sbluhmprint("Expect spliced payload") 743488794cSbluhmsniffer = Sniff1(); 753488794cSbluhmsniffer.filter = "src %s and dst %s and tcp port %u " \ 763488794cSbluhm "and tcp[tcpflags] = tcp-ack|tcp-push" % (ip.dst, ip.src, server) 773488794cSbluhmsniffer.start() 783488794cSbluhmtime.sleep(1) 793488794cSbluhm 80*8feac640Sbluhmprint("Send spliced SYN+ACK packet to finish handshake") 813488794cSbluhmspliced_synack=TCP(sport=spliced_syn.dport, dport=spliced_syn.sport, 823488794cSbluhm seq=0, ack=spliced_syn.seq+1, flags='SA') 833488794cSbluhmspliced_ack=sr1(ip/spliced_synack, iface=LOCAL_IF) 843488794cSbluhm 853488794cSbluhmif spliced_ack is None: 86*8feac640Sbluhm print("ERROR: No spliced ACK packet received") 873488794cSbluhm exit(1) 883488794cSbluhm 893488794cSbluhmsniffer.join(timeout=7) 903488794cSbluhmspliced_payload = sniffer.packet 913488794cSbluhm 923488794cSbluhmif spliced_payload is None: 93*8feac640Sbluhm print("ERROR: No spliced payload packet received") 943488794cSbluhm exit(1) 953488794cSbluhmif spliced_payload.seq != spliced_ack.seq: 96*8feac640Sbluhm print("ERROR: Expected seq %d, got %d in spliced payload" % 97*8feac640Sbluhm (spliced_ack.seq, spliced_payload.seq)) 983488794cSbluhm exit(1) 993488794cSbluhmif spliced_payload.len-20-20 != len(data): 100*8feac640Sbluhm print("ERROR: Expected len %d, got %d in spliced payload" % 101*8feac640Sbluhm (len(data), spliced_payload.len-20-20)) 1023488794cSbluhm exit(1) 1033488794cSbluhm 104*8feac640Sbluhmprint("Expect spliced ACK retransmission") 105925939b7Sbluhmsniffer = Sniff1(); 106925939b7Sbluhmsniffer.filter = "src %s and dst %s and tcp port %u " \ 107925939b7Sbluhm "and tcp[tcpflags] = tcp-ack" % (ip.dst, ip.src, server) 108925939b7Sbluhmsniffer.start() 109925939b7Sbluhmtime.sleep(1) 110925939b7Sbluhm 111*8feac640Sbluhmprint("Retransmit spliced SYN+ACK packet to trigger ACK") 112925939b7Sbluhmsend(ip/spliced_synack, iface=LOCAL_IF) 113925939b7Sbluhm 114925939b7Sbluhmsniffer.join(timeout=7) 115925939b7Sbluhmspliced_ack_retrans = sniffer.packet 1163488794cSbluhm 1173488794cSbluhmif spliced_ack_retrans is None: 118*8feac640Sbluhm print("ERROR: No spliced ACK retransmit packet received") 1193488794cSbluhm exit(1) 1203488794cSbluhmif spliced_ack_retrans.seq != spliced_syn.seq+1+len(data): 121*8feac640Sbluhm print("ERROR: Expected seq %d, got %d in retransmitted spliced ack" % 122*8feac640Sbluhm (spliced_syn.seq+1+len(data), spliced_ack_retrans.seq)) 1233488794cSbluhm exit(1) 1243488794cSbluhmif spliced_ack_retrans.ack != 1: 125*8feac640Sbluhm print("ERROR: Expected ack %d, got %d in retransmitted spliced ack" % 126*8feac640Sbluhm (1, spliced_ack_retrans.ack)) 1273488794cSbluhm exit(1) 1283488794cSbluhmif spliced_ack_retrans.len-20-20 != 0: 129*8feac640Sbluhm print("ERROR: Expected len %d, got %d in retransmitted spliced ack" % 130*8feac640Sbluhm (0, spliced_ack_retrans.len-20-20)) 1313488794cSbluhm exit(1) 1323488794cSbluhm 133*8feac640Sbluhmprint("Kill connections with RST") 1343488794cSbluhmspliced_rst=TCP(sport=spliced_ack.dport, dport=spliced_ack.sport, 1353488794cSbluhm seq=1, ack=spliced_ack.seq, flags='RA') 1363488794cSbluhmsend(ip/spliced_rst, iface=LOCAL_IF) 1373488794cSbluhmrst=TCP(sport=synack.dport, dport=synack.sport, 1383488794cSbluhm seq=payload_ack.ack, ack=synack.seq+1, flags='RA') 1393488794cSbluhmsend(ip/rst, iface=LOCAL_IF) 1403488794cSbluhm 1413488794cSbluhmexit(0) 142