【Python学习】Mac下用python+pypcap+dpkt抓取IP数据包并分析(一)

这几天在做网络协议的课程设计,题目是IP数据报流量监控,要求是从本地抓取数据包然后解析并进行统计。

这不是有现成的Wireshark吗。。功能强大好用支持多平台,简直是居家旅行黑人电脑攻击网站必备神器(误),现在老师居然要我们自己写一个。不过我脑筋一转,正好这学期开始时看了点python,想着锻炼下自己能力,用python写个抓包加分析的小脚本好了。

环境:MacBook Pro (13-inch, 2016) / macOS Sierra 10.12.5/Python 2.7.10/Sublime Text

OK,这是大致的环境。我们老师给的材料里建议是用Winpcap,但是这是windows上的抓包模块,Mac上。。我们还是从头来吧。。

在网上查了查Mac下Python抓包的文章或博客,发现相关资料还蛮少的,不过还是让我发现了一些有用的部分。

首先,抓包的库还是蛮多的,我这边采用的是 pypcap抓包+dpkt解包 的方法,另外还有scapy啊什么的(我们另外一个班有一组做的就是用scapy的)。而关于Pypcap+dpkt目前能搜到的中文资料就更有限了(可能是我经验不足),给出的方法很多都没法用,或者输出是各种乱码,问题蛮多需要一个一个去解决。后来我在*上终于找到了一个跟我一样困惑的外国友人。他提了几个关于抓包的问题和我的困惑也蛮相似的,比如Mac下如何安装Python libcap(其实就是pypcap,原谅我那时候有多无知哈哈哈),为什么抓了包用dpkt解析出来后输出是一串串莫名其妙的字符等等等,反正我觉得这个老兄跟我一样蛮惨,很多概念都从零开始。

嗯。。这篇文章就当作从零开始小白教学好了(我也是小白QAQ。。


1、认识下Pypcap和dpkt

要介绍pypcap和wincap等库,首先必须知道libpcap。Libpcap是一个开源代码库,它提供了一个为网络数据报抓取系统设计的高层接口。它发明于1994年,作者是来自加利福尼亚大学的研究学者,当时制作Libpcap目的是为了更好的研究TCP协议和因特网接口。

Libpcap的作者的主要目的是创造一种与运行平台无关的API库。它可以消除在各种不同应用中设立基于不同平台的数据报捕获模型的需要,消除各种操作系统建立不同捕获软件的需要。

一开始,lipcap API库被设计成使用C和C++语言运行。但随着更多不用高级编程语言的出现,比如Perl、Python、Java、C#和Ruby等,lipcap被允许可以被封装成不同语言的库被调用。Libpcap可以在大部分的Unix操作系统下运行,同时也支持windows系统,也就是winpcap库。

有了上面概念,pypcap库的介绍就简单很多了,它是一款基于libpcap封装的为python语言提供接口的抓包库,专门在python上运行。由于Mac OS系统预安装了python2.7,因此它可以运行Pypcap库。

至于dpkt,它则是用来解析数据包的库,不过我对它的了解不是很多。

这边再讲一下pypcap和dpkt的安装,我的建议是用pip或者easy_install的方式,比较省时省力。这里值得一提的是,一开始在安装pypcap的时候,我使用了网上一个帖子的方法,在官网下载pypcap的压缩包后,通过命令行的方法手动软链接,但是在调用import pcap的时候仍然发生了错误。在查找了网上的资料后,安装了homebrew,然后使用了brew doctor的命令,检测了软链接的错误。随后使用了pip成功进行了安装。


2、开始一场纠结的冒险吧

好的这部分将要讲的内容是编程部分,将会站在一个小白的角度逐步讲解。

首先是建文件,用sublime新建个py文件(command+N),目录么。。个人喜好吧,我就放在桌面了。command+S保存,右下角改成python语言,这样可以自动检查语法上的一些问题。

既然辛辛苦苦把库都安装好了,肯定得用对吧。这边直接import把库调用一下。对了,为了后面实现另外一些功能,除了pcap和dpkt,还需要调用一下time、math和os库。

【Python学习】Mac下用python+pypcap+dpkt抓取IP数据包并分析(一)

嗯还有utf-8编码。

好的接下来我们使用pcap库来进行抓包,这里要用到一个函数pcap.pcap()。这个函数是用来定义嗅探器的,我们的抓包就是通过这个函数定义的嗅探器实现的。如果给嗅探器取名为sniffer,那么参考的定义如下:【Python学习】Mac下用python+pypcap+dpkt抓取IP数据包并分析(一)

其中括号里是可以加入参数的,比如name、promisc、immediate和所要抓包的网卡名称等等。网上的中文资料对这个函数的介绍非常有限,所以我也没有找到一个参数列表。但是不加参数也是可以运行的。

好的有了嗅探器以后,我们就可以进行抓包了。那么抓下来的包在哪里呢了(我觉得应该是在缓存里面,请原谅我的无知。。),我们去sniffer里面找找。在这里sniffer是一直在抓包的并把数据源源不断存入内存,但是我们解包得一个个解吧。所以我们做一个循环:

【Python学习】Mac下用python+pypcap+dpkt抓取IP数据包并分析(一)

这边sniffer中应该是有两个对象,一个timestamp是指时间戳,raw_buf是指包中的原始数据。

接下来我们用dpkt进行解包了,注意以下定义:

【Python学习】Mac下用python+pypcap+dpkt抓取IP数据包并分析(一)

eth是我们定义的一个对象,dpkt.ethernet.ethernet()则是利用dpkt库解包的方法。这句话的含义是解析以太网帧(即第一次剥离)。我们可以得到源mac地址、目的mac地址等内容。同时,我们也就得到了判断这个包是不是IP数据报的方法。如果是则继续,不是则输出一句话。

【Python学习】Mac下用python+pypcap+dpkt抓取IP数据包并分析(一)

接下来我们让以太网帧的ip数据报部分等于一个新的对象,packet:

【Python学习】Mac下用python+pypcap+dpkt抓取IP数据包并分析(一)

将分片信息等取出:

【Python学习】Mac下用python+pypcap+dpkt抓取IP数据包并分析(一)

好的所需要的信息差不多到这里已经收集得差不多了,是时候进行输出了。在这里我采用了字典数组的方式进行输出,看起来也简洁美观一点:

【Python学习】Mac下用python+pypcap+dpkt抓取IP数据包并分析(一)

【Python学习】Mac下用python+pypcap+dpkt抓取IP数据包并分析(一)

这里值得一提的是两个地方。第一个,时间的输出。如果直接输出timestamp,造成的问题便是输出的是一串秒数。所以这里使用一个time.localtime()函数进行转换,再用time.strftime格式化成固定字符串进行输出。第二个,如果直接输出packet.src和packet.dst,那么我们得到的将会是一串/0x16/x98/0xaf 这样的乱码,这是为啥,为什么会出现这样的乱码。我也是在网上搜了好久的资料,才发觉原来这是一个python的编码问题。这里使用了一个语句,'%d.%d.%d.%d'%tuple(map(ord,list(packet.src))) 来对packet.src进行转换。%后面那串的大意就是将packet.src转换为list列表,然后使用ord方法返回字符在ASCII码中对应整数,再将这串整数转化为一个元组,'%d.%d.%d.%d'% 的意思是将后面的元组按单引号中的格式输出。(这一部分真是折腾死我了,好不容易找到一个将乱码转化成正常IP地址的格式)

好的至此整个脚本的主体部分就完成了,后续的文章中我会介绍完善的方法。

渣排版请见谅。