struggling_learner
struggling_learner

Reputation: 1258

Intercepting DNS requests - deducing QR, Opccode, AA, TC etc

Was trying to intercept incoming DNS requests by spinning up a small udp server and ended up trying https://stackoverflow.com/a/16981944/9488865.

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

To deduce QR, opcode, AA, TC etc, we are doing:

DNS_QUERY_MESSAGE_HEADER = struct.Struct("!6H")
id, misc, qdcount, ancount, nscount, arcount = DNS_QUERY_MESSAGE_HEADER.unpack_from(message)

qr = (misc & 0x8000) != 0
opcode = (misc & 0x7800) >> 11
aa = (misc & 0x0400) != 0
tc = (misc & 0x200) != 0
rd = (misc & 0x100) != 0
ra = (misc & 0x80) != 0
z = (misc & 0x70) >> 4
rcode = misc & 0xF

While Scapy makes it all super easy (https://stackoverflow.com/a/6732956/9488865), I would like to use this opportunity to learn a bit more here.

How can I find out to use 0x8000, 0x7800, 0x0400 .. 0x70, 0xF etc for doing those ANDs? How do we find and lock in on those values?

Upvotes: 0

Views: 252

Answers (1)

Patrick Mevzek
Patrick Mevzek

Reputation: 12485

The DNS wire format is defined in https://www.rfc-editor.org/rfc/rfc1035.txt

For example you have this:

4.1.1. Header section format

The header contains the following fields:

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      ID                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    QDCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ANCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    NSCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ARCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

What you see on top are bytes, and hence will show the necessary offsets to apply to get each specific part.

You can also study how current DNS parsers/generators library do it, for example in Python: https://github.com/rthalley/dnspython/blob/master/dns/message.py#L732

Upvotes: 1

Related Questions