Python Scapy -- ARP请求和响应

3
我用这行代码发送一个arp广播包:

send(ARP(op=ARP.who_has, psrc="192.168.5.51", pdst=the_ip))

我的问题是:如何查看响应(在这种情况下:远程IP的MAC地址)?我知道我可以执行以下操作:
pkt = sniff(filter=arp , count=10) 
print (pkt.summary()) 

但我不想数数据包,因为我不知道它何时被打印出来(可能在接下来的10个或100个数据包中)。

在嗅探过程中,有没有一种方式可以打印摘要,以此查看我正在寻找的MAC地址?

编辑:我有一个想法,我可以嗅探10个数据包,如果数据包中有IP,则打印MAC地址,否则再嗅探10个数据包...... 这种技术似乎不是一个好方法......

2个回答

9

Scapy用户手册建议使用sr()sr1()函数发送数据包并接收答案:

sr()函数用于发送数据包并接收答案。该函数返回数据包和答案的一对,以及未被回答的数据包。函数sr1()是一个变体,仅返回一个已回答发送数据包(或数据包集)的数据包。数据包必须是第3层协议数据包(IPARP等)。函数srp()与此类似,但适用于第2层协议数据包(Ethernet802.3等)。

官方API文档指定了它们的完整签名。这些似乎是这种用例的相关参数:

retry:如果是正数,则重新发送未回复的数据包的次数。如果是负数,则在放弃之前连续未回答的探测次数。只有负值实际上有用。
timeout:在最后一个数据包被发送后等待多长时间。默认情况下,sr将永远等待,用户需要在预计没有更多答案时中断(Ctrl-C)。
inter:每个数据包发送之间等待的时间(以秒为单位)。

以下是使用sr()函数的执行示例:

In [1]: from scapy.all import *
WARNING: No route found for IPv6 destination :: (no default route?)

In [2]: results, unanswered = sr(ARP(op=ARP.who_has, psrc='192.168.1.2', pdst='192.168.1.1'))
Begin emission:
.....*Finished to send 1 packets.

Received 6 packets, got 1 answers, remaining 0 packets

In [3]: results
Out[3]: <Results: TCP:0 UDP:0 ICMP:0 Other:1>

In [4]: result = results[0]

In [5]: result
Out[5]: 
(<ARP  op=who-has psrc=192.168.1.2 pdst=192.168.1.1 |>,
 <ARP  hwtype=0x1 ptype=0x800 hwlen=6 plen=4 op=is-at hwsrc=XX:XX:XX:XX:XX:XX psrc=192.168.1.1 hwdst=XX:XX:XX:XX:XX:XX pdst=192.168.1.2 |>)

In [6]: original_packet, answer = result

In [7]: original_packet
Out[7]: <ARP  op=who-has psrc=192.168.1.2 pdst=192.168.1.1 |>

In [8]: answer
Out[8]: <ARP  hwtype=0x1 ptype=0x800 hwlen=6 plen=4 op=is-at hwsrc=XX:XX:XX:XX:XX:XX psrc=192.168.1.1 hwdst=XX:XX:XX:XX:XX:XX pdst=192.168.1.2 |>

In [9]: answer.hwsrc
Out[9]: 'XX:XX:XX:XX:XX:XX'

这里是使用sr1()函数的执行示例:
In [10]: result = sr1(ARP(op=ARP.who_has, psrc='192.168.1.2', pdst='192.168.1.1'))
Begin emission:
.....Finished to send 1 packets.
*
Received 6 packets, got 1 answers, remaining 0 packets

In [11]: result
Out[11]: <ARP  hwtype=0x1 ptype=0x800 hwlen=6 plen=4 op=is-at hwsrc=XX:XX:XX:XX:XX:XX psrc=192.168.1.1 hwdst=XX:XX:XX:XX:XX:XX pdst=192.168.1.2 |>

In [12]: result.hwsrc
Out[12]: 'XX:XX:XX:XX:XX:XX'

注意: 另一个回答该如何提取MAC地址演示了MAC地址如何被提取,这个答案也被编辑以反映这一点。


我无法打印结果(必须使用字节打印)。我尝试使用decode("utf-8"),但它没有起作用:AttributeError: decode - Bob Ebert
数据包的十六进制表示可以通过语句 str(packet).encode("HEX") 打印出来。 - Yoel
这是输出:pkt = str(pkt).encode("HEX") LookupError: 'HEX' 不是文本编码;使用codecs.encode()来处理任意编解码器。 - Bob Ebert
在 Python3 中,语句 import binascii; binascii.hexlify(bytes(packet)) 应该可以使用。 - Yoel
这是输出结果:b'0001080006040002028261493d94c0a80501a45e60d56ea5c0a80533'... 应该打印:<ARP hwtype=0x1 ptype=0x800 hwlen=6 plen=4 op=is-at hwsrc=XX:XX:XX:XX:XX:XX psrc=192.168.1.1 hwdst=XX:XX:XX:XX:XX:XX pdst=192.168.1.2 |> - Bob Ebert
显示剩余3条评论

2

我知道这个答案有些晚了,但对于其他人来说,根据最新版本的scapy,您可以通过索引从arp响应中提取mac地址,例如:

如果您做了类似于这样的事情:

pkt = Ether(dst='ff:ff:ff:ff:ff')/ARP(pdst='192.168.43.1')
ans,unans = sendp(pkt)

然后,您可以使用以下方法提取远程IP的MAC地址:
ans[0][1][ARP].hwsrc

据我所知,您无法使用正则表达式提取它。上面的代码将以字符串格式给出MAC地址。
同样地,您可以通过试错和更改索引来提取所有其他字段。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接