4 minutes
Custom Packet Sniffer
Have you ever wanted to create your own packet sniffer? Here is the code below on how that is possible!
#!/usr/bin/python
import socket
import os
import binascii
import struct
# Examples were obtained from http://www.bitforestinfo.com/2017/01/how-to-write-simple-packet-sniffer.htm
# and https://www.binarytides.com/python-packet-sniffer-code-linux/
# used for formating MAC address
def eth_addr(a):
b = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" % (ord(a[0]), ord(a[1]), ord(a[2]), ord(a[3]), ord(a[4]), ord(a[5]))
return b
# the script is designed to work on linux operating system with python 2.
# windows implementation was being problamatic with the socket implementation
if os.name == "nt":
host = socket.gethostbyname(socket.gethostname())
print('IP: {}'.format(host))
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
s.bind((host, 0))
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
else:
# PF_PACKET used for linux implementation. socket.ntohs(0x0800) used to obtain IPV4
s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0800))
# Continue as long as packets are being recieved
while True:
packet = s.recvfrom(65565)
packet = packet[0]
# Prints out the packet content as hex bytes
print("\n===>> [+] ------------ Packet ----------- [+]")
print('Packet : ' + binascii.hexlify(packet))
# parse ethernet header
eth_length = 14
eth_header = packet[:eth_length]
eth = struct.unpack('!6s6sH', eth_header)
eth_protocol = socket.ntohs(eth[2])
print("\n===>> [+] ------------ Ethernet Header ------------[+]")
print(
"Destination MAC : " + eth_addr(packet[0:6]) + ' Source MAC : ' + eth_addr(packet[6:12]) + ' Protocol : ' + str(
eth_protocol))
# ip header starts at 14 and goes to 34. These bytes contain the IP Header Information
ip_header = packet[eth_length:20 + eth_length]
# Struct used to unpack the bytes and oder them properly. Example obtained from (http://www.bitforestinfo.com/2017/01/how-to-write-simple-packet-sniffer.html)
iph = struct.unpack('!BBHHHBBH4s4s', ip_header)
version_ihl = iph[0]
version = version_ihl >> 4
ihl = version_ihl & 0xF
iph_length = ihl * 4
ttl = iph[5]
protocol = iph[6]
s_addr = socket.inet_ntoa(iph[8])
d_addr = socket.inet_ntoa(iph[9])
print("\n===>> [+] ------------ IP Header ------------[+]")
print('Version : ' + str(version) + ' IP Header Length : ' + str(ihl) + ' TTL : ' + str(ttl) + ' Protocol : ' + str(
protocol) + ' Source Address : ' + str(s_addr) + ' Destination Address : ' + str(d_addr))
# TCP protocol
if protocol == 6:
t = iph_length + eth_length
# TCP Header bytes going from 34 to 54
tcp_header = packet[t:t + 20]
# Struct used to unpack the bytes and oder them properly. Example obtained from (http://www.bitforestinfo.com/2017/01/how-to-write-simple-packet-sniffer.html)
tcph = struct.unpack('!HHLLBBHHH', tcp_header)
source_port = tcph[0]
dest_port = tcph[1]
sequence = tcph[2]
acknowledgement = tcph[3]
doff_reserved = tcph[4]
tcph_length = doff_reserved >> 4
print("\n===>> [+] ------------ TCP Header ----------- [+]")
print('Source Port : ' + str(source_port) + ' Dest Port : ' + str(dest_port) + ' Sequence Number : ' + str(
sequence) + ' Acknowledgement : ' + str(acknowledgement) + ' TCP header length : ' + str(tcph_length))
h_size = eth_length + iph_length + tcph_length * 4
data_size = len(packet) - h_size
# get data from the packet by going to the end of the header information
data = packet[h_size:]
# Display the data from the packet in hex form
print("\n===>> [+] ------------ Data ----------- [+]")
print('Data : ' + binascii.hexlify(data))
# UDP packets
elif protocol == 17:
u = iph_length + eth_length
udph_length = 8
# UDP Header bytes going from 34 to 42
udp_header = packet[u:u + 8]
# Struct used to unpack the bytes and oder them properly. Example obtained from (http://www.bitforestinfo.com/2017/01/how-to-write-simple-packet-sniffer.html)
udph = struct.unpack('!HHHH', udp_header)
source_port = udph[0]
dest_port = udph[1]
length = udph[2]
checksum = udph[3]
print("\n===>> [+] ------------ UDP Header ----------- [+]")
print('Source Port : ' + str(source_port) + ' Dest Port : ' + str(dest_port) + ' Length : ' + str(
length) + ' Checksum : ' + str(checksum))
h_size = eth_length + iph_length + udph_length
data_size = len(packet) - h_size
# get data from the packet by going to the end of the header information
data = packet[h_size:]
# Display the data from the packet in hex form
print("\n===>> [+] ------------ Data ----------- [+]")
print('Data : ' + binascii.hexlify(data))
else:
print("Protocol type not supported.")
Example screenshot of it in action: