随着Python越来越流行,它在安全领域的用途也越来越多。比如可以使用requests模块写一个Web请求工具;使用sockets编写一个TCP网络通信程序;您可以使用struct模块来解析和生成字节流。解析和处理网络数据包在网络安全领域比较常见,我们经常会用到tcpdump和wireshark(tshark)。但是如果你想自己编写程序进行处理,就需要一个更加灵活的语言包(库),这就是本文要介绍的Scapy。概述Scapy是一个用于底层网络数据包的Python模块和交互程序。该程序对底层的数据包处理进行了抽象和封装,使得网络数据包的处理变得非常简单。该类库在网络安全领域可以有非常广泛的用例,可用于漏洞利用开发、数据泄露、网络监控、入侵检测、流量分析捕获等。Scapy集成了数据可视化和报告生成功能,可以轻松展示结果和数据。Scapy的基本思想是提出一种领域特定的语言,用于方便快捷的WireFormat管理。安装运行Scapy可以通过pip安装:pipinstallscapy也可以通过发行版的包管理器安装,比如yum,但是它的版本可能太旧过时了。也可以直接从官方仓库clone源码安装:gitclonegithub/secdev/scapy然后直接运行:cdscapy./run_scapyusageexampleanalysisPCAPcapture使用Scapy最简单的就是读取PCAP文件。我们以下载Wireshark的sip-rtp-opus-hybrid.pcap示例PCAP数据包为例:使用rdpcap()函数导入PCAP文件并读取其内容:>>>pkts=rdpcap("sip-rtp-opus-hybrid.pcap")>>>pkts要更详细的读取PCAP文件中的数据,可以使用PcapReader打开迭代读取文件句柄中的数据包,一次一个包,bing实例化的对象:>>>fd=open("sip-rtp-opus-hybrid.pcap","rb")>>>reader=PcapReader(fd)>>>reader>>>forCCinreader:...:print(CC)...:>>>fd.close()如上所示,每一个Each数据包以有线格式提供。Scapy将每个数据包与网络层堆叠在一起。Scapy层对象对应于网络协议及其格式。获取第一个数据包并检查IP层是否可用:>>>first=CC[0]>>>first.haslayer(IP)True>>>IPinfirstTrue要解析来自特定层的数据包,请按需执行您希望图层对其进行索引并让Scapy打印所有字段:要以十六进制打印数据包,您可以使用hexdump()函数:>>>hexdump(first)为了完全解析并完美地输出数据包,show()方法需要调用:>>>first.show()可以看到,上面的SIload无法有效解析。这是因为Scapy主要处理网络堆栈下部的二进制协议,而SIP则不是。但是可以引入第三方模块来解析一些应用层协议,比如HTTP协议。实时数据包捕获分析例如,您可以读取带有预捕获数据包的PCAP文件。如果你想做一些数据包嗅探,如果系统准备好在混杂模式下使用网络接口,你可以调用sniff()从网卡中获取一些数据。封装函数:>>>forCCinsniff(count=5):...:CC.show()...:Scapy也可以使用与Wireshark(tshark)和tcpdump相同的BPF语法来过滤嗅探的数据包和许多其他工具支持:>>>forCCinsniff(filter="udp",count=5):...:CC.show()...:要将捕获的数据包保存到PCAP文件以供进一步分析,您可以使用wrpcap()函数导出到文件:>>>capture=sniff(filter="udp",count=5)>>>capture>>>wrpcap("udp.pcap",capture)除了嗅探(捕获和解析)网络数据包之外,还发送ping数据包,但Scapy还支持为各种主动欺骗生成数据包:网络扫描、服务器探测、通过发送格式错误的请求来攻击系统等。尝试ping下面的服务器,这涉及向服务发送ICMP数据包:>>>CC=IP(dst="XXX")/ICMP()>>>CC.show()然后调用sr1()函数,可以发送一个ICMP包(即ping),等待返回包返回:>>>rr=sr1(CC)Beginemission:Finishedsending1packets....*Received4packets,got1answers,remaining0packets>>>上面的rr得到了正确的ICMP回复。为了发送多个数据包并接收响应(例如,实现ping扫描),可以使用sr()函数。发送多个数据包,但等待单个响应。您还可以使用sr1_flood()函数。网络协议层乱序Scapy通过重载Python/操作符实现层堆叠,不再强制按照网络层的顺序执行,从而实现按照预期的人为顺序执行(这在一些测试和应用中很有用)。>>>CC=ICMP()/UDP()/IP()/IP()>>>CC>>>>>>>CC.show()###[ICMP]###type=echo-r??equestcode=0chksum=Noneid=0x0seq=0x0###[UDP]###sport=domaindport=domainlen=Nonechksum=None###[IP]###version=4ihl=Nonetos=0x0len=Noneid=1flags=frag=0ttl=64proto=ipv4chksum=Nonesrc=127.0.0.1dst=127.0.0.1\options\###[IP]###version=4ihl=Nonetos=0x0len=Noneid=1flags=frag=0ttl=64proto=hopoptchksum=Nonesrc=127.0.0.1dst=127.0.0.1\options\>>>hexdump(CC)警告:没有IP底层来计算校验和。保留null.00000800F765000000000035003500300000...e...5.5.0..0010450000280001000040047CCF7F000001E..(....@.|..00207F000001450000140001000040007CE7....E....@.|.00307F0000017F000001是这样设计的,主要是生成任意网络数据包(故意破坏),用于漏洞测试研究或利用,当然对于不熟悉这方面的用户,强烈建议不要轻易尝试,以免引起质疑。数据可视化Scapy还支持通过PyX进行数据可视化(需要预装模块)。可以作为数据包或数据包列表输出的图形(PostScript/PDF格式):>>>xxCC[404].pdfdump(layer_shift=1)>>>xxCC[404].psdump("/tmp/xxCC.eps",layer_shift=1)模糊测试使用函数fuzz()使用快速构造生成随机测试值并使用模糊模板循环发送进行测试。在下面的例子中,IP层是正常的,UDP和NTP层是fuzzed的。UDP校验和将是正确的,UDP目标端口将被NTP重载为123,NTP版本将被强制为4,所有其他端口将被随机化:send(IP(dst="target")/fuzz(UDP()/NTP(version=4)),loop=1)..........^CS发送了16个数据包。这只是scapy庞大功能中的冰山一角,更多使用方法请参考官方文档。