这篇文章主要介绍了使用 Python 实现 windows 下的抓包与解析, 非常不错, 具有参考借鉴价值, 需要的朋友可以参考下
系统环境: windows7, 选择 windows 系统是因为我对自己平时日常机器上的流量比较感兴趣
python 环境: python2.7 , 这里不选择 python3 的原因, 是因为接下来要用到的 scapy 包在 python3 中安装较于 python2 要麻烦得多如果你习惯于用 python3, 数据包的分析完全可以放在 3 下面做, 因为抓包和分析是两个完全独立的过程
需要的 python 包: scapy 和 dpkt
抓包代码:
- from scapy.sendrecv import sniff
- from scapy.utils import wrpcap
- dpkt = sniff(count = 100) #这里是针对单网卡的机子, 多网卡的可以在参数中指定网卡
- wrpcap("demo.pcap", dpkt)
你没看错, 仅仅只需要两行代码就可以实现一个简单的抓包功能 sniff 函数负责嗅探数据包, 而 wrpcap 函数将抓取到的数据包保存起来
数据包的分析:
- import dpkt
- import socket
- import datetime
- def printPcap(pcap):
- try:
- for timestamp, buf in pcap:
- eth = dpkt.ethernet.Ethernet(buf) #获得以太包, 即数据链路层包
- print("ip layer:"+eth.data.__class__.__name__) #以太包的数据既是网络层包
- print("tcp layer:"+eth.data.data.__class__.__name__) #网络层包的数据既是传输层包
- print("http layer:" + eth.data.data.data.__class__.__name__) #传输层包的数据既是应用层包
- print('Timestamp:',str(datetime.datetime.utcfromtimestamp(timestamp))) #打印出包的抓取时间
- if not isinstance(eth.data, dpkt.ip.IP):
- print('Non IP Packet type not supported %s' % eth.data.__class__.__name__)
- continue
- 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)' % (socket.inet_ntoa(ip.src), socket.inet_ntoa(ip.dst), ip.len, ip.ttl, do_not_fragment, more_fragments,fragment_offset))
- except:
- pass
- def main():
- f =open('demo.pcap','rb')
- pcap = dpkt.pcap.Reader(f)
- printPcap(pcap)
- if __name__ =='__main__':
- main()
结果显示:
这是我打开 360 的路由器卫士时抓取的数据包这个软件在打开时与路由器通信, 获得连接路由器的电脑和手机的列表 192.168.1.100 是我的机器, 192.168.1.1 是路由器地址, 其中可以看到 windows 发送的数据包的 ttl 值默认是 128, 其他的系统默认是 64, 与我们的理论常识是相符的
TCP/IP 五层分层的结构和封包过程, 附图二张:
来源: http://www.phperz.com/article/18/0225/362710.html