├── README.md └── Packet-Sniffer.py /README.md: -------------------------------------------------------------------------------- 1 | # Python-Packet-Sniffer 2 | 3 | ## Overview 4 | 5 | Packet Sniffer created in Python 3. Allows you to monitor traffic running through local network. Allows the user to be able to view Source of the packets, Target host and the type of protocol used e.g. UDP/TCP. 6 | 7 | ## Requirement 8 | - Python 3.x 9 | - Privileged/Administrative Rights 10 | - Linux Operating System 11 | 12 | ## Suport 13 | - Suport IPv6 : ICMP ,UDP, TCP 14 | 15 | ## Can filter 16 | - That is possible filter the data from the follow packets: 17 | - TCP ( V4 and V6) 18 | - UDP ( V4 and V6) 19 | - ICMP( V4 and V6) 20 | 21 | ## Run 22 | -sudo python3 Packet-Sniffer.py 23 | -sudo python3 Packet-Sniffer.py UDP 24 | -sudo python3 Packet-Sniffer.py ICMP 25 | -sudo python3 Packet-Sniffer.py TCP 26 | -------------------------------------------------------------------------------- /Packet-Sniffer.py: -------------------------------------------------------------------------------- 1 | #! /usr/local/bin/python3.5 2 | 3 | import socket 4 | import struct 5 | import textwrap 6 | import binascii 7 | import struct 8 | import sys 9 | 10 | TAB_1 = '\t - ' 11 | TAB_2 = '\t\t - ' 12 | TAB_3 = '\t\t\t - ' 13 | TAB_4 = '\t\t\t\t - ' 14 | 15 | DATA_TAB_1 = '\t ' 16 | DATA_TAB_2 = '\t\t ' 17 | DATA_TAB_3 = '\t\t\t ' 18 | DATA_TAB_4 = '\t\t\t\t ' 19 | 20 | def main(): 21 | conn = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.ntohs(3)) 22 | 23 | filters = (["ICMP", 1, "ICMPv6"],["UDP", 17, "UDP"], ["TCP", 6, "TCP"]) 24 | filter = [] 25 | 26 | if len(sys.argv) == 2: 27 | print("This is the filter: ", sys.argv[1]) 28 | for f in filters: 29 | if sys .argv[1] == f[0]: 30 | filter = f 31 | 32 | 33 | 34 | while True: 35 | raw_data, addr = conn.recvfrom(65536) 36 | dest_mac, src_mac, eth_proto, data = ethernet_frame(raw_data) 37 | 38 | if eth_proto == 'IPV6': 39 | newPacket, nextProto = ipv6Header(data, filter) 40 | printPacketsV6(filter, nextProto, newPacket) 41 | 42 | elif eth_proto == 'IPV4': 43 | printPacketsV4(filter, data, raw_data) 44 | 45 | 46 | 47 | def printPacketsV4(filter, data, raw_data): 48 | (version, header_length, ttl, proto, src, target, data) = ipv4_Packet(data) 49 | 50 | # ICMP 51 | if proto == 1 and (len(filter) == 0 or filter[1] == 1): 52 | icmp_type, code, checksum, data = icmp_packet(data) 53 | print ("*******************ICMP***********************") 54 | print ("\tICMP type: %s" % (icmp_type)) 55 | print ("\tICMP code: %s" % (code)) 56 | print ("\tICMP checksum: %s" % (checksum)) 57 | 58 | # TCP 59 | elif proto == 6 and (len(filter) == 0 or filter[1] == 6): 60 | print("*******************TCPv4***********************") 61 | print('Version: {}\nHeader Length: {}\nTTL: {}'.format(version, header_length, ttl)) 62 | print('protocol: {}\nSource: {}\nTarget: {}'.format(proto, src, target)) 63 | src_port, dest_port, sequence, acknowledgment, flag_urg, flag_ack, flag_psh, flag_rst, flag_syn, flag_fin = struct.unpack( 64 | '! H H L L H H H H H H', raw_data[:24]) 65 | print('*****TCP Segment*****') 66 | print('Source Port: {}\nDestination Port: {}'.format(src_port, dest_port)) 67 | print('Sequence: {}\nAcknowledgment: {}'.format(sequence, acknowledgment)) 68 | print('*****Flags*****') 69 | print('URG: {}\nACK: {}\nPSH: {}'.format(flag_urg, flag_ack, flag_psh)) 70 | print('RST: {}\nSYN: {}\nFIN:{}'.format(flag_rst, flag_syn, flag_fin)) 71 | 72 | if len(data) > 0: 73 | # HTTP 74 | if src_port == 80 or dest_port == 80: 75 | print('*****HTTP Data*****') 76 | try: 77 | http = HTTP(data) 78 | http_info = str(http.data).split('\n') 79 | for line in http_info: 80 | print(str(line)) 81 | except: 82 | print(format_output_line("",data)) 83 | else: 84 | print('*****TCP Data*****') 85 | print(format_output_line("",data)) 86 | # UDP 87 | elif proto == 17 and (len(filter) == 0 or filter[1] == 17): 88 | print("*******************UDPv4***********************") 89 | print('Version: {}\nHeader Length: {}\nTTL: {}'.format(version, header_length, ttl)) 90 | print('protocol: {}\nSource: {}\nTarget: {}'.format(proto, src, target)) 91 | src_port, dest_port, length, data = udp_seg(data) 92 | print('*****UDP Segment*****') 93 | print('Source Port: {}\nDestination Port: {}\nLength: {}'.format(src_port, dest_port, length)) 94 | 95 | 96 | def printPacketsV6(filter, nextProto, newPacket): 97 | remainingPacket = "" 98 | 99 | if (nextProto == 'ICMPv6' and (len(filter) == 0 or filter[2] == "ICMPv6")): 100 | remainingPacket = icmpv6Header(newPacket) 101 | elif (nextProto == 'TCP' and (len(filter) == 0 or filter[2] == "TCP")): 102 | remainingPacket = tcpHeader(newPacket) 103 | elif (nextProto == 'UDP' and (len(filter) == 0 or filter[2] == "UDP")): 104 | remainingPacket = udpHeader(newPacket) 105 | 106 | return remainingPacket 107 | 108 | 109 | def tcpHeader(newPacket): 110 | # 2 unsigned short,2unsigned Int,4 unsigned short. 2byt+2byt+4byt+4byt+2byt+2byt+2byt+2byt==20byts 111 | packet = struct.unpack("!2H2I4H", newPacket[0:20]) 112 | srcPort = packet[0] 113 | dstPort = packet[1] 114 | sqncNum = packet[2] 115 | acknNum = packet[3] 116 | dataOffset = packet[4] >> 12 117 | reserved = (packet[4] >> 6) & 0x003F 118 | tcpFlags = packet[4] & 0x003F 119 | urgFlag = tcpFlags & 0x0020 120 | ackFlag = tcpFlags & 0x0010 121 | pushFlag = tcpFlags & 0x0008 122 | resetFlag = tcpFlags & 0x0004 123 | synFlag = tcpFlags & 0x0002 124 | finFlag = tcpFlags & 0x0001 125 | window = packet[5] 126 | checkSum = packet[6] 127 | urgPntr = packet[7] 128 | 129 | print ("*******************TCP***********************") 130 | print ("\tSource Port: "+str(srcPort) ) 131 | print ("\tDestination Port: "+str(dstPort) ) 132 | print ("\tSequence Number: "+str(sqncNum) ) 133 | print ("\tAck. Number: "+str(acknNum) ) 134 | print ("\tData Offset: "+str(dataOffset) ) 135 | print ("\tReserved: "+str(reserved) ) 136 | print ("\tTCP Flags: "+str(tcpFlags) ) 137 | 138 | if(urgFlag == 32): 139 | print ("\tUrgent Flag: Set") 140 | if(ackFlag == 16): 141 | print ("\tAck Flag: Set") 142 | if(pushFlag == 8): 143 | print ("\tPush Flag: Set") 144 | if(resetFlag == 4): 145 | print ("\tReset Flag: Set") 146 | if(synFlag == 2): 147 | print ("\tSyn Flag: Set") 148 | if(finFlag == True): 149 | print ("\tFin Flag: Set") 150 | 151 | print ("\tWindow: "+str(window)) 152 | print ("\tChecksum: "+str(checkSum)) 153 | print ("\tUrgent Pointer: "+str(urgPntr)) 154 | print (" ") 155 | 156 | packet = packet[20:] 157 | return packet 158 | 159 | 160 | def udpHeader(newPacket): 161 | packet = struct.unpack("!4H", newPacket[0:8]) 162 | srcPort = packet[0] 163 | dstPort = packet[1] 164 | lenght = packet[2] 165 | checkSum = packet[3] 166 | 167 | print ("*******************UDP***********************") 168 | print ("\tSource Port: "+str(srcPort)) 169 | print ("\tDestination Port: "+str(dstPort)) 170 | print ("\tLenght: "+str(lenght)) 171 | print ("\tChecksum: "+str(checkSum)) 172 | print (" ") 173 | 174 | packet = packet[8:] 175 | return packet 176 | 177 | 178 | def icmpv6Header(data): 179 | ipv6_icmp_type, ipv6_icmp_code, ipv6_icmp_chekcsum = struct.unpack( 180 | ">BBH", data[:4]) 181 | 182 | print ("*******************ICMPv6***********************") 183 | print ("\tICMPv6 type: %s" % (ipv6_icmp_type)) 184 | print ("\tICMPv6 code: %s" % (ipv6_icmp_code)) 185 | print ("\tICMPv6 checksum: %s" % (ipv6_icmp_chekcsum)) 186 | 187 | data = data[4:] 188 | return data 189 | 190 | 191 | def nextHeader(ipv6_next_header): 192 | if (ipv6_next_header == 6): 193 | ipv6_next_header = 'TCP' 194 | elif (ipv6_next_header == 17): 195 | ipv6_next_header = 'UDP' 196 | elif (ipv6_next_header == 43): 197 | ipv6_next_header = 'Routing' 198 | elif (ipv6_next_header == 1): 199 | ipv6_next_header = 'ICMP' 200 | elif (ipv6_next_header == 58): 201 | ipv6_next_header = 'ICMPv6' 202 | elif (ipv6_next_header == 44): 203 | ipv6_next_header = 'Fragment' 204 | elif (ipv6_next_header == 0): 205 | ipv6_next_header = 'HOPOPT' 206 | elif (ipv6_next_header == 60): 207 | ipv6_next_header = 'Destination' 208 | elif (ipv6_next_header == 51): 209 | ipv6_next_header = 'Authentication' 210 | elif (ipv6_next_header == 50): 211 | ipv6_next_header = 'Encapsuling' 212 | 213 | return ipv6_next_header 214 | 215 | 216 | def ipv6Header(data, filter): 217 | ipv6_first_word, ipv6_payload_legth, ipv6_next_header, ipv6_hoplimit = struct.unpack( 218 | ">IHBB", data[0:8]) 219 | ipv6_src_ip = socket.inet_ntop(socket.AF_INET6, data[8:24]) 220 | ipv6_dst_ip = socket.inet_ntop(socket.AF_INET6, data[24:40]) 221 | 222 | bin(ipv6_first_word) 223 | "{0:b}".format(ipv6_first_word) 224 | version = ipv6_first_word >> 28 225 | traffic_class = ipv6_first_word >> 16 226 | traffic_class = int(traffic_class) & 4095 227 | flow_label = int(ipv6_first_word) & 65535 228 | 229 | ipv6_next_header = nextHeader(ipv6_next_header) 230 | data = data[40:] 231 | 232 | return data, ipv6_next_header 233 | 234 | 235 | # Unpack Ethernet Frame 236 | def ethernet_frame(data): 237 | proto = "" 238 | IpHeader = struct.unpack("!6s6sH",data[0:14]) 239 | dstMac = binascii.hexlify(IpHeader[0]) 240 | srcMac = binascii.hexlify(IpHeader[1]) 241 | protoType = IpHeader[2] 242 | nextProto = hex(protoType) 243 | 244 | if (nextProto == '0x800'): 245 | proto = 'IPV4' 246 | elif (nextProto == '0x86dd'): 247 | proto = 'IPV6' 248 | 249 | data = data[14:] 250 | 251 | return dstMac, srcMac, proto, data 252 | 253 | # Format MAC Address 254 | def get_mac_addr(bytes_addr): 255 | bytes_str = map('{:02x}'.format, bytes_addr) 256 | mac_addr = ':'.join(bytes_str).upper() 257 | return mac_addr 258 | 259 | # Unpack IPv4 Packets Recieved 260 | def ipv4_Packet(data): 261 | version_header_len = data[0] 262 | version = version_header_len >> 4 263 | header_len = (version_header_len & 15) * 4 264 | ttl, proto, src, target = struct.unpack('! 8x B B 2x 4s 4s', data[:20]) 265 | return version, header_len, ttl, proto, ipv4(src), ipv4(target), data[header_len:] 266 | 267 | # Returns Formatted IP Address 268 | def ipv4(addr): 269 | return '.'.join(map(str, addr)) 270 | 271 | 272 | # Unpacks for any ICMP Packet 273 | def icmp_packet(data): 274 | icmp_type, code, checksum = struct.unpack('! B B H', data[:4]) 275 | return icmp_type, code, checksum, data[4:] 276 | 277 | # Unpacks for any TCP Packet 278 | def tcp_seg(data): 279 | (src_port, dest_port, sequence, acknowledgement, offset_reserved_flag) = struct.unpack('! H H L L H', data[:14]) 280 | offset = (offset_reserved_flag >> 12) * 4 281 | flag_urg = (offset_reserved_flag & 32) >> 5 282 | flag_ack = (offset_reserved_flag & 32) >> 4 283 | flag_psh = (offset_reserved_flag & 32) >> 3 284 | flag_rst = (offset_reserved_flag & 32) >> 2 285 | flag_syn = (offset_reserved_flag & 32) >> 1 286 | flag_fin = (offset_reserved_flag & 32) >> 1 287 | 288 | return src_port, dest_port, sequence, acknowledgement, flag_urg, flag_ack, flag_psh, flag_rst, flag_syn, flag_fin, data[offset:] 289 | 290 | 291 | # Unpacks for any UDP Packet 292 | def udp_seg(data): 293 | src_port, dest_port, size = struct.unpack('! H H 2x H', data[:8]) 294 | return src_port, dest_port, size, data[8:] 295 | 296 | # Formats the output line 297 | def format_output_line(prefix, string): 298 | size=80 299 | size -= len(prefix) 300 | if isinstance(string, bytes): 301 | string = ''.join(r'\x{:02x}'.format(byte) for byte in string) 302 | if size % 2: 303 | size-= 1 304 | return '\n'.join([prefix + line for line in textwrap.wrap(string, size)]) 305 | 306 | 307 | main() 308 | --------------------------------------------------------------------------------