kbandla / dpkt

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

dns resource record pack not working in certain cases #443

Open timngo1 opened 5 years ago

timngo1 commented 5 years ago

I was trying to parse some dns requests/responses, edit some fields, and then write out the new packets when I noticed that for some inputs the newly written packets were messed up. I took out all my changes to the packet and still saw the same issue

    mdns = dpkt.dns.DNS (udp.data)
    udp.data = mdns
    p_write.writepkt(eth, ts)

tcpdump -vv -n -r rewrite.pcap .... bad udp cksum 0x6d58 -> 0xbb39!] 11938 q: A? www.youtube.com. 7/13/6 www.youtube.com. CNAME youtube-ui.l.google.com., youtube-ui.l.google.com. A 172.217.6.46, youtube-ui.l.google.com. A 172.217.6.78, youtube-ui.l.google.com. A 172.217.164.110, youtube-ui.l.google.com. A 216.58.195.78, youtube-ui.l.google.com. A 172.217.0.46, youtube-ui.l.google.com. A 172.217.5.110 ns: . NS f.root-servers.net., . NS m.^@^DM-,M-Y^En^@^@^B^@^A^@^@M-&M-^M^@^T^Af^Lroot-servers^Cnet^@^@^@^B^@^A^@^@.M-^M^@^D^AmM-@M-0^@^@^B^@^A^ ....

I think the issue occurs when the first RR has type DNS_CNAME and has the url in bytes in the rdata field

RR(name='www.youtube.com', type=5, ttl=43919, rlen=22, rdata=b'\nyoutube-ui\x01l\x06google\xc0\x18', cname='youtube-ui.l.google.com')

Then when dpkt is packing it into bytes it calls pack_rdata which will execute this

    def pack_rdata(self, off, label_ptrs):
        # XXX - yeah, this sux
        if self.rdata:
            return self.rdata

But this will not update label_ptrs so when the next RR object references youtube-ui.l.google.com it will pack the url again and create a ptr offset to the newly packed url and store that in label_ptrs.

b'... \xc0\x0c\x00\x05\x00\x01\x00\x00\xab\x8f\x00\x16\nyoutube-ui\x01l\x06google\xc0\x18\nyoutube-ui\x01l\x06google\xc0\x18\ ...'

I see that when I comment out return self.rdata it instead executes pack_name and correctly stores the label_ptrs and the newly written pcap looks the same as the source

A workaround is to just set rr.rdata = None for all the packets and pack_rdata figures it out.