Introduction

About Scapy

Scapy is a Python program that enables the user to send, sniff and dissect and forge network packets. This capability allows construction of tools that can probe, scan or attack networks.

换句话说,Scapy是功能强大的交互式数据包处理程序. 它能够伪造或解码各种协议的数据包,在线发送它们,捕获它们,匹配请求和答复等等. Scapy可以轻松处理大多数经典任务,例如扫描,跟踪路由,探测,单元测试,攻击或网络发现. 它可以替代hping,arpspoof,arp-sk,arping,p0f甚至Nmap,tcpdump和tshark的某些部分.

_images/testing-taxonomy.png

Scapy在许多其他工具无法处理的许多其他特定任务上也表现出色,例如发送无效帧,注入您自己的802.11帧,组合技术(VLAN跳变+ ARP缓存中毒,WEP加密通道上的VOIP解码,... )等

这个想法很简单. Scapy主要做两件事:发送数据包和接收答案. 您定义了一组数据包,它将发送它们,接收答案,将请求与答案进行匹配并返回数据包对(请求,答案)列表和不匹配的数据包列表. 与Nmap或hping之类的工具相比,这具有很大的优势,答案不会减少为(打开/关闭/过滤),而是整个数据包.

在此之上可以构建更多高级功能,例如,执行跟踪路由并因此仅给出请求的起始TTL和答案的源IP的功能. 可以ping通整个网络并提供计算机应答列表. 一个执行portcan并返回LaTeX报告的程序.

What makes Scapy so special

首先,使用大多数其他网络工具,您将无法创建作者无法想象的东西. 这些工具是为特定目标而构建的,与之相距无几. 例如,ARP缓存中毒程序不会让您使用双重802.1q封装. 或者尝试找到一个程序,该程序可以发送带有填充的ICMP数据包(我说是padding ,不是有效负载 ,见?). 实际上,每当您有新需求时,就必须构建一个新工具.

其次,它们通常会使解码和解释混乱. 机器擅长解码,可以帮助人类. 解释是为人类保留的. 一些程序试图模仿这种行为. 例如,他们说" 此端口已打开 ",而不是" 我收到了SYN-ACK ". 有时候他们是对的. 有时不是. 对于初学者来说,这比较容易,但是当您知道自己在做什么时,便会继续尝试从程序的解释中推断出真正发生的事情以制作自己的东西,这很困难,因为您丢失了大量的信息. 而且您经常最终使用tcpdump -xX解码和解释该工具遗漏的内容.

第三,即使仅解码的程序也无法提供您收到的所有信息. 他们给您的网络愿景是他们认为足够的. 但这还不完整,您会有偏差. 例如,您知道一个报告以太网填充的工具吗?

Scapy试图克服这些问题. 它使您能够准确构建所需的数据包. 即使我认为在TCP之上堆叠802.1q层是没有意义的,但对于其他人开发某些我不知道的产品来说,它可能也有一些意义. Scapy有一个灵活的模型,它试图避免这种任意限制. 您可以随意将所需的任何值放在所需的任何字段中,并根据需要堆叠它们. 毕竟你是成年人.

实际上,这就像每次都构建一个新工具一样,但是您只需要编写两行Scapy,而不是处理一百行的C程序.

进行探查(扫描,跟踪路由等)之后,Scapy会始终为您提供来自探查的完整解码数据包,然后再进行任何解释. 这意味着您可以进行一次探查并进行多次解释,例如请求跟踪路由并查看填充.

Fast packet design

其他工具遵循您从Shell范例运行程序 . 结果是描述分组的可怕语法. 对于这些工具,采用的解决方案以工具作者所设想的场景的形式使用了较高但功能不强的描述. 例如,仅IP地址必须提供给端口扫描程序以触发端口扫描方案. 即使对该场景进行了一些调整,您仍然会陷入端口扫描.

Scapy的范例是提出一种领域特定语言(DSL),该语言能够对任何类型的数据包进行强大而快速的描述. 使用Python语法和Python解释器作为DSL语法和解释器具有许多优点:无需编写单独的解释器,用户不需要学习另一种语言,并且他们受益于完整,简洁而非常强大的语言.

Scapy使用户能够将一个数据包或一组数据包描述为一层又一层地堆叠在一起的层. 每层的字段都有有用的默认值,可以将其重载. Scapy不强制用户使用预定的方法或模板. 这减轻了每次需要不同方案时编写新工具的需求. 在C语言中,描述一个数据包平均需要60行. 使用Scapy,可以仅在一行中描述要发送的数据包,而在另一行中描述该结果以打印结果. 可以在2行Scapy中重写90%的网络探测工具.

Probe once, interpret many

网络发现是黑盒测试. 探测网络时,会发送许多刺激,而仅回答其中的一些. 如果选择了正确的刺激,则可以通过响应或缺少响应来获得所需的信息. 与许多工具不同,Scapy提供所有信息,即发送的所有刺激和接收的所有响应. 检查这些数据将为用户提供所需的信息. 当数据集较小时,用户可以对其进行挖掘. 在其他情况下,数据的解释将取决于所采取的观点. 大多数工具会选择视点,并丢弃与该视点无关的所有数据. 由于Scapy提供了完整的原始数据,因此可以多次使用该数据,从而使视点在分析过程中得以发展. 例如,可以探测TCP端口扫描,并将数据可视化为端口扫描的结果. 然后,还可以相对于响应数据包的TTL可视化数据. 无需启动新的探针来调整数据的视点.

_images/scapy-concept.png

Scapy decodes, it does not interpret

网络探测工具的一个常见问题是它们试图解释收到的答案,而不是仅仅解码并给出事实. 报告诸如在端口80上接收到TCP重置之类的内容不会产生解释错误. 报告端口80已关闭是一种解释,在大多数情况下可能是正确的,但在工具作者未曾想到的某些特定情况下是错误的. 例如,某些扫描程序在收到ICMP目标不可达数据包时,往往会报告已过滤的TCP端口. 这可能是正确的,但是在某些情况下,这意味着数据包没有被防火墙过滤,而是没有主机转发数据包.

解释结果可以帮助不知道端口扫描是什么的用户,但也可能弊大于利,因为这会给结果带来偏差. 可能发生的情况是,他们可以自己进行解释,有知识的用户将尝试对工具的解释进行逆向工程,以得出触发该解释的事实. 不幸的是,此操作丢失了很多信息.

Quick demo

_images/animation-scapy-demo.svg

首先,我们播放一下并一次创建四个IP数据包. 让我们看看它是如何工作的. 我们首先实例化IP类. 然后,我们再次实例化它,并提供了一个值得四个IP地址的目的地(/ 30提供了网络掩码). 使用Python习惯用法,我们在一组显式包中开发此隐式包. 然后,我们退出翻译. 当我们提供一个会话文件时,我们正在处理的变量将被保存,然后重新加载:

# ./run_scapy -s mysession
New session [mysession]
Welcome to Scapy (2.4.0)
>>> IP()
<IP |>
>>> target="www.target.com/30"
>>> ip=IP(dst=target)
>>> ip
<IP dst=<Net www.target.com/30> |>
>>> [p for p in ip]
[<IP dst=207.171.175.28 |>, <IP dst=207.171.175.29 |>,
 <IP dst=207.171.175.30 |>, <IP dst=207.171.175.31 |>]
>>> ^D
# ./run_scapy -s mysession
Using session [mysession]
Welcome to Scapy (2.4.0)
>>> ip
<IP dst=<Net www.target.com/30> |>

现在,让我们处理一些数据包:

>>> IP()
<IP |>
>>> a=IP(dst="172.16.1.40")
>>> a
<IP dst=172.16.1.40 |>
>>> a.dst
'172.16.1.40'
>>> a.ttl
64

假设我要广播的MAC地址和ketchup.com和mayo.com的IP有效负载,TTL值从1到9,以及UDP有效负载:

>>> Ether(dst="ff:ff:ff:ff:ff:ff")
      /IP(dst=["ketchup.com","mayo.com"],ttl=(1,9))
      /UDP()

我们在1行中定义了18个数据包(1个隐式数据包)

Sensible default values

Scapy尝试对所有数据包字段使用合理的默认值. 如果不被覆盖,

  • 根据目的地和路由表选择IP源

  • 计算校验和

  • 根据输出接口选择源MAC

  • 以太网类型和IP协议由上层确定

_images/default-values-ip.png

其他字段的默认值被选为最有用的:

  • TCP源端口为20,目标端口为80.

  • UDP源和目标端口为53.

  • ICMP类型是回显请求.

Learning Python

Scapy使用Python解释器作为命令板. 这意味着您可以直接使用Python语言(分配变量,使用循环,定义函数等).

如果您是Python的新手,却真的不懂一个字,或者您想学习这种语言,请花一个小时阅读Guido Van Rossum撰写的非常好的Python教程 . 之后,您将了解Python :)(真的!). 对于更深入的教程, Dive Into Python也是一个很好的开始.