先讨论pcap包的抓取
这里我们可以使用Wireshark
+Winpcap
组合进行抓取pcap包,但这里要注意的是这个组合不可以抓取回环包,如果要抓回环包可以使用Wireshark
+Npcap
这个组合。
Winpcap
与Npcap
在网上都是可以找到集成应用的,可以一键配置。
这里我在windows
环境下使用python
+pypcap
+dpkt
进行抓取分析。
首先要安装pypcap包,我是用pip install pypcap
命令下载失败,[这里是下载pypcap的链接](pypcap · PyPI )
pypcap 是一个对libpcap
C库进行封装和简化的面向对象的抓包工具库,可以非常方便的用于抓包和过滤,结合dpkt
解析库可以完成许多网络数据包的抓取和分析。也就是说pypcap是用c语言写成的。一开始,lipcap API库被设计成使用C和C++语言运行。但随着更多不用高级编程语言的出现,比如Perl、Python、Java、C#和Ruby等,lipcap被允许可以被封装成不同语言的库被调用。Libpcap可以在大部分的Unix操作系统下运行,同时也支持windows系统,也就是winpcap库。
这里我们需要Npcap
的支持,先将[Npcap](Npcap: Windows 数据包捕获库和驱动程序 (nmap.org) )下载安装,再下载Npcap SDK然后再将下载的pypcap解压到Npcap SDK的目录。并将Npcap SDK的文件名改为wpdpack放在python文件的include文件夹下。然后在文件夹里打开powershell。运行python setup.py install
这里遇到了一些问题error: Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++ Build Tools"
。要配置VSC++环境。待配置好之后在powershell窗口python setup.py build & python setup.py install
成功即可。
可以先调试下是否安装成功。
1 2 3 4 5 6 7 8 9 import pcapdevs = pcap.findalldevs() print (*devs, sep='\n' )pc = pcap.pcap(devs[3 ], promisc=True , immediate=True , timeout_ms=50 ) pc.setfilter('tcp port 80' ) for ptime, pdata in pc: print (ptime, pdata)
成功之后就可以使用了。
dpkt的安装pip install dpkt
用来解析获取的pcap包。
之后就是使用pypacp抓包了。先了解其中的主要函数。
先是findalldevs,它可以列出当前操作系统的所有网络接口pcap.findalldevs()
但是这个方法在windows下并不好操作,这里可以借用wireshark抓包获得接口。
再是pcap.pcap,pc = pcap.pcap(devs[3], promisc=True, immediate=True, timeout_ms=50)
以上代码定义了一个pcap对象,首个参数devs[3]
对应接口名,promisc
为真代表打开混杂模式,immediate
代表立即模式,启用将不缓存数据包,timeout_ms
代表接收数据包的超时时间
之后是setfilter函数,是用来设置数据包过滤器,比如只想抓http的包,那就通过setfilter(tcp port 80)
实现。
再就是最后的抓包
1 2 for ptime,pdata in pc: print (ptime,pdata)
上边的pcap.pcap对象pc是一个动态数据包,通过循环结构不断输出。
下边是一个简易的抓包工具
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 108 109 110 111 112 113 114 import pcapimport dpkt import getoptimport sysimport datetimeimport timeimport osimport platform if 'Windows' in platform.platform(): import winreg as wr IF_REG = r'SYSTEM\CurrentControlSet\Control\Network\{4d36e972-e325-11ce-bfc1-08002be10318}' def getInterfaceByName (name ): //根据接口名称,通过查找注册表信息获取pcap所需的接口设备信息,适用于Windows系统. '''Get guid of interface from regedit of windows system Args: name: interface name Returns: An valid guid value or None. Example: getInterfaceByName('eth0') ''' reg = wr.ConnectRegistry(None , wr.HKEY_LOCAL_MACHINE) reg_key = wr.OpenKey(reg, IF_REG) for i in range (wr.QueryInfoKey(reg_key)[0 ]): subkey_name = wr.EnumKey(reg_key, i) try : reg_subkey = wr.OpenKey(reg_key, subkey_name + r'\Connection' ) Name = wr.QueryValueEx(reg_subkey, 'Name' )[0 ] wr.CloseKey(reg_subkey) if Name == name: return r'\Device\NPF_' + subkey_name except FileNotFoundError as e: pass return None def mac_addr (mac ): return '%02x:%02x:%02x:%02x:%02x:%02x' %tuple (mac) def ip_addr (ip ): return '%d.%d.%d.%d' %tuple (ip) def captureData (iface ): pkt = pcap.pcap(iface, promisc=True , immediate=True , timeout_ms=50 ) filters = { 'DNS' : 'udp port 53' , 'HTTP' : 'tcp port 80' } pcap_filepath = 'pkts/pkts_{}.pcap' .format (time.strftime("%Y%m%d-%H%M%S" , time.localtime())) pcap_file = open (pcap_filepath, 'wb' ) //数据包的存储 writer = dpkt.pcap.Writer(pcap_file) print ('Start capture...' ) try : pkts_count = 0 for ptime, pdata in pkt: writer.writepkt(pdata, ptime) printRawPkt(ptime, pdata) pkts_count += 1 except KeyboardInterrupt as e: writer.close() pcap_file.close() if not pkts_count: os.remove(pcap_filepath) print ('%d packets received' %(pkts_count)) def printRawPkt (time, data ): //打印数据包的基本信息 eth = dpkt.ethernet.Ethernet(data) //数据包的解析 print ('Timestamp: ' , str (datetime.datetime.utcfromtimestamp(time))) print ('Ethernet Frame: ' , mac_addr(eth.src), mac_addr(eth.dst)) if not isinstance (eth.data, dpkt.ip.IP): print ('' ) return ip = eth.data do_not_fragment = bool (ip.off & dpkt.ip.IP_DF) more_fragments = bool (ip.off & dpkt.ip.IP_MF) fragment_offset = ip.off & dpkt.ip.IP_OFFMASK print ('IP: %s -> %s (len=%d ttl=%d DF=%d MF=%d offset=%d)\n' % ( ip_addr(ip.src), ip_addr(ip.dst), ip.len , ip.ttl, do_not_fragment, more_fragments, fragment_offset)) def anlysisData (data ): packet = dpkt.ethernet.Ethernet(data) if isinstance (packet.data, dpkt.ip.IP): ip = ip_addr(packet.data.dst) if packet.data.data.dport == 80 or packet.data.data.sport == 80 : try : print (packet.data.data.data.decode('utf-8' , errors='ignore' )) except UnicodeDecodeError as uderr: print (uderr.__str__()) def main (): if 'Windows' in platform.platform(): iface = getInterfaceByName('Router' ) else : iface = 'enp2s0' captureData(iface) if __name__ == "__main__" : main()
再就是简单介绍wireshark
数据包的颜色代表了其性质。可以看出它传输过程中不同网络等次的信息,显化TCP三次握手记录。这里区分TCP和UDP,TCP的三次握手四次挥手确保了数据的完整性,不容易丢包,但是相对速度慢。UDP可以说是流式传输,丢包率高速度快,应用于视频电话之类的时间同步较高的传输。