介绍

关于 Scapy

Scapy是一个 Python程序,它允许用户发送、嗅探、分析和伪造网络包。这种能力允许构建能够探测、扫描或攻击网络的工具。

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

_images/testing-taxonomy.png

scapy还可以很好地执行许多其他工具无法处理的其他特定任务,例如发送无效帧、注入自己的802.11帧、结合技术(VLAN跳跃+ARP缓存中毒、WEP加密通道上的VoIP解码等)。

这个想法很简单。scapy主要做两件事:发送数据包和接收答案。定义一组数据包,发送它们,接收答案,将请求与答案匹配,并返回数据包对(请求、应答)列表和不匹配数据包列表。与nmap或hping等工具相比,这有一个很大的优势,即答案不会减少到(打开/关闭/过滤),而是整个包。

除此之外,还可以构建更多的高级功能,例如,跟踪路由并仅给出请求的起始TTL和应答的源IP。一种能发出整个网络信号并给出应答机列表的设备。一个执行portscan并返回一个 Latex 报告的函数。

是什么让 Scapy 如此特别?

首先,使用大多数其他网络工具,您不会构建作者没有想到的东西。这些工具是为特定的目标而构建的,不能偏离太多。例如,一个ARP缓存中毒程序不允许您使用双802.1q封装。或者尝试找到一个程序,可以发送,比如,填充的ICMP包(我说 衬垫 不是 有效载荷 看到了吗?).事实上,每次你有新的需求时,你都必须构建一个新的工具。

其次,它们通常会混淆解码和解释。机器擅长解码,可以帮助人类破解。翻译是为人类保留的。有些程序试图模仿这种行为。例如他们说 这个港口是开放的 “而不是” I received a SYN-ACK “。有时候他们是对的。有时不会。对于初学者来说,这很容易,但是当你知道你在做什么时,你会继续尝试从程序的解释中推断出实际发生的事情,以形成你自己的,这很难,因为你丢失了大量的信息。最后你经常使用 tcpdump -xX 解码和解释工具遗漏的内容。

第三,即使是只进行解码的程序也不能提供它们接收到的所有信息。他们给你的网络愿景是他们的作者认为足够的。但它并不完整,你有偏见。例如,您知道一个报告以太网填充的工具吗?

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

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

在探测之后(扫描、跟踪路径等),scapy总是在任何解释之前,从探测中给出完整的解码数据包。这意味着您可以探测一次并解释多次,请求traceroute并查看填充。

快速分组设计

其他工具会粘在 program-that-you-run-from-a-shell 范式。结果是描述一个包的糟糕语法。对于这些工具,所采用的解决方案使用了更高但不太强大的描述,其形式是工具作者设想的场景。例如,只有IP地址必须提供给端口扫描仪才能触发 端口扫描 脚本。即使稍微调整了一下场景,您仍然需要进行端口扫描。

scapy的范例是提出一种特定于领域的语言(DSL),它能够对任何类型的数据包进行强大而快速的描述。使用python语法和python解释器作为DSL语法和解释器有许多优点:不需要编写单独的解释器,用户不需要再学习另一种语言,他们从一种完整、简洁和强大的语言中获益。

scapy允许用户将一个或一组数据包描述为层叠在一起的层。每个层的字段都有可以重载的有用默认值。scapy不强制用户使用预先确定的方法或模板。这减少了每次需要不同场景时编写新工具的需求。在C语言中,平均需要60行来描述一个包。使用scapy,将要发送的数据包只能在一行中描述,另一行用于打印结果。90%的网络探测工具可以用2行scapy重写。

探测一次,解释许多

网络发现是黑盒测试。当探测一个网络时,许多刺激被发送,而只有少数被应答。如果选择了正确的刺激,所需的信息可以通过反应或缺乏反应获得。与许多工具不同,scapy提供所有信息,即发送的所有刺激和接收的所有响应。对这些数据的检查将为用户提供所需的信息。当数据集很小时,用户只需挖掘它。在其他情况下,数据的解释将取决于所采取的观点。大多数工具选择视点并放弃与该视点无关的所有数据。因为scapy提供了完整的原始数据,所以该数据可能会被多次使用,从而允许视点在分析过程中演变。例如,可以探测TCP端口扫描,并将数据作为端口扫描的结果可视化。然后还可以根据响应包的TTL来可视化数据。无需启动新的探测器来调整数据的视点。

_images/scapy-concept.png

狡猾的译码,它无法解释

网络探测工具的一个常见问题是,它们试图解释收到的答案,而不仅仅是解码和给出事实。报告类似 在端口80上接收到TCP重置 不受解释错误的影响。报告 端口80关闭 是一种解释,在工具作者无法想象的特定环境中,大多数时候可能是正确的,但也可能是错误的。例如,一些扫描器在接收到无法到达的ICMP目的地数据包时,往往会报告一个经过过滤的TCP端口。这可能是正确的,但在某些情况下,这意味着数据包没有被防火墙过滤,而是没有主机将数据包转发到。

解释结果可以帮助不知道端口扫描是什么的用户,但它也可以带来更多的伤害而不是好处,因为它会给结果注入偏见。可能会发生的情况是,为了让他们自己进行解释,知识渊博的用户将尝试对工具的解释进行逆向工程,以得出触发该解释的事实。不幸的是,在这次行动中丢失了很多信息。

快速演示

_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地址,IP负载到ketchup.com和mayo.com,TTL值从1到9,以及一个udp负载:

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

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

合理的默认值

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

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

  • 计算校验和

  • 根据输出接口选择源MAC

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

_images/default-values-ip.png

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

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

  • UDP源端口和目标端口为53。

  • ICMP类型为回显请求。

Python学习手册

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

如果你对python还不熟悉,而且你真的因为这个而不懂一个词,或者如果你想学习这种语言,花一个小时的时间来阅读非常好的 Python tutorial 吉多·范·罗森。在那之后,你就会知道 Python :)(真的!)。对于更深入的教程 Dive Into Python 也是一个很好的开端。