kbandla / dpkt

fast, simple packet creation / parsing, with definitions for the basic TCP/IP protocols
Other
1.09k stars 270 forks source link

Parsing truncated DNS packets #498

Closed brightpinefield closed 3 years ago

brightpinefield commented 3 years ago

I'm trying to dump DNS data out of pcaps that are truncated to the first 100 bytes. Found a script here https://mmishou.wordpress.com/2010/04/13/passive-dns-mining-from-pcap-with-dpkt-python/ to test dpkt but it seems to not go past the "try: dns = dpkt.dns.DNS(udp.data)" .. it hits the continue and I get nothing.. is it possible to use dpkt with truncated packets? I have data in the DNS packet (see screenshot) that I was hoping to get at..

Screen Shot 2020-12-10 at 2 06 19 PM

kbandla commented 3 years ago

@brightpinefield would it be possible for you to share the pcap? I suspect that lib will fail with dpkt.UnpackError, but wanted to check.

brightpinefield commented 3 years ago

@kbandla Sure. I've attached it..Thx for the help!

test.pcap.zip

kbandla commented 3 years ago

Yes, there is way to parse truncated data! We do this by first creating a dns object and then calling the unpack method, with the UDP data. This will populate the fields in the dns object as far as data in the packet is available, till an exception is raised.
However note that print(dns_object) function will fail because it will internally call the unpack routine again, leading to failure.

Example:

....
for ts, buf in pcap:
    try:
        eth = dpkt.ethernet.Ethernet(buf)
        if eth.type != 2048:
            continue
        ip = eth.data
        if ip.p != 17:
            continue
        udp = ip.data
        if udp.sport != 53 and udp.dport != 53:
            continue
        dns = dpkt.dns.DNS()        # <---- THIS
        dns.unpack(udp.data)        # <---- HERE
    except Exception as e:
        print('ErrorParsingDNS: %s'%e)
        print('Warning: Not all DNS fields might have been populated')

    if dns.qr != dpkt.dns.DNS_R:
        continue
    if dns.opcode != dpkt.dns.DNS_QUERY:
        continue
    if dns.rcode != dpkt.dns.DNS_RCODE_NOERR:
        continue
    if len(dns.an) < 1:
        continue

    for answer in dns.an:
        if answer.type == 5:
            print('CNAME: %s - %s'%(answer.name, answer.cname))
        elif answer.type == 1:
            print('A: %s - %s'%(answer.name, answer.ip))
        # etc
....
brightpinefield commented 3 years ago

Hey Kiran! Ah cool.. Thanks a lot for the help on this! Really appreciate it!

brifordwylie commented 3 years ago

@kbandla I also didn't realize you could do this.. I think this would be a good addition to our examples/ scripts. I'll gen up a script in the next couple of days and have you review it.

brifordwylie commented 3 years ago

@brightpinefield would it be okay if I put the PCAP above in the dpkt examples/data? I've got an example script for truncated packets.

brightpinefield commented 3 years ago

@brifordwylie sure, go ahead.

brifordwylie commented 3 years ago

Kewl.. here's the example script to parse truncated DNS https://github.com/kbandla/dpkt/blob/master/examples/print_dns_truncated.py