1#!/usr/local/bin/python2.7 2# send urgent data from client to relay before connecting to server 3 4import os 5import re 6import sys 7import threading 8from addr import * 9from scapy.all import * 10 11client=os.getpid() & 0xffff 12relay=int(sys.argv[2]) 13server=int(sys.argv[1]) 14 15class Sniff1(threading.Thread): 16 filter = None 17 captured = None 18 packet = None 19 def __init__(self): 20 # clear packets buffered by scapy bpf 21 sniff(iface=LOCAL_IF, timeout=1) 22 super(Sniff1, self).__init__() 23 def run(self): 24 self.captured = sniff(iface=LOCAL_IF, filter=self.filter, 25 count=1, timeout=5) 26 if self.captured: 27 self.packet = self.captured[0] 28 29ip=IP(src=FAKE_NET_ADDR, dst=REMOTE_ADDR) 30 31print "Send SYN packet, receive SYN+ACK" 32syn=TCP(sport=client, dport=relay, seq=0, flags='S', window=(2**16)-1) 33synack=sr1(ip/syn, iface=LOCAL_IF, timeout=5) 34 35if synack is None: 36 print "ERROR: No matching SYN+ACK packet received" 37 exit(1) 38 39print "Send ACK packet to finish handshake" 40ack=TCP(sport=synack.dport, dport=synack.sport, 41 seq=1, ack=synack.seq+1, flags='A') 42send(ip/ack, iface=LOCAL_IF) 43 44print "Expect spliced SYN" 45sniffer = Sniff1(); 46sniffer.filter = "src %s and dst %s and tcp port %u " \ 47 "and tcp[tcpflags] = tcp-syn" % (ip.dst, ip.src, server) 48sniffer.start() 49time.sleep(1) 50 51print "Send 20 bytes payload and one urgent byte" 52data="0123456789Xabcdefghij" 53payload=TCP(sport=synack.dport, dport=synack.sport, urgptr=11, 54 seq=1, ack=synack.seq+1, flags='APU')/data 55payload_ack=sr1(ip/payload, iface=LOCAL_IF) 56 57if payload_ack is None: 58 print "ERROR: No payload ACK packet received" 59 exit(1) 60if payload_ack.ack != len(data)+1: 61 print "ERROR: Expected ack %d, got %d in payload ACK" % \ 62 (len(data)+1, payload_ack.ack) 63 exit(1) 64 65sniffer.join(timeout=7) 66spliced_syn = sniffer.packet 67 68if spliced_syn is None: 69 print "ERROR: No spliced SYN packet received" 70 exit(1) 71 72print "Expect spliced urgent payload" 73sniffer = Sniff1(); 74sniffer.filter = "src %s and dst %s and tcp port %u " \ 75 "and tcp[tcpflags] = tcp-ack|tcp-urg" % (ip.dst, ip.src, server) 76sniffer.start() 77time.sleep(1) 78 79print "Wait for splicing syscall, grep it in relay log" 80def loggrep(file, regex, timeout): 81 for i in range(timeout): 82 for line in open(file, 'r'): 83 if re.search(regex, line): 84 return line 85 time.sleep(1) 86 return None 87if not loggrep("relay.log", "Spliced", 5): 88 print "ERROR: Relay did not splice" 89 exit(1) 90 91print "Send spliced SYN+ACK packet to finish handshake" 92spliced_synack=TCP(sport=spliced_syn.dport, dport=spliced_syn.sport, 93 seq=0, ack=spliced_syn.seq+1, flags='SA') 94spliced_ack=sr1(ip/spliced_synack, iface=LOCAL_IF) 95 96if spliced_ack is None: 97 print "ERROR: No spliced ACK packet received" 98 exit(1) 99 100sniffer.join(timeout=7) 101spliced_payload = sniffer.packet 102 103if spliced_payload is None: 104 print "ERROR: No spliced urgent payload packet received" 105 exit(1) 106if spliced_payload.seq != spliced_ack.seq: 107 print "ERROR: Expected seq %d, got %d in spliced payload" % \ 108 (spliced_ack.seq, spliced_payload.seq) 109 exit(1) 110if spliced_payload.urgptr != 11: 111 print "ERROR: Expected urgptr %d, got %d in spliced payload" % \ 112 (11, spliced_payload.urgptr) 113 exit(1) 114 115print "Kill connections with RST" 116spliced_rst=TCP(sport=spliced_ack.dport, dport=spliced_ack.sport, 117 seq=1, ack=spliced_ack.seq, flags='RA') 118send(ip/spliced_rst, iface=LOCAL_IF) 119rst=TCP(sport=synack.dport, dport=synack.sport, 120 seq=payload_ack.ack, ack=synack.seq+1, flags='RA') 121send(ip/rst, iface=LOCAL_IF) 122 123exit(0) 124