1. Raw Socket Base
Provides a way to bypass the entire network stack traversal and deliver Ethernet frames directly to an application.
There are a number of ways to create raw sockets, such as Af_packet,pf_packet. Here you use Pf_packet, which is an option on a Linux system, and if it's a Windows or Mac system, you can use Af_packet.
1.1 Pf_socket
- Receive and send packets on the link layer to the application interface.
- All received packages contain a complete header and data section.
- All packets sent will be passed to the media without changes to the kernel.
- Supports the use of Berkley Packet filtering. (For more information, refer to: HTTP://HOWTOUNIX.INFO/MAN/FREEBSD/MAN4/BPF.4)
2. Create raw Socket2.1 Understanding Packet Header
For Ethernet frame Header and IP header format:
The head of the Ethernet frame has 14 bytes, the first 6 bytes are the destination MAC address, the last 6 bytes are the source MAC address, and the next 2 bytes are the type of the internal protocol, such as the type of IP protocol 0x0800
. The types of protocols can be viewed in a /usr/include/linux/if_ether.h
file (Linux system). In the first layer is IP and other network layer protocol, the IP layer contains TCP, UDP and other transport layer protocol, and then in the application layer protocol, such as HTTP, SSH and so on.
The bottom-most side of the figure is the head format of the IP, the most important part being the first 20 bytes.
2.2 Extracting binary data into a variable
- Use the unpack () function in the struct module.
- Returns the time tuple format. (For more detailed information on the tuple, refer to: Liaoche, the tuple part of Python)
- The first character indicates a byte order.
- The network byte order is usually a big-endian.
For example, enter Python under the terminal and do the following:
>>> Import struct
>>>
>>>
>>> struct.pack ("B", 1)
' \X01 '
>>> struct.pack ("H", 1)
' \x01\x00 '
>>> struct.pack (">h", 1)
' \X00\X01 '
>>> Struct.pack ("! H ", 1)
' \X00\X01 '
>>> Struct.pack ("! L ", 1)
' \X00\X00\X00\X01 '
>>> exit ()
2.3 Raw Socket sniffing
Main ideas:
Use the socket module.
Reads the received package.
Explain and analyze packages.
You can also send an answer
Linux to open the terminal, into the Python environment (raw_socket requires root permission, the input command is to enter the command sudo python
.) ), and then click on the following method:
[Email protected]:~/workspace/python$ sudo python
[sudo] password for jeanphorn:
Python 2.7.3 (Default, APR 20 2012, 22:44:07)
[GCC 4.6.3] on linux2
Type "Help", "copyright", "credits" or "license" for more information.
>>>
>>>
>>>
>>> Import Socket
>>> Import struct
>>> Import Binascii
>>>
>>>
>>> Rawsocket = socket.socket (socket. Pf_packet,socket. Sock_raw,socket.htons (0x0800))
>>>
>>> PKT = Rawsocket.recvfrom (2048)
>>> PKT
("\x08\x00" [Email protected]\x8f.\xd5\xc4\x08\x00e\x10\x004w\[email protected]\[email protected]\x06_\xf0\xc0\xa8 \x01_\xc0\xa8\x01\x0e\xf0u\x00\x16\xa9^i\x03\xe3\xa0v\xb4\x80\x10\x0f\xfegr\x00\x00\x01\x01\x08\n\x1e\xd3\x0f\ Xc7\x00\x00/\xb2 ", (' eth0 ', 2048, 0, 1, ' @l\x8f.\xd5\xc4 '))
>>> Ethernetheader = pkt[0][0:14]
>>>ethernetheader
"\x08\x00" [email protected]\x8f.\xd5\xc4\x08\x00]
>>> ETH_HDR = Struct.unpack ("!6s6s2s", Ethernetheader)
>>> ETH_HDR = Struct.unpack ("!6s6s2s", Ethernetheader)
>>> ETH_HDR
("\x08\x00 ' 5BY", ' @l\x8f.\xd5\xc4 ', ' \x08\x00 ')
>>> binascii.hexlify (eth_hdr[0])
' 080027354259 '
>>> binascii.hexlify (eth_hdr[1])
' 406c8f2ed5c4 '
>>> binascii.hexlify (eth_hdr[2])
' 0800 '
>>> Ipheader = pkt[0][14:34]
>>> PKT
("\x08\x00" [Email protected]\x8f.\xd5\xc4\x08\x00e\x10\x004w\[email protected]\[email protected]\x06_\xf0\xc0\xa8 \x01_\xc0\xa8\x01\x0e\xf0u\x00\x16\xa9^i\x03\xe3\xa0v\xb4\x80\x10\x0f\xfegr\x00\x00\x01\x01\x08\n\x1e\xd3\x0f\ Xc7\x00\x00/\xb2 ", (' eth0 ', 2048, 0, 1, ' @l\x8f.\xd5\xc4 '))
>>> IP_HDR = Struct.unpack ("!12s4s4s", Ipheader)
>>> IP_HDR
(' E\x10\x004w\[email protected]\[email protected]\x06_\xf0 ', ' \xc0\xa8\x01_ ', ' \xc0\xa8\x01\x0e ')
>>> Socket.inet_ntoa (ip_hdr[1])
' 192.168.1.95 '
>>> Socket.inet_ntoa (ip_hdr[2])
' 192.168.1.14 '
>>> Tcpheader = pkt[0][34:54]
>>> TCP_HDR = Struct.unpack ("! Hh16s ", Tcpheader)
>>> TCP_HDR
(61557, "\xa9^i\x03\xe3\xa0v\xb4\x80\x10\x0f\xfegr\x00\x00")
3. Complete Python code
Write the above code in a packetsniffer.py file and add it to the runtime sudo ./packetSniffer.py
.
#!/usr/bin/env python# _*_ Coding=utf-8 _*_Import socketimport Structimport binasciirawsocket = socket.socket (socket. Pf_packet,socket. Sock_Raw,socket.htons (0x0800)) PKT = Rawsocket.recvfrom (2048) Ethernetheader = pkt[0][0:14] #提取以太网帧头eth_hdr = Struct.unpack ("!6s6s2s", Ethernetheader) #6字节目的mac地址, 6-byte source MAC address, 2-byte protocol type binascii.hexlify (eth_hdr[ 0]) binascii.hexlify (eth_hdr[1]) binascii.hexlify (eth_hdr[2]) Ipheader = pkt[0][14:34] #提取IP协议头, does not contain the option and Padding fields. IP_HDR = Struct.unpack ("!12s4s4s", Ipheader) #! Mark the conversion network byte order, the first 12 bytes are version, head length, service type, total length, flags and other options, the following two four bytes are the source IP address and the destination IP address in turn. Print "Source IP address:" + soket.inet_ntoa (Ip_HDR[1]) print "Destination IP address:" + soket.inet_ntoa (Ip_HDR[2]) Tcpheader = pkt[0][34:54]TCP_HDR = Struct.unpack ("! Hh16s ", Tcpheader) print Tcp_hdr
Python uses raw sockets for Ethernet frame sniffing