Python的Scapy模块能够让用户发送,嗅探,解析并伪造网络数据包。这些能力能用来构建探测,扫描或者攻击网络的工具。
换句话说,Scapy是一个强大的交互式数据包处理程序。它能够伪造或者解码大量的数据包协议,发送,捕获数据包并匹配请求和回复。Scapy能轻松的处理像扫描,追踪,探测,单元测试,攻击或者网络发现能大多数常见的任务。它能够替代像hping, arpspoof, arp-sk, arping, p0f甚至是Nmap, tcpdump, and tshark这样的工具。
Scapy在执行很多工具不能处理的特定问题上也完成的很好。像是发送无效的数据帧,注入我们自己的802.11帧,在WEP上解码加密通道结合其他技术(VLAN hopping攻击+APR缓存中毒,VOIP解码等)等等。
看起来很不错。Scapy只做了两件主要的事:发送数据包并接受响应。你定义了一些数据包,然后发送他们,接受响应,匹配符合要求的响应,然后返回数据元组(请求,响应)和一些没有被匹配的数据包。这对于那些像Nmap和hping的工具来说有巨大的优势,他们不会减少数据包而是完整的数据包。
这些能建立更高水平的功能,比如路由追踪,只需要开始请求的TTL和响应的原始的IP地址便可返回结果。Ping这个网络并返回主机的响应,端口扫描并返回LaTeX格式的报告。
首先,大多数网络工具你不能做作者没有设定的事情。那些工具被建立起来是为了特定的目标,不能偏离目标。比如说,ARP缓存中毒工具不会让你使用双802.1q封装。或者试图发现一个程序能发送,表达一个用ICMP的数据包。事实上,每当你有新的需求你必须构建新的工具。
第二,他们通常把解码和解释弄混淆。机器很擅长解码并帮助人们开始,解释是给人类看的。一些程序试图模仿这些行为。例如,他们说“这个端口是开放的”而不是“我收到了一个SYN-ACK”,有些时候他们是对的,有时候并不是。这对初学者很容易,但是当你知道你正在做什么的时候,你要试图解码从程序的解释中到底发生了什么,这是很困难的,因为你丢掉了大量的信息。并且你经常使用tcpdump -xX来解码,并解释,工具丢失了大量的信息。
第三,甚至程序只解码并不给他们收到的所有的信息。他们给你的网络情况是作者认为已经足够了的。但是并不完整,你对此会有一些偏见。比如说,你知道一个工具介绍以太网填充吗?
Scapy试图克服上面这些问题,他能够让你建立精确的你想要的数据包。尽管我认为堆一个802.1q协议上层的TCP没有任何意义。他可能工作在其他人的产品里我们不知道。Scapy有一个灵活的模块试图避免这种任意的限制。你能添加任何值和任何字段在协议栈中,历你是所有的作者。
事实上,在建立一个新的程序时,你不必写一百行的C代码,而只需2行的Scapy。
在探测(追踪,扫描等)之后,Scapy总是给你所有的探测解码包,在解释之前。这就意味着你只需探测一次便可解释很多次。请求一个数据查看里面的填充的数据。
其他工具坚持 program-that-you-run-from-a-shell的范式。结果是糟糕的语法来描述数据包。对于这样的工具,解决方法是采用跟高级的但是不怎么强大的描述,在这种情况下全凭住作者的设计。不如说,只有IP地址必须传给端口扫瞄器来触发端口扫描方案。即时情况改变了一点,你还是要进行端口扫描。
Scapy的范式提出了领域特定语言(DSL)可以强大并快速的描述不同类型的数据包。使用Python语法和Python解释器作为DSL的语法和解释器有很多有优点:不必编写独立的解释器,用户不需要在学其他的语言,他们将受益与一个完整,简介,强大的语言。
Scapy能允许用户描述数据包或者设置数据包在协议栈的层面上。每一个协议的字段都有默认的值并且能重载。Scapy不会强迫用户使用特定的方法或模板。这减轻了编写一个工具的要求,在C语言中,平均需要60行代码来描述一个数据包。用Scapy,发送的数据包可能只需要一行来描述其他的行来打印结果。90%的网络探测工具只需要两行Scapy代码便可编写。
网络测试是一个黑盒测试。当探测一个网络时,很多探测的数据包被发送,只有一小部分有响应。如果选择了正确的探测数据,想要的信息就可能通过响应获得或者是响应不足。不想许多工具,Scapy提供所有的信息,即所有发送的探测数据包和所有收到的数据包。检查数据能提供给用户想要的信息。当数据集很小的时候,用户只能从中挖掘信息。其他情况下,数据的解释依赖于观测点的采取,大多数工具选择观测点并丢弃所有与观测点不相关的数据。因为Scapy提供完整的原始数据,数据可能会被使用很多次允许观测点的演化,在分析中。比如说,TCP端口扫描能被探测到,扫描的结果数据很直观,这些数据也能直观的反应响应数据包的TTL。只需要调整数据的观测点一个新的探测就不必被启动了。
网络探测工具的共同的问题就是他们试图解释收到的响应而不是解码并给出事实。报告一些事情像是Received a TCP Reset on port 80是不会解释出错的,报告Port 80 is closed是一个解释,可能正确在大多数情况下,但是在作者没想到的特殊情况下也可能错误。例如,一些扫瞄器倾向于报告一个过滤的TCP端口当他们收到一个ICMP目标地址不可达的数据包时。这可能是正确的,但是在一些情况下坑两个数据包并没有被防火墙过滤而是没有主机转发这个数据包。
解释的结果能帮助用户理解扫描de结果,但是也可能带来更多的坏处,当他偏向于某个结果时。当发生什么事情时他们能自己做出解释,知识丰富的用户将试图逆向工程工具的解释来获取应发解释的事实。不幸的是大多数信息在操作时已经被抛弃了。
首先,我们玩一个字节,一次创建四个IP数据包。让我们看看他是怎么工作的。我们首先实例化一个IP类,然后我们再次实例化它并提供四个有意义的目标IP地址(/30是子网掩码)。使用Python的列表,我们发展了一个隐式的数据包在一个显示的数据报上。然后我们停止解释器,这为我们提供了一个会话文件,我们的变量在工作时就保存了,以便我们重新加载: