Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

psrc property of ARP packet returns invalid text instead of IP address in some cases #4420

Open
stijnh92 opened this issue Jun 11, 2024 · 2 comments

Comments

@stijnh92
Copy link

stijnh92 commented Jun 11, 2024

Brief description

Hey guys. We have been using the scapy library to parse the result of a tcpdump process in which we perform the arping function for quite a while now with success.

Until a few days ago it started behaving weird when printing the replies of a packet. We are interested in which IP address is being returned by some MAC address. To do so, we use the rdpcap module, loop over the sessions and get the packet[Ether].src for the MAC address and the packet[ARP].psrc for the IP address.

In some cases, the IP address contains some weird ASCII entries like b'\ns\x14g' or b'\ns\x14f'.

Is there something wrong with the way we parse the results from the ARP replies, or is something else wrong? Thanks in advance!

Scapy version

2.5.0

Python version

3.9.18

Operating system

Linux 5.14.0-427.13.1.el9_4.x86_64 (RHEL 10)

Additional environment information

No response

How to reproduce

The function to start the tcpdump process and the arping call:

def perform_arp_request(range, interface, pcap_filename):
    # first start tcpdump process in the background
    process = Popen(
        ['tcpdump', '-i', interface, '-w', pcap_filename, '-s', '65535', 'arp', 'and', 'arp[7]', '==', '2'],
        stdout=DEVNULL,
        stderr=DEVNULL
    )
    arping(range, iface=interface, verbose=False)
    sleep(1)
    process.terminate()

The function to parse the results from the tcpdump file:

def parse_and_print_results(pcap_filename):
    data = set()
    pcap_flow = rdpcap(pcap_filename)
    sessions = pcap_flow.sessions()
    for session in sessions:
        for packet in sessions[session]:
            data.add((packet[Ether].src, packet[ARP].psrc))

    for mac, ip in data:
        print(mac + ',' + ip)

Actual result

The following error is thrown:
TypeError: can only concatenate str (not "bytes") to str

It happens here:

print(mac + ',' + ip)

Because IP in this case is equal to b'\ns\x14h'. So it seems like the expected IP of 10.115.20.104 as seen from parsing the pcap file is evaluated to some weird string. Also note in the pcap file that for this case, there are 2 ARP replies from that IP. Don't know if it's related.

Expected result

00:50:56:95:e3:b3,10.115.20.7,
00:50:56:95:58:14,10.115.20.25
b4:96:91:4e:9c:c5,10.115.20.104
00:50:56:aa:da:db,10.115.20.22
00:50:56:95:73:c4,10.115.20.20

Related resources

13:50:15.471285 ARP, Reply 10.115.20.7 is-at 00:50:56:95:e3:b3 (oui Unknown), length 46
13:50:15.474909 ARP, Reply 10.115.20.25 is-at 00:50:56:95:58:14 (oui Unknown), length 46
13:50:15.489031 ARP, Reply 10.115.20.104 is-at b4:96:91:4e:9c:c5 (oui Unknown), length 46
13:50:15.489031 ARP, Reply 10.115.20.104 is-at b4:96:91:4e:9c:c5 (oui Unknown), length 46
13:50:15.475548 ARP, Reply 10.115.20.22 is-at 00:50:56:aa:da:db (oui Unknown), length 46
13:50:15.474909 ARP, Reply 10.115.20.25 is-at 00:50:56:95:58:14 (oui Unknown), length 46

Debug script

Run this script with a pcap file as argument (e.g. python3 scapy_debug.py some_dump.pcap)

import sys

from scapy.layers.l2 import arping, Ether, ARP
from scapy.utils import rdpcap


def parse_and_print_results(pcap_filename):
    data = set()
    pcap_flow = rdpcap(pcap_filename)
    sessions = pcap_flow.sessions()
    for session in sessions:
        for packet in sessions[session]:
            data.add((packet[Ether].src, packet[ARP].psrc))

    for mac, ip in data:
        try:
            print(mac + ',' + ip)
        except:
            print('---- ERROR ----')
            print(ip)
            print(mac)
            print('---------------')


if __name__ == "__main__":
    parse_and_print_results(sys.argv[1])                                        
@stijnh92
Copy link
Author

I can provide a full pcap file if that is of any help?

@gpotter2
Copy link
Member

That's interesting.
Could you retry using master? If that still doesn't work, a pcap would indeed greatly help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants