3

I send a arp packet broadcast with this line:

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

My question is: How can I view the response (in this case: the mac of the remote ip)? I know I can do:

pkt = sniff(filter=arp , count=10) 
print (pkt.summary()) 

But I do not want to count the packets because I do not know when it will be printed (could be in the next 10 or 100 packets)

Is there a way to while it is sniffing, to print the summary and thus, see the mac adress I am looking for?

Edit: I have an idea, Could I sniff 10 packets, if there is the ip in the packets print the mac adress, else sniff 10 more packets... This technique doesn't seems to be a good one tho...

Bob Ebert
  • 1,342
  • 4
  • 22
  • 41

2 Answers2

8

Scapy's user manual suggests using the sr() or sr1() function for sending packets and receiving answers:

The sr() function is for sending packets and receiving answers. The function returns a couple of packet and answers, and the unanswered packets. The function sr1() is a variant that only returns one packet that answered the packet (or the packet set) sent. The packets must be layer 3 packets (IP, ARP, etc.). The function srp() does the same for layer 2 packets (Ethernet, 802.3, etc.)

The official API documentation specifies their full signature. These seem to be the relevant arguments for this use-case:

retry: if positive, how many times to resend unanswered packets. if negative, how many consecutive unanswered probes before giving up. Only the negative value is really useful.
timeout: how much time to wait after the last packet has been sent. By default, sr will wait forever and the user will have to interrupt (Ctrl-C) it when he expects no more answers.
inter: time in seconds to wait between each packet sent.

Here is an execution example with the sr() function:

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'

Here is an execution example with the sr1() function:

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'

Note: An another answer to this question demonstrates how the MAC address can be extracted and this answer was edited to reflect it as well.

Yoel
  • 9,144
  • 7
  • 42
  • 57
  • I was not able to print the result (must be printed using bytes). I tried decode("utf-8") which did not work: AttributeError: decode – Bob Ebert Sep 27 '15 at 15:43
  • The hex representation of a packet may be printed via the statement `str(packet).encode("HEX")`. – Yoel Sep 27 '15 at 15:55
  • this is the output: pkt = str(pkt).encode("HEX") LookupError: 'HEX' is not a text encoding; use codecs.encode() to handle arbitrary codecs – Bob Ebert Sep 27 '15 at 15:57
  • In _Python3_ the statements `import binascii; binascii.hexlify(bytes(packet))` should work. – Yoel Sep 27 '15 at 16:09
  • Well this is the output: b'0001080006040002028261493d94c0a80501a45e60d56ea5c0a80533'... When it is supposed to print: – Bob Ebert Sep 27 '15 at 16:21
  • Oh, I thought you're interested in the hex representation of the packet. The output you're interested in may be printed by executing the statement `print(repr(packet))`. Note that there are other useful human-readable formats such as `packet.summary()`. – Yoel Sep 27 '15 at 16:37
  • Is there a way to do this with a specific timeout? – Edgecase Dec 21 '18 at 23:38
  • Never mind that last comment. Adding a timeout is as easy as adding the "timeout" option to the "sr" function. – Edgecase Dec 21 '18 at 23:49
2

I know this is a late answer but for anyone else, according to the latest version of scapy you can extract the mac from that arp response by indexing such as:

if you did something like this:

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

then you can extract the mac of remote ip with

ans[0][1][ARP].hwsrc

To my knowledge you cant extract it with regex. the above code will give you the mac address in string format.

Similarly you can extract all other fields by trial and error by messing with the indexes.