Code To Create TCP packet header with Python socket module

Namaste Hackers,



Today, In this tutorial I am going to show you how you can easily create a raw TCP packet using python socket module and struct module.


Friend, If You Are New on our Blog, Then Don't Forget To Follow Us On Social Media Because We Create These Types of Tutorials in Every Small Gap of the week and of course, with social media, you can easily get updates of this blog or you can also directly connect with me on facebook.

In today's module basically, we going to play with socket modules. so, To Make you skill more familiar with python and socket module. You Can Also Read Our Other Networking Posts Also.




Or You Can Also Check Our Complete Project List Here


Introduction

As we know, Many times for large networking project we have to write codes for creating raw networking packets without using any external libraries or modules And at that time, to accomplish our work we have to play with binary level data.
By the way, TCP packets are the most important packets to established a secure connection between client and server. Without TCP handshake, a client and server can't establish a secure connection. so this reason also makes more solid pressure to understand TCP concept briefly. So, Basically, In Today's tutorial, I am going to show you how you can easily create TCP header packets with socket and struct module. This tutorial will give you important and structural knowledge of TCP packets and python struct module methods. How we can use python for networking packets analyzing, creating, manipulation etc.


Requirements


1. Python 2.x Or Python 3.x
2. Linux
3. Python Socket and Struct
4. Wireshark (For Verifying Create TCP Packet)


How it's going to work?


As we know, python is not that much compatible with binary number operations if compared to C language but yes, there are some modules that provide us the facilities to play with binary level concepts. well, here struct module is our life-saving module which provides us the facility to play with the binary network packet. I am assuming that you all are already aware of python struct module and python socket module. Basically, we just going to create a TCP packet using struct module and then send it using python socket module.

TCP Packet Structure.

Before Starting Our Example Codes, Take a look at this diagram.



This diagram is a representation of TCP Header Packet Structure. As you can see in this diagram there are various types of field, flags are available in TCP header packet. so, we going to load all these fields into our TCP packet structure to make it real.

Ooh yes, another noticeable topic in TCP packet is its CheckSum field and because Checksum of TCP packet is a very interesting topic. I created a separate post on it. check it here

Basically, To calculate the Checksum of TCP packet first we have to assemble all the data of TCP packet where set checksum value equal to Zero. then, create a pseudo packet that contains various pieces of information from all over the packet header after that follow checksum algorithms to find the correct hash value. (Don't know about Pseudo Concept. Check it here)

 Now, let's move to practical codes that will provide you more understanding of today's concept


Step 1

Let's try to understand with a simple example. Basically Here In preview codes, first import modules and then, I created a simple starting structure for python class object. In it's initialized function, we will take five arguments from the user, arguments are destination Port, destination IP address, source IP address, source port and TCP Raw Data to calculate correct checksum.


#!/usr/bin/python
import socket
import struct


class TCPPacket:
 def __init__(self, dport = 80, sport = 65535, dst='127.0.0.1', src='192.168.1.101', data = 'Nothing'):
  self.dport = dport
  self.sport = sport
  self.src_ip = src
  self.dst_ip = dst
  self.data   = data
  self.raw = None
  self.create_tcp_feilds()


Step 2

As I already mention TCP Diagram above, here in this function we are going to create all required fields with possible Default values and store it in the self container so that in next function we can directly access this data to assemble and create TCP packet structure.

To make my codes more easy to understand I tried to use maximum comments in codes to make it more simple for you.
I hope now you all are getting what I have done in these codes.


 def create_tcp_feilds(self):

  # ---- [ Source Port ]
  self.tcp_src = self.sport

  # ---- [ Destination Port ]
  self.tcp_dst = self.dport

  # ---- [ TCP Sequence Number]
  self.tcp_seq = 0

  # ---- [ TCP Acknowledgement Number]
  self.tcp_ack_seq = 0

  # ---- [ Header Length ]
  self.tcp_hdr_len = 80

  # ---- [ TCP Flags ]
  tcp_flags_rsv = (0 << 9)
  tcp_flags_noc = (0 << 8)
  tcp_flags_cwr = (0 << 7)
  tcp_flags_ecn = (0 << 6)
  tcp_flags_urg = (0 << 5)
  tcp_flags_ack = (0 << 4)
  tcp_flags_psh = (0 << 3)
  tcp_flags_rst = (0 << 2)
  tcp_flags_syn = (1 << 1)
  tcp_flags_fin = (0)

  self.tcp_flags = tcp_flags_rsv + tcp_flags_noc + tcp_flags_cwr + \
        tcp_flags_ecn + tcp_flags_urg + tcp_flags_ack + \
        tcp_flags_psh + tcp_flags_rst + tcp_flags_syn + tcp_flags_fin

  # ---- [ TCP Window Size ]
  self.tcp_wdw = socket.htons (5840)

  # ---- [ TCP CheckSum ]
  self.tcp_chksum = 0

  # ---- [ TCP Urgent Pointer ]
  self.tcp_urg_ptr = 0


  return



Step  3

Assemble All Feilds with the help of struct module and create a TCP Binary Packet Structure. I hope my comments are providing you hints to understand these codes. (if struct module looks hard to you, comment below I will make a tutorial on it.)
Basically, In current function, we just creating a temporarily TCP packet with Checksum value 0 so that in next functions we can calculate right checksum value with the help of pseudo concept and then reassemble all this data to make a valid TCP packet structure.


 def assemble_tcp_feilds(self):
  self.raw = struct.pack('!HHLLBBHHH', # Data Structure Representation
   self.tcp_src,   # Source IP
   self.tcp_dst,    # Destination IP
   self.tcp_seq,    # Sequence
   self.tcp_ack_seq,  # Acknownlegment Sequence
   self.tcp_hdr_len,   # Header Length
   self.tcp_flags ,    # TCP Flags
   self.tcp_wdw,   # TCP Windows
   self.tcp_chksum,  # TCP cheksum
   self.tcp_urg_ptr # TCP Urgent Pointer
   )

  self.calculate_chksum() # Call Calculate CheckSum
  return



Step 4

In this function, we going to create a pseudo frame that will help us to calculate right checksum value. For more detail about Pseudo Concept. Check it here


 def calculate_chksum(self):
  src_addr     = socket.inet_aton( self.src_ip )
  dest_addr    = socket.inet_aton( self.dst_ip )
  placeholder  = 0
  protocol     = socket.IPPROTO_TCP
  tcp_len      = len(self.raw) + len(self.data)
 
  psh = struct.pack('!4s4sBBH' , 
   src_addr ,    # Source Address  
   dest_addr ,   # Destination Address 
   placeholder , # Placeholder
   protocol ,    # Protocol 
   tcp_len       # Length of pseudo + Demo TCP header + Data 
   )

  psh = psh + self.raw + self.data

  self.tcp_chksum = self.chksum(psh) # call CheckSum calculation function
  
  self.reassemble_tcp_feilds()       # finally, reassemble all peice of information
  
  return 



Step 5

Algorithms to Calculate The Checksum of TCP header Packet. For Details check it here


 def chksum(self, msg):
  s = 0  # Binary Sum

  # loop taking 2 characters at a time
  for i in range(0, len(msg), 2):

   a = ord(msg[i]) 
   b = ord(msg[i+1])
   s = s + (a+(b << 8))
   
  
  # One's Complement
  s = s + (s >> 16)
  s = ~s & 0xffff
  return s


Step 6

After finding the correct checksum value of the pseudo header, it's time to again reassemble all piece of information into a binary packet structure to make a valid TCP packet. Of course, below function is responsible for it.

 def reassemble_tcp_feilds(self):
  self.raw = struct.pack('!HHLLBBH', 
   self.tcp_src, 
   self.tcp_dst, 
   self.tcp_seq, 
   self.tcp_ack_seq, 
   self.tcp_hdr_len, 
   self.tcp_flags , 
   self.tcp_wdw
   )+
  struct.pack("H", 
   self.tcp_chksum
   )+
  struct.pack('!H', 
   self.tcp_urg_ptr
   )
  return



Finally

Final Preview To Understand Actually How Our Class Object Code looks like


#!/usr/bin/python
import socket
import struct


class TCPPacket:
 def __init__(self, dport = 80, sport = 65535, dst='127.0.0.1', src='192.168.1.101', data = 'Nothing'):
  self.dport = dport
  self.sport = sport
  self.src_ip = src
  self.dst_ip = dst
  self.data   = data
  self.raw = None
  self.create_tcp_feilds()

 def assemble_tcp_feilds(self):
  self.raw = struct.pack('!HHLLBBHHH', # Data Structure Representation
   self.tcp_src,   # Source IP
   self.tcp_dst,    # Destination IP
   self.tcp_seq,    # Sequence
   self.tcp_ack_seq,  # Acknownlegment Sequence
   self.tcp_hdr_len,   # Header Length
   self.tcp_flags ,    # TCP Flags
   self.tcp_wdw,   # TCP Windows
   self.tcp_chksum,  # TCP cheksum
   self.tcp_urg_ptr # TCP Urgent Pointer
   )

  self.calculate_chksum() # Call Calculate CheckSum
  return


 def reassemble_tcp_feilds(self):
  self.raw = struct.pack('!HHLLBBH', 
   self.tcp_src, 
   self.tcp_dst, 
   self.tcp_seq, 
   self.tcp_ack_seq, 
   self.tcp_hdr_len, 
   self.tcp_flags , 
   self.tcp_wdw
   )+
  struct.pack("H", 
   self.tcp_chksum
   )+
  struct.pack('!H', 
   self.tcp_urg_ptr
   )
  return

 def calculate_chksum(self):
  src_addr     = socket.inet_aton( self.src_ip )
  dest_addr    = socket.inet_aton( self.dst_ip )
  placeholder  = 0
  protocol     = socket.IPPROTO_TCP
  tcp_len      = len(self.raw) + len(self.data)
 
  psh = struct.pack('!4s4sBBH' , 
   src_addr , 
   dest_addr , 
   placeholder , 
   protocol , 
   tcp_len
   )

  psh = psh + self.raw + self.data

  self.tcp_chksum = self.chksum(psh)
  
  self.reassemble_tcp_feilds()
  
  return 


 def chksum(self, msg):
  s = 0  # Binary Sum

  # loop taking 2 characters at a time
  for i in range(0, len(msg), 2):

   a = ord(msg[i]) 
   b = ord(msg[i+1])
   s = s + (a+(b << 8))
   
  
  # One's Complement
  s = s + (s >> 16)
  s = ~s & 0xffff
  return s

 def create_tcp_feilds(self):

  # ---- [ Source Port ]
  self.tcp_src = self.sport

  # ---- [ Destination Port ]
  self.tcp_dst = self.dport

  # ---- [ TCP Sequence Number]
  self.tcp_seq = 0

  # ---- [ TCP Acknowledgement Number]
  self.tcp_ack_seq = 0

  # ---- [ Header Length ]
  self.tcp_hdr_len = 80

  # ---- [ TCP Flags ]
  tcp_flags_rsv = (0 << 9)
  tcp_flags_noc = (0 << 8)
  tcp_flags_cwr = (0 << 7)
  tcp_flags_ecn = (0 << 6)
  tcp_flags_urg = (0 << 5)
  tcp_flags_ack = (0 << 4)
  tcp_flags_psh = (0 << 3)
  tcp_flags_rst = (0 << 2)
  tcp_flags_syn = (1 << 1)
  tcp_flags_fin = (0)

  self.tcp_flags = tcp_flags_rsv + tcp_flags_noc + tcp_flags_cwr + \
        tcp_flags_ecn + tcp_flags_urg + tcp_flags_ack + \
        tcp_flags_psh + tcp_flags_rst + tcp_flags_syn + tcp_flags_fin

  # ---- [ TCP Window Size ]
  self.tcp_wdw = socket.htons (5840)

  # ---- [ TCP CheckSum ]
  self.tcp_chksum = 0

  # ---- [ TCP Urgent Pointer ]
  self.tcp_urg_ptr = 0


  return




Run


To Run Above, Just Copy These Code In The End Of script.


if __name__=='__main__':
        # Create Raw Socket
 s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)

 tcp = TCPPacket()
 tcp.assemble_tcp_feilds()

 s.sendto(tcp.raw, ('127.0.0.1' , 0 ))
 

Run it With Sudo permission.

In Linux:

:~# sudo script/name/path.py


I hope you enjoyed this tutorial.
for any suggestion or query
comment below.


have a nice day.

Share this

Related Posts

Previous
Next Post »

10 comments

Write comments
27 December 2017 at 21:16 delete

I hope you all enjoying my tutorials.. 😎😎😎😎

Reply
avatar
28 April 2018 at 16:25 delete

Thank you so much. You explained this in great detail making a novice like me understand

Reply
avatar
22 July 2018 at 15:02 delete

Hello, thanks for the tutorial !

Could you explain me why you use "0 << 1" for tcp flags ? I don't understand what << does, it says it shifts left the left number by the right number, but what does it do exactly ? Why do you need it here ?
Also the socket.htons, does it give the variable a given size in bits ?
I've never used the struct module before, could you do a tutorial on it please ?
I'm curious about the pseudo header concept. You only use some fields of the original TCP header in the pseudo tcp header. Is pseudo header described in a RFC ?

Anyway thanks for your tutorial, it helps me understand a little better how it works.

Reply
avatar
22 July 2018 at 15:52 delete

Also, i have an error using Python 3
a = msg[i]
b = msg[i+1]
it says that i is out of range which makes sense, but i'm not sure how to fixt it ? Should I check if the value of i is greater than len(msg) and if so do nothing ?

Reply
avatar
25 July 2018 at 12:20 delete

Friend, Pay Attention In below Example.

For Example, As we can see in above codes.. This is a Small Piece Of Code.
and Lets Assume That

# ---- [ TCP Flags ]
tcp_flags_rsv = (a << 9) = In Binary Bytes = a000000000
tcp_flags_noc = (b << 8) = In Binary Bytes = b00000000
tcp_flags_cwr = (c << 7) = In Binary Bytes = c0000000
tcp_flags_ecn = (d << 6) = In Binary Bytes = d000000
tcp_flags_urg = (e << 5) = In Binary Bytes = e00000
tcp_flags_ack = (f << 4) = In Binary Bytes = f0000
tcp_flags_psh = (g << 3) = In Binary Bytes = g000
tcp_flags_rst = (h << 2) = In Binary Bytes = h00
tcp_flags_syn = (i << 1) = In Binary Bytes = i0
tcp_flags_fin = (j) = In Binary Bytes = j


SUM OF ALL Binary Bytes = abcdefghij

Reply
avatar
25 July 2018 at 16:47 delete

Hi !

Thanks for your answer, I have another question related to this.
if
bits = 101011
bits << 3 # = 101011000
right ?

and
bits = 101011
bits >> 3 # = 000101011
is it right ?

Reply
avatar
Anonymous
26 July 2018 at 02:38 delete

Hi. In your method checksum(...), what if the size of the message is odd? In the for loop, msg[i+1] goes out of bounds when the message size if odd.

Reply
avatar
26 July 2018 at 06:32 delete

Friend,
I am sorry, But I forget that much details about this project but I think may be we have to use Padding like A Free Space To Make it Even because I Never Encounter Any Odd Size Packet In Wireshark. To Calculate Correct IP checksum, Below Codes Are Important.

a = ord(msg[i])
b = ord(msg[i+1])
s = s + (a+(b << 8))

Check this link. Because I wrote these code after reading this article. https://tools.ietf.org/html/rfc1071

Regard
SSB

Reply
avatar
26 July 2018 at 06:36 delete


In [16]: bits = 35

In [17]: print "Binary : ", bin(bits)
Binary : 0b100011

In [18]: print "Binary : ", bin( bits >> 3)
Binary : 0b100

In [19]: print "Binary : ", bin(bits << 3)
Binary : 0b100011000

In [20]:

Reply
avatar