3

I'm trying to use Python to parse hex-formated DNS RDATA-values (should be RFC1035-compliant) that's generated in audit logs from Windows DNS Server when a record is created or deleted. I've tried a couple of Python dns-modules and think I'm getting close with dnslib, however all the documentation I find is for parsing a complete DNS-packet captured from the network including question and answer header ++.

The audit log only provides the class type and the RDATA it stores in AD (Active Directory-integrated zone), so I figured I might be able to use the parse(buffer,length) method of the individual record type-classes to parse it, but so far all my attempts are failing.

Sample data:

Type = MX

RDATA = 0A0011737276312E636F6E746F736F2E636F6D2E

Which should be parsed to:

preference = 10

mx = srv1.contoso.com.

Latest attempt:

import dnslib
import binascii

mxrdata = binascii.unhexlify(b'0A0011737276312E636F6E746F736F2E636F6D2E')
b = dnslib.DNSBuffer(mxrdata)
mx = dnslib.MX.parse(b,len(b))

this fails with:

Traceback (most recent call last):
  File "C:\Python37-32\lib\site-packages\dnslib\dns.py", line 1250, in parse
    mx = buffer.decode_name()
  File "C:\Python37-32\lib\site-packages\dnslib\label.py", line 235, in decode_name
    (length,) = self.unpack("!B")
  File "C:\Python37-32\lib\site-packages\dnslib\buffer.py", line 103, in unpack
    data = self.get(struct.calcsize(fmt))
  File "C:\Python37-32\lib\site-packages\dnslib\buffer.py", line 64, in get
    (self.offset,self.remaining(),length))
dnslib.buffer.BufferError: Not enough bytes [offset=20,remaining=0,requested=1]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python37-32\lib\site-packages\dnslib\dns.py", line 1254, in parse
    (buffer.offset,e))
dnslib.dns.DNSError: Error unpacking MX [offset=20]: Not enough bytes [offset=20,remaining=0,requested=1]

Can anyone help me? Is it even possible using this module?

2
  • In all generic case, you can not parse just part of the message: due to name compression, names in the packet can use pointers pointing anywhere (almost) in the packet so if you just take a part of it, you may be missing some data. Commented Sep 3, 2019 at 5:59
  • If this was a network capture, I might agree. However this is the actual rdata being stores in the database when modifying a record, provided directly in the server log from the vendor (MS), so I'm 100% sure it should be safe to parse it. Commented Sep 3, 2019 at 6:14

1 Answer 1

2

You are encoding the RDATA wrongly a bit:

First, you specify the preference:

0A00

However, this is not 10 (because integer are encoded MSB first, not LSB first), but 2560. So this should be

000A

Then, you try to encode the hostname here:

11737276312E636F6E746F736F2E636F6D2E

0x11 should be the length byte and the rest is the domain name srv1.contoso.com.. But this is not how encoding a hostname works. You have to encode each label separately with a length byte and terminate the hostname with a 0-length label. So this should be:

04 73727631 07 636F6E746F736F 03 636F6D 00
   s r v 1  .  c o n t o s o  .  c o m  .

This adds up to:

mxrdata = binascii.unhexlify(b'000A047372763107636F6E746F736F03636F6D00')

Them the parser should succeed. So if you really get the RDATA in such an invalid format, you have to convert it first in to make it rfc1035-compliant.

Sign up to request clarification or add additional context in comments.

3 Comments

"You are encoding the RDATA wrongly a bit:" I understood that the OP is saying that he gets the data from the log, so he is not responsible for the string he gets.
A MS consultant told me it should be RFC1035 compliant using ASCII/UTF8. The little endian situation difference seems logical considering dnslib is intended for network packets using network byte order (big endian) while this is the data saved to DB. The problem however is the error while parsing the remaining servername. I'll take a look at it when I get home, but you might be right that they are not following the RFC 100% as promised.
You're correct. I was provided invalid information about the format. They may follow the format (size, order++) for the records, but the labels are stored as pure ASCII/UTF8 and not using length-octets like the rfc1035 describes. This basically means all dns libraries won't work and we have to write the parser ourself as they don't provide any tools. :-(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.