Advertisement
Guest User

RAW Socks

a guest
Nov 1st, 2013
651
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.75 KB | None | 0 0
  1. ##
  2. #  Uses a raw socket to create a TCP/IP packet
  3. import socket
  4. from struct import *
  5. import sys
  6. import time
  7. import random
  8.  
  9.  
  10. class Header:
  11.  
  12.   ##
  13.   #  Creates a header structure that is encoded/decoded using
  14.   #  encodestr. Fields of this header are identified by strings
  15.   #  stored in enc_keys, the ordering of this list specifies
  16.   #  the ordering of data in the header.
  17.   #  @param encodestr Str Format encoding string
  18.   #  @param enc_keys List of Str that are names of fields in this
  19.   #   header. If an element is a list and not a str, it indicates
  20.   #   that the given element is a single byte split into pieces. The
  21.   #   inner list should contain only lists. Each of those lists contain
  22.   #   two elements, the name of the field and the number of bits it occupies.
  23.   def __init__(self, encodestr, enc_keys):
  24.     self.encodestr = encodestr
  25.     self.enc_keys = enc_keys
  26.     self.fields = {}
  27.  
  28.   ##
  29.   #  Allows struct like transparency
  30.   def __getattr__(self, key):
  31.     return self.get(key)
  32.  
  33.   def __repr__(self):
  34.     mystr = ""
  35.     for key in enc_keys:
  36.       if isinstance(key, list):
  37.         for k2, bits in key:
  38.           mystr += "{} = {}, ".format(k2, self.fields[k2])
  39.       else:
  40.         mystr += "{} = {}, ".format(key, self.fields[key])
  41.     return mystr
  42.  
  43.  
  44.   ##
  45.   #  Set a given field to a given value
  46.   def set(self, key, value):
  47.     self.fields[key] = value
  48.  
  49.   ##
  50.   #  Set multiple field's values at once
  51.   def sets(self, values):
  52.     for key in values:
  53.       self.set(key, values[key])
  54.  
  55.   ##
  56.   #  Get a single field's value
  57.   def get(self, key):
  58.     return self.fields[key]
  59.  
  60.   def gets(self):
  61.     return self.fields
  62.  
  63.   ##
  64.   #  Decodes the encoded string hdr into this header
  65.   def decode(self, hdr):
  66.     hdrvals = unpack (self.encodestr, hdr)
  67.     for idx,key in enumerate(self.enc_keys):
  68.       # Represents a byte split into pieces
  69.       if isinstance(key, list):
  70.         rshift = sum(map(lambda x: x[1], key))
  71.         for index, lst in enumerate(key):
  72.           k2, length = lst
  73.           rshift -= length
  74.           mask = 2**length - 1
  75.           val = (hdrvals[idx] >> rshift) & mask
  76.           self.set(k2, val)
  77.       else:
  78.         self.set(key, hdrvals[idx])
  79.  
  80.   ##
  81.   #  Encodes self into a header string as specified by
  82.   #  self.encodestr
  83.   def encode(self):
  84.     values = []
  85.     for key in self.enc_keys:
  86.       if isinstance(key, list):
  87.         sumbits = sum([x[1] for x in key])
  88.         value = 0
  89.         for k2, bits in key:
  90.           sumbits -= bits
  91.           value += (self.get(k2) << sumbits)
  92.         values.append(value)
  93.       else:
  94.         values.append(self.get(key))
  95.    
  96.     print ("Packing: {}\n{}".format(self.encodestr, values))
  97.     return pack(self.encodestr, *values)
  98.  
  99.  
  100. ##
  101. #  Defines some instance variables and special methods to
  102. #   help with reading and writing IP Headers
  103. class IPHeader(Header):
  104.  
  105.   ##
  106.   #  Constructor.
  107.   #  @param values Dict of values to set for this header
  108.   def __init__(self, values=None):
  109.     super().__init__(None, None)
  110.     self.encodestr = "!BBHHHBBH4s4s"
  111.     self.enc_keys = [[["version", 4], ["length", 4]], "tos", "total_len", "ident",
  112.       [["flags", 3], ["offset", 13]], "ttl", "protocol", "checksum",
  113.       "s_addr", "d_addr"]
  114.     if values != None:
  115.       self.sets(values)
  116.     self.fields["checksum"] = 0
  117.  
  118.   ##
  119.   #  Takes a raw packet (that begins with the IP Header) and
  120.   #  strips off the IP Header into this object.
  121.   #  @param hdr Raw IP Packet to decode
  122.   #  @post self is populated to contain data read from the packet
  123.   def decode(self, hdr):
  124.     super().decode(hdr[:20])
  125.     if self.length > 5:
  126.       toAdd = self.length - 5
  127.       decstr = "!"
  128.       added = ["L" for i in range(toAdd)]
  129.       decstr += "".join(added)
  130.       op_fields = ["options{}".format(i) for i in range(toAdd)]
  131.       iph_ops = Header(decstr, op_fields)
  132.       iph_ops.decode(hdr[20:20+(toAdd*4)])
  133.       self.sets(iph_ops.gets())
  134.  
  135.   ##
  136.   #  Encodes the values stored in self.fields into a network
  137.   #  ready IP Header.
  138.   #  @return Bytes array containing self encoded as an IP Header
  139.   def encode(self):
  140.     self.fields["checksum"] = 0
  141.     encData = super().encode()
  142.     halves = int(len(encData) / 2)
  143.     if len(encData) % 2 != 0:
  144.       halves+=1
  145.     decstr = "!"
  146.     decstr += "".join(["H" for i in range(halves)])
  147.     halves = unpack(decstr, encData)
  148.     checksum = 0
  149.     for half in halves:
  150.       checksum += half
  151.     while checksum >= 2**16:
  152.       additive = 0xFF00 & checksum
  153.       checksum &= 0xFF
  154.       checksum += additive
  155.     checksum = checksum ^ 0xFF
  156.  
  157.     self.set("checksum", checksum)
  158.     return super().encode()
  159.  
  160. ##
  161. #  Defines some instance variables and special methods to
  162. #   help with reading and writing TCP Headers
  163. class TCPHeader(Header):
  164.   def __init__(self, values=None):
  165.     super().__init__(None, None)
  166.     self.encodestr = "!HHLLHHHH"
  167.     self.enc_keys = ["s_port", "d_port", "seq", "ack",
  168.       [["offset", 4], ["reserved", 3], ["flags", 9]],
  169.       "window", "checksum", "urgent_ptr"]
  170.     self.options = pack("!BBBB",
  171.       0x02, 0x04, 0x40, 0x0c)
  172.     if values is not None:
  173.       self.sets(values)
  174.       self.fields['offset'] += int(len(self.options) / 4)
  175.  
  176.   def decode(self, hdr):
  177.     super().decode(hdr[:20])
  178.     if self.offset > 5:
  179.       toAdd = self.offset - 5
  180.       decstr = "!"
  181.       added = ["L" for i in range(toAdd)]
  182.       decstr += "".join(added)
  183.       decfields = ["options{}".format(i) for i in range(toAdd)]
  184.       tcp_ops = Header(decstr, decfields)
  185.       tcp_ops.decode(hdr[20:20+toAdd*4])
  186.       self.sets(tcp_ops.gets())
  187.  
  188.   def encode(self, iph, payload):
  189.     ipdata = Header.encode(iph)
  190.  
  191.     self.fields["checksum"] = 0
  192.     encData = ipdata + super().encode() + self.options + payload
  193.     halves = int(len(encData) / 2)
  194.     if len(encData) % 2 != 0:
  195.       halves+=1
  196.     decstr = "!"
  197.     decstr += "".join(["H" for i in range(halves)])
  198.     halves = unpack(decstr, encData)
  199.     checksum = 0
  200.     for half in halves:
  201.       checksum += half
  202.     while checksum >= 2**16:
  203.       additive = 0xFF00 & checksum
  204.       checksum &= 0xFF
  205.       checksum += additive
  206.     checksum = checksum ^ 0xFF
  207.  
  208.     self.set("checksum", checksum)
  209.     return super().encode() + self.options
  210.  
  211.  
  212. def configure_socket():
  213.   s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
  214.   # Tells the kernel not to put IP Headers on packets from this socket
  215.   s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
  216.   return s
  217.  
  218.  
  219.  
  220. def encodemsg (msg, src, dst):
  221.   iph = IPHeader({
  222.       "version": 4,
  223.       "length": 5,
  224.       "tos": 0, #Not real sure about this one
  225.       "total_len": 0,# 20+40+len(msg),
  226.       "flags": 2, # Don't fragment
  227.       "offset": 0,
  228.       "ttl": 64,
  229.       "protocol": 6,
  230.       "ident": 62546,#random.randint(0, 2**14-1),
  231.       "s_addr": socket.inet_aton(src[0]),
  232.       "d_addr": socket.inet_aton(dst[0]),
  233.   })
  234.  
  235.   tcph = TCPHeader({
  236.     "s_port": src[1],
  237.     "d_port": dst[1],
  238.     "seq": random.randint(0, 2**32-1),
  239.     "ack": 0,
  240.     "offset": 5,
  241.     "reserved": 0,
  242.     "flags": 2,
  243.     "window": 32792, # Arbitrarily large so no backoff
  244.     "urgent_ptr": 0,
  245.     "checksum": 0, # Filled in shortly
  246.   })
  247.  
  248.   encstr = "!"
  249.   toAdd = ["B" for i in range(len(msg))]
  250.   encstr += "".join(toAdd)
  251.   payload = pack(encstr, *bytes(msg, "utf-8")) if len(msg) > 0 else b''
  252.  
  253.   tcpdata = tcph.encode(iph, payload)
  254.  
  255.   return iph.encode() + tcpdata + payload
  256.  
  257.  
  258. def decodemsg(msg):
  259.   iph = IPHeader()
  260.   iph.decode(msg)
  261.   msg = msg[iph.length*4:]
  262.    
  263.   iph_values = iph.gets()
  264.   iph_values['s_addr'] = socket.inet_ntoa(iph_values['s_addr'])
  265.   iph_values['d_addr'] = socket.inet_ntoa(iph_values['d_addr'])
  266.  
  267.   print ("IP HEADER")
  268.   print (iph_values)
  269.   print ("\n")
  270.  
  271.   tcph = TCPHeader()
  272.   tcph.decode(msg)
  273.   msg = msg[tcph.offset*4:]
  274.  
  275.   print ("TCP HEADER")
  276.   print (tcph.gets())
  277.   print ("\n")
  278.  
  279.   print ("PAYLOAD:")
  280.   print (msg)
  281.  
  282.  
  283. def sniff():
  284.   s = configure_socket()
  285.   s.bind(("localhost", 0))
  286.   while True:
  287.     msg = s.recv(66565)
  288.     decodemsg(msg)
  289.   s.close()
  290.  
  291.  
  292. def main(src, dst):
  293.   s = configure_socket()
  294.   msg = input("$ ")
  295.   while msg != "exit":
  296.     payload = encodemsg(msg, src, dst)
  297.     s.sendto(payload, (dst[0], 0))
  298.     msg = input("$ ")
  299.  
  300. def usage():
  301.   print (
  302. """
  303. Usage: {} [<<src-host> <src-port> <dst-host> <dst-port>>]
  304.    If arguments are supplied, they must all be supplied. They
  305.    specify to open a connection as <src-host>:<src-port> connected
  306.    to <dst-host>:<dst-port>.
  307.    If no arguments are supplied, the program acts as a sniffer
  308. """.format(sys.argv[0]))
  309.  
  310. if __name__ == '__main__':
  311.   if len(sys.argv) == 5:
  312.     main((sys.argv[1], int(sys.argv[2])), (sys.argv[3], int(sys.argv[4])))
  313.   elif len(sys.argv) == 1:
  314.     sniff()
  315.   else:
  316.     usage()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement