-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpacketSniffer.py
107 lines (91 loc) · 4.35 KB
/
packetSniffer.py
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
import socket
import struct
import textwrap
# Unpack Ethernet frame
def ethernet_frame(data):
dest_mac, src_mac, proto = struct.unpack('! 6s 6s H', data[:14])
return get_mac_addr(dest_mac), get_mac_addr(src_mac), socket.htons(proto), data[14:]
# Return properly formatted MAC address (AA:BB:CC:DD:EE:FF)
def get_mac_addr(bytes_addr):
bytes_str = map('{:02x}'.format, bytes_addr)
return ':'.join(bytes_str).upper()
# Unpack IPv4 packet
def ipv4_packet(data):
version_header_length = data[0]
version = version_header_length >> 4
header_length = (version_header_length & 15) * 4
ttl, proto, src, target = struct.unpack('! 8x B B 2x 4s 4s', data[:20])
return version, header_length, ttl, proto, ipv4(src), ipv4(target), data[header_length:]
# Returns properly formatted IPv4 address
def ipv4(addr):
return '.'.join(map(str, addr))
# Unpack ICMP packet
def icmp_packet(data):
icmp_type, code, checksum = struct.unpack('! B B H', data[:4])
return icmp_type, code, checksum, data[4:]
# Unpack TCP segment
def tcp_segment(data):
(src_port, dest_port, sequence, acknowledgment, offset_reserved_flags) = struct.unpack('! H H L L H', data[:14])
offset = (offset_reserved_flags >> 12) * 4
flag_urg = (offset_reserved_flags & 32) >> 5
flag_ack = (offset_reserved_flags & 16) >> 4
flag_psh = (offset_reserved_flags & 8) >> 3
flag_rst = (offset_reserved_flags & 4) >> 2
flag_syn = (offset_reserved_flags & 2) >> 1
flag_fin = offset_reserved_flags & 1
return src_port, dest_port, sequence, acknowledgment, flag_urg, flag_ack, flag_psh, flag_rst, flag_syn, flag_fin, data[offset:]
# Unpack UDP segment
def udp_segment(data):
src_port, dest_port, size = struct.unpack('! H H 2x H', data[:8])
return src_port, dest_port, size, data[8:]
# Format multi-line data
def format_multi_line(prefix, string, size=80):
size -= len(prefix)
if isinstance(string, bytes):
string = ''.join(r'\x{:02x}'.format(byte) for byte in string)
if size % 2:
size -= 1
return '\n'.join([prefix + line for line in textwrap.wrap(string, size)])
def main():
# Create a raw socket
conn = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(3))
while True:
raw_data, addr = conn.recvfrom(65536)
dest_mac, src_mac, eth_proto, data = ethernet_frame(raw_data)
print('\nEthernet Frame:')
print(f'Destination: {dest_mac}, Source: {src_mac}, Protocol: {eth_proto}')
# IPv4
if eth_proto == 8:
(version, header_length, ttl, proto, src, target, data) = ipv4_packet(data)
print(f'\t- IPv4 Packet:')
print(f'\t\t- Version: {version}, Header Length: {header_length}, TTL: {ttl}')
print(f'\t\t- Protocol: {proto}, Source: {src}, Target: {target}')
# ICMP
if proto == 1:
icmp_type, code, checksum, data = icmp_packet(data)
print(f'\t- ICMP Packet:')
print(f'\t\t- Type: {icmp_type}, Code: {code}, Checksum: {checksum}')
print(f'\t\t- Data:')
print(format_multi_line('\t\t\t', data))
# TCP
elif proto == 6:
(src_port, dest_port, sequence, acknowledgment, flag_urg, flag_ack, flag_psh, flag_rst, flag_syn, flag_fin, data) = tcp_segment(data)
print(f'\t- TCP Segment:')
print(f'\t\t- Source Port: {src_port}, Destination Port: {dest_port}')
print(f'\t\t- Sequence: {sequence}, Acknowledgment: {acknowledgment}')
print(f'\t\t- Flags:')
print(f'\t\t\t- URG: {flag_urg}, ACK: {flag_ack}, PSH: {flag_psh}')
print(f'\t\t\t- RST: {flag_rst}, SYN: {flag_syn}, FIN: {flag_fin}')
print(f'\t\t- Data:')
print(format_multi_line('\t\t\t', data))
# UDP
elif proto == 17:
src_port, dest_port, length, data = udp_segment(data)
print(f'\t- UDP Segment:')
print(f'\t\t- Source Port: {src_port}, Destination Port: {dest_port}, Length: {length}')
# Other
else:
print(f'\t- Other IPv4 Data:')
print(format_multi_line('\t\t', data))
if __name__ == "__main__":
main()