Windows和Linux上的包嗅探:
#!/usr/bin/python import socket import os #监听的主机 host = "10.10.10.160" #创建原始套接字,然后绑定在公开接口上 if os.name == "nt": socket_protocol = socket.IPPROTO_IP else: socket_protocol = socket.IPPROTO_ICMP sniffer = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket_protocol) sniffer.bind((host,0)) #设置在捕获的数据包中包含IP头 sniffer.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1) #在Windows平台上,我们需要设置IOCTL以启动混杂模式 if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON) #读取单个数据包 print sniffer.recvfrom(65565) #在Windows平台上关闭混杂模式 if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)
运行结果:
解码IP层:
#!/usr/bin/python #coding=utf-8 import socket import os import struct from ctypes import * #监听的主机 host = "10.10.10.160" #IP头定义 class IP(Structure): """docstring for IP""" _fields_ = [ ("ihl", c_ubyte, 4), ("version", c_ubyte, 4), ("tos", c_ubyte), ("len", c_ushort), ("id", c_ushort), ("offset", c_ushort), ("ttl", c_ubyte), ("protocol_num", c_ubyte), ("sum", c_ushort), ("src", c_ulong), ("dst", c_ulong) ] def __new__(self,socket_buffer=None): return self.from_buffer_copy(socket_buffer) def __init__(self, socket_buffer=None): #协议字段与协议名称对应 self.protocol_map = {1:"ICMP",6:"TCP",17:"UDP"} #可读性更强的IP地址 self.src_address = socket.inet_ntoa(struct.pack("<L",self.src)) self.dst_address = socket.inet_ntoa(struct.pack("<L",self.dst)) #协议类型 try: self.protocol = self.protocol_map[self.protocol_num] except: self.protocol = str(self.protocol_num) #下面的代码类似于之前的例子 if os.name == "nt": socket_protocol = socket.IPPROTO_IP else: socket_protocol = socket.IPPROTO_ICMP sniffer = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket_protocol) sniffer.bind((host,0)) sniffer.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1) if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON) try: while True: #读取数据包 raw_buffer = sniffer.recvfrom(65565)[0] #将缓冲区的前20个字节按IP头进行解析 ip_header = IP(raw_buffer[0:20]) #输出协议和通信双方IP地址 print "Protocol : %s %s -> %s"%(ip_header.protocol,ip_header.src_address,ip_header.dst_address) #处理CTRL-C except KeyboardInterrupt: #如果运行在Windows上,关闭混杂模式 if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)
运行结果:
Win10上用户有管理员权限执行cmd所以会报错:
Kali下运行会出错,主要是因为32位与64位之间的一些问题:
解决方案:http://stackoverflow.com/questions/29306747/python-sniffing-from-black-hat-python-book
改进的可在Kali中运行的代码:
#!/usr/bin/python import socket import os import struct from ctypes import * #监听的主机 host = "10.10.10.160" #IP头定义 class IP(Structure): """docstring for IP""" _fields_ = [ ("ihl", c_ubyte, 4), ("version", c_ubyte, 4), ("tos", c_ubyte), ("len", c_ushort), ("id", c_ushort), ("offset", c_ushort), ("ttl", c_ubyte), ("protocol_num", c_ubyte), ("sum", c_ushort), ("src", c_uint32), ("dst", c_uint32) ] def __new__(self,socket_buffer=None): return self.from_buffer_copy(socket_buffer) def __init__(self, socket_buffer=None): #协议字段与协议名称对应 self.protocol_map = {1:"ICMP",6:"TCP",17:"UDP"} #可读性更强的IP地址 self.src_address = socket.inet_ntoa(struct.pack("@I",self.src)) self.dst_address = socket.inet_ntoa(struct.pack("@I",self.dst)) #协议类型 try: self.protocol = self.protocol_map[self.protocol_num] except: self.protocol = str(self.protocol_num) #下面的代码类似于之前的例子 if os.name == "nt": socket_protocol = socket.IPPROTO_IP else: socket_protocol = socket.IPPROTO_ICMP sniffer = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket_protocol) sniffer.bind((host,0)) sniffer.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1) if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON) try: while True: #读取数据包 raw_buffer = sniffer.recvfrom(65565)[0] #将缓冲区的前20个字节按IP头进行解析 ip_header = IP(raw_buffer[0:20]) #输出协议和通信双方IP地址 print "Protocol : %s %s -> %s"%(ip_header.protocol,ip_header.src_address,ip_header.dst_address) #处理CTRL-C except KeyboardInterrupt: #如果运行在Windows上,关闭混杂模式 if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)
运行结果:
解码ICMP:
#!/usr/bin/python #coding=utf-8 import socket import os import struct from ctypes import * host = "10.10.10.160" class IP(Structure): """docstring for IP""" _fields_ = [ ("ihl", c_ubyte, 4), ("version", c_ubyte, 4), ("tos", c_ubyte), ("len", c_ushort), ("id", c_ushort), ("offset", c_ushort), ("ttl", c_ubyte), ("protocol_num", c_ubyte), ("sum", c_ushort), ("src", c_ulong), ("dst", c_ulong) ] def __new__(self,socket_buffer=None): return self.from_buffer_copy(socket_buffer) def __init__(self, socket_buffer=None): self.protocol_map = {1:"ICMP",6:"TCP",17:"UDP"} self.src_address = socket.inet_ntoa(struct.pack("<L",self.src)) self.dst_address = socket.inet_ntoa(struct.pack("<L",self.dst)) try: self.protocol = self.protocol_map[self.protocol_num] except: self.protocol = str(self.protocol_num) class ICMP(Structure): """docstring for ICMP""" _fields_ = [ ("type", c_ubyte), ("code", c_ubyte), ("checksum", c_ushort), ("unused", c_ushort), ("next_hop_mtu", c_ushort) ] def __new__(self,socket_buffer): return self.from_buffer_copy(socket_buffer) def __new__(self,socket_buffer): pass if os.name == "nt": socket_protocol = socket.IPPROTO_IP else: socket_protocol = socket.IPPROTO_ICMP sniffer = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket_protocol) sniffer.bind((host,0)) sniffer.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1) if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON) try: while True: raw_buffer = sniffer.recvfrom(65565)[0] ip_header = IP(raw_buffer[0:20]) print "Protocol : %s %s -> %s"%(ip_header.protocol,ip_header.src_address,ip_header.dst_address) #如果为ICMP,进行处理 if ip_header.protocol == "ICMP": #计算ICMP包的起始位置 offset = ip_header.ihl*4 buf = raw_buffer[offset:offset + sizeof(ICMP)] #解析ICMP数据 icmp_header = ICMP(buf) print "ICMP -> Type : %d Code : %d"%(icmp_header.type,icmp_header.code) except KeyboardInterrupt: if os.name == "nt": sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)
但是结果并不能正常解析ICMP,排查的结果是代码中变量buf为None:
完犊子....