Usr6

Raw socket programming in python (Linux)

Raw sockets allow a program or application to provide custom headers for the specific protocol(tcp ip) which are otherwise provided by the kernel/os network stack. In more simple terms its for adding custom headers instead of headers provided by the underlying operating system.

 

Raw socket support is available natively in the socket api in linux. This is different from windows where it is absent (it became available in windows 2000/xp/xp sp1 but was removed later). Although raw sockets dont find much use in common networking applications, they are used widely in applications related to network security.

In this article we are going to create raw tcp/ip packets. For this we need to know how to make proper ip header and tcp headers. A packet = Ip header + Tcp header + data.

So lets have a look at the structures.

Ip header

According to Please login or register to see this link.

0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |Version|  IHL  |Type of Service|          Total Length         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Identification        |Flags|      Fragment Offset    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Time to Live |    Protocol   |         Header Checksum       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                       Source Address                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Destination Address                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Every single number is 1 bit. So for example the Version field is 4 bit. The header must be constructed exactly like shown.

TCP header

Next comes the TCP header. According to Please login or register to see this link.

0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          Source Port          |       Destination Port        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        Sequence Number                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Acknowledgment Number                      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Data |           |U|A|P|R|S|F|                               |
   | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
   |       |           |G|K|H|T|N|N|                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Checksum            |         Urgent Pointer        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             data                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

 

Create a raw socket

Raw socket can be created in python like this

#create a raw socket
try:
	s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
except socket.error , msg:
	print 'Socket could not be created. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
	sys.exit()

To create raw socket, the program must have root privileges on the system. For example on ubuntu run the program with sudo. The above example creates a raw socket of type IPPROTO_RAW which is a raw IP packet. Means that we provide everything including the ip header.

Once the socket is created, next thing is to create and construct the packet that is to be send out. C like structures are not available in python, therefore the functions called pack and unpack have to be used to create the packet in the structure specified above.

So first, lets make the ip header

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
source_ip = '192.168.1.101'
dest_ip = '192.168.1.1' # or socket.gethostbyname('www.google.com')
 
# ip header fields
ip_ihl = 5
ip_ver = 4
ip_tos = 0
ip_tot_len = 0  # kernel will fill the correct total length
ip_id = 54321   #Id of this packet
ip_frag_off = 0
ip_ttl = 255
ip_proto = socket.IPPROTO_TCP
ip_check = 0    # kernel will fill the correct checksum
ip_saddr = socket.inet_aton ( source_ip )   #Spoof the source ip address if you want to
ip_daddr = socket.inet_aton ( dest_ip )
 
ip_ihl_ver = (version << 4) + ihl
 
# the ! in the pack format string means network order
ip_header = pack('!BBHHHBBH4s4s' , ip_ihl_ver, ip_tos, ip_tot_len, ip_id, ip_frag_off, ip_ttl, ip_proto, ip_check, ip_saddr, ip_daddr)

Now ip_header has the data for the ip header. Now the usage of pack function, it packs some values has bytes, some as 16bit fields and some as 32 bit fields.

Next comes the tcp header

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# tcp header fields
tcp_source = 1234   # source port
tcp_dest = 80   # destination port
tcp_seq = 454
tcp_ack_seq = 0
tcp_doff = 5    #4 bit field, size of tcp header, 5 * 4 = 20 bytes
#tcp flags
tcp_fin = 0
tcp_syn = 1
tcp_rst = 0
tcp_psh = 0
tcp_ack = 0
tcp_urg = 0
tcp_window = socket.htons (5840)    #   maximum allowed window size
tcp_check = 0
tcp_urg_ptr = 0
 
tcp_offset_res = (tcp_doff << 4) + 0
tcp_flags = tcp_fin + (tcp_syn << 1) + (tcp_rst << 2) + (tcp_psh <<3) + (tcp_ack << 4) + (tcp_urg << 5)
 
# the ! in the pack format string means network order
tcp_header = pack('!HHLLBBHHH' , tcp_source, tcp_dest, tcp_seq, tcp_ack_seq, tcp_offset_res, tcp_flags,  tcp_window, tcp_check, tcp_urg_ptr)

The construction of the tcp header is similar to the ip header. The tcp header has a field called checksum which needs to be filled in correctly. A pseudo header is constructed to compute the checksum. The checksum is calculated over the tcp header along with the data. Checksum is necessary to detect errors in the transmission on the receiver side.

Code

Here is the full code to send a raw packet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
'''
    Raw sockets on Linux
     
    Silver Moon (m00n.silv3r@gmail.com)
'''
 
# some imports
import socket, sys
from struct import *
 
# checksum functions needed for calculation checksum
def checksum(msg):
    s = 0
     
    # loop taking 2 characters at a time
    for i in range(0, len(msg), 2):
        w = ord(msg) + (ord(msg[i+1]) << 8 )
        s = s + w
     
    s = (s>>16) + (s & 0xffff);
    s = s + (s >> 16);
     
    #complement and mask to 4 byte short
    s = ~s & 0xffff
     
    return s
 
#create a raw socket
try:
    s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
except socket.error , msg:
    print 'Socket could not be created. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
    sys.exit()
 
# tell kernel not to put in headers, since we are providing it, when using IPPROTO_RAW this is not necessary
# s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
     
# now start constructing the packet
packet = '';
 
source_ip = '192.168.1.101'
dest_ip = '192.168.1.1' # or socket.gethostbyname('www.google.com')
 
# ip header fields
ip_ihl = 5
ip_ver = 4
ip_tos = 0
ip_tot_len = 0  # kernel will fill the correct total length
ip_id = 54321   #Id of this packet
ip_frag_off = 0
ip_ttl = 255
ip_proto = socket.IPPROTO_TCP
ip_check = 0    # kernel will fill the correct checksum
ip_saddr = socket.inet_aton ( source_ip )   #Spoof the source ip address if you want to
ip_daddr = socket.inet_aton ( dest_ip )
 
ip_ihl_ver = (ip_ver << 4) + ip_ihl
 
# the ! in the pack format string means network order
ip_header = pack('!BBHHHBBH4s4s' , ip_ihl_ver, ip_tos, ip_tot_len, ip_id, ip_frag_off, ip_ttl, ip_proto, ip_check, ip_saddr, ip_daddr)
 
# tcp header fields
tcp_source = 1234   # source port
tcp_dest = 80   # destination port
tcp_seq = 454
tcp_ack_seq = 0
tcp_doff = 5    #4 bit field, size of tcp header, 5 * 4 = 20 bytes
#tcp flags
tcp_fin = 0
tcp_syn = 1
tcp_rst = 0
tcp_psh = 0
tcp_ack = 0
tcp_urg = 0
tcp_window = socket.htons (5840)    #   maximum allowed window size
tcp_check = 0
tcp_urg_ptr = 0
 
tcp_offset_res = (tcp_doff << 4) + 0
tcp_flags = tcp_fin + (tcp_syn << 1) + (tcp_rst << 2) + (tcp_psh <<3) + (tcp_ack << 4) + (tcp_urg << 5)
 
# the ! in the pack format string means network order
tcp_header = pack('!HHLLBBHHH' , tcp_source, tcp_dest, tcp_seq, tcp_ack_seq, tcp_offset_res, tcp_flags,  tcp_window, tcp_check, tcp_urg_ptr)
 
user_data = 'Hello, how are you'
 
# pseudo header fields
source_address = socket.inet_aton( source_ip )
dest_address = socket.inet_aton(dest_ip)
placeholder = 0
protocol = socket.IPPROTO_TCP
tcp_length = len(tcp_header) + len(user_data)
 
psh = pack('!4s4sBBH' , source_address , dest_address , placeholder , protocol , tcp_length);
psh = psh + tcp_header + user_data;
 
tcp_check = checksum(psh)
#print tcp_checksum
 
# make the tcp header again and fill the correct checksum - remember checksum is NOT in network byte order
tcp_header = pack('!HHLLBBH' , tcp_source, tcp_dest, tcp_seq, tcp_ack_seq, tcp_offset_res, tcp_flags,  tcp_window) + pack('H' , tcp_check) + pack('!H' , tcp_urg_ptr)
 
# final full packet - syn packets dont have any data
packet = ip_header + tcp_header + user_data
 
#Send the packet finally - the port specified has no effect
s.sendto(packet, (dest_ip , 0 ))    # put this in a loop if you want to flood the target

Run the above program from the terminal and check the network traffic using a packet sniffer like wireshark. It should show the packet.

Raw sockets find application in the field of network security. The above example can be used to code a tcp syn flood program. Syn flood programs are used in Dos attacks. Raw sockets are also used to code packet sniffers, port scanners etc.

 

sursa: Please login or register to see this link.

4

Share this post


Link to post
Share on other sites

Ceva mai simplu decat in C, dar nu e mare diferenta. 

1

Share this post


Link to post
Share on other sites
4 hours ago, Nytro said:

Ceva mai simplu decat in C, dar nu e mare diferenta. 

 

Fmm pointeri. God bless Python. Numa' faptu' ca nu vad * ma face sa am o erectie :))

2

Share this post


Link to post
Share on other sites

Interesant articol. Util cand nu ai acces la pcap si scapy.

 

Off topic: Heretic!

1 minute ago, MrGrj said:

 

Fmm pointeri. God bless Python. Numa' faptu' ca nu vad * ma face sa am o erectie :))

0

Share this post


Link to post
Share on other sites
37 minutes ago, u0m3 said:

Interesant articol. Util cand nu ai acces la pcap si scapy.

 

Off topic: Heretic!

 

Si access 'root'. Ceea ce presupune faptul ca poti instala pcap, scapy si tot ce doresti. Nu poti face raw si altera pachetele fara uid 0. Tot din motivul asta si banalul bing are bit suid setat.

Si python este limbaj de programare pentru elevi. :))))

 

-- Haterul de serviciu

2

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Similar Content

    • By Adln
      Salut,
       
      Tocmai am insalat Kali pe un stick usb și am observat că stick-ul e partiționat automat de către pc.
       
      Prima oară aveam 4 partiții Please login or register to see this link.  ..
      .. după care 5 partiții Please login or register to see this link.
       
      De ce se întâmplă asta ? Trebuie să le formatez după fiecare reboot ?
    • By gigiRoman
      Nullege is a search engine for Python source code. It helps you find working samples for Python libraries from production-quality open source projects.
      Unlike generic search engines, Nullege really understands Python and knows
      class InspectionFrame(wx.Frame):
          def SaveSettings(self, config):
              w, h = self.GetSize()
      is a sample for wx.Frame.GetSize(). It also tries to bring you more information in the first search result page, so you can find the right example with fewer clicks.
      Nullege is growing every day. If you can't find a sample for a library, or have ideas or feature requests, or just want to let us know that Nullege is useful (or not), please send us a mail, or click the 'feedback' button on the right.
      Please login or register to see this link.
      Please login or register to see this link.
    • By tinderboy
      Salut,
       
      Cumpar serviciile unui programator (python) pentru cateva proiecte "educationale". Plata se face prin BTC pe ora sau proiect.
      Detalii in privat sau pe jabber:  tinderboy@jabber.ru.
       
      PS: in cazul in care am postat unde nu trebuia, rog adminul sa mute topicul in categoria potrivita.
    • By vatman32
      Neata.
       
      address = 0x0018FB54 address = address + 0x14 address = address + 0x0 address = address + 0x7 ReadProcessMemory(processHandle, address, buffer, bufferSize, byref(bytesRead))  
      Se rupe filmul la acel "0x0" , prin urmare nu reusesc sa completez pointerul. Am luat la puricat documentatia python cat mi-a permis experienta pana in prezent, am rupt stackoverflow, am cautat si pe rst si nu gasesc un exemplu viabil sa accesez un amarat de pointer.
       
      Am invartit variabila aia de am innebunit, de ieri ma chinui intruna. Am luat cateva snipetturi de cod C++ si le-am transcris in python insa nu faceau obiectul problemei prezentate mai sus, ci ma aducea intr-un punct in care am mai fost, sa inaintez cu 2-3 offset-uri asta daca vreun offset nu echivala cu decimal mai mare de 99 (de ex am avut offset +444 (1BCh) si iar s-a rupt filmul ca la 0x0, nu schimba cu nimic rezultatul final oricate offset-uri ii mai adaugam dupa acel +444.
       
      Provocarea principala este ca vreau sa pot manevra un proces la fel de usor si rapid prin cod Python nu C++ (am fix pe creier) si inafara de impedimente de astea stupide nu am avut nici o dilema pana in prezent care sa ma retina mai mult de 6-7 ore pana sa gasesc o rezolvare.
       
      Sistem de operare: Windows 7 x64
      Aplicatiile pe care exersez: x32
       
      Multumesc anticipat.
    • By ionutbu
      Buna, am programat un comment și email grabber in Python, sper sa va placa
       
      Aici e link-ul: Please login or register to see this link.
       
      Daca ma puteti ajuta cu un invite la un site invite only unde gasesc torenturi va rog sa imi lasati mesaj  multumesc