0

Trying to parse DNS responses with Scapy (see function below). My issue is all of the answers in the rdata[] field are not showing. When I do a packet capture with Wireshark, I see multiple answers in the rdata[] field, there are usually two or three answers in a single response packet for those unfamiliar with DNS.

I am only returned with one of the answers (the first). I have tried using sr() instead of sr1() and have also tried adding multi=True as a parameter when sending the packet but neither of these work.

Any ideas?

def send_query_recursion(resolver, target):
dns_req = IP(dst=f'{resolver}')/UDP(dport=53)/DNS(qr=0, rd=1, qd=DNSQR(qname=f'{target}'))
answer = sr1(dns_req, verbose=1)
for received in answer:
    if received.haslayer(DNS):
        for x in received:
            print(str(x[DNS].id))
            print("rrname: " + str(x[DNSRR].rrname))
            print("Type: " + str(x[DNSRR].type))
            if str(x[DNSRR].rclass) == "1":
                print("Class: " + str(x[DNSRR].rclass) + " IN")
            print("TTL: " + str(x[DNSRR].ttl))
            print("Resource Data Length: " + str(x[DNSRR].rdlen))
            print("Resource Data: " + str(x[DNSRR].rdata[:-1]))

1 Answers1

0

I have the same issue as you do. I could not resolve it using scapy, so I have used dpkt package to parse the answer of the DNS responses as follow (python 3):

with open('your_pcap.pcap', 'rb') as f:
        pcap = dpkt.pcap.Reader(f)
        for timestamp, buf in pcap:
            try:
                eth = dpkt.ethernet.Ethernet(buf)
            except:
                continue
            if eth.type != 2048:
                continue
            try:
                ip = eth.data
            except:
                continue
            if ip.p != 17:
                continue
            #filter on UDP assigned ports for DNS
            try:
                udp = ip.data
            except:
                continue
            if udp.sport != 53 and udp.dport != 53:
                continue
            #make the dns object out of the udp data and
            #check for it being a RR (answer) and for opcode QUERY
            try:
                dns = dpkt.dns.DNS(udp.data)
            except:
                continue
            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 qname in dns.qd:
                print("The DNS response packet has ", len(dns.an), " answers")
                print("The answers (in a list) are: ", dns.an)

You can find additional information on parsing DNS using dpkt on the following pages:

https://dpkt.readthedocs.io/en/latest/_modules/dpkt/dns.html

https://mmishou.wordpress.com/2010/04/13/passive-dns-mining-from-pcap-with-dpkt-python/

ali
  • 1
  • 1