summaryrefslogtreecommitdiff
path: root/scripts/parse_dump.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/parse_dump.py')
-rwxr-xr-xscripts/parse_dump.py145
1 files changed, 145 insertions, 0 deletions
diff --git a/scripts/parse_dump.py b/scripts/parse_dump.py
new file mode 100755
index 0000000..d9cc44b
--- /dev/null
+++ b/scripts/parse_dump.py
@@ -0,0 +1,145 @@
+#!/usr/bin/python
+from scapy.all import *
+from binascii import *
+import base64
+import sys
+import dns.rdata
+import dns.rrset
+from struct import *
+
+fr = open(sys.argv[1] + ".raw_data", 'wb')
+fp = open(sys.argv[1] + ".parsed_data", 'wb')
+
+def chop_and_write_rr_query(rr):
+ name = dns.name.from_text(rr.qname)
+# print rr.qname
+
+ wire = name.to_wire()
+ fp.write(pack('B', len(wire)))
+# print len(wire)
+ fp.write(wire)
+ fp.write(pack('H', rr.qtype))
+ fp.write(pack('H', rr.qclass))
+
+def chop_and_write_rr_response(rr):
+ name = dns.name.from_text(rr.rrname)
+# print rr.rrname
+
+ wire = name.to_wire()
+ fp.write(pack('B', len(wire)))
+ fp.write(wire)
+ fp.write(pack('H', rr.type))
+ fp.write(pack('H', rr.rclass))
+ fp.write(pack('L', rr.ttl))
+
+ try:
+ rdata = dns.rdata.from_wire(rr.rclass, rr.type, rr.rdata, 0, len(rr.rdata))
+ fp.write(pack('H', len(rr.rdata)))
+# print "type ", rr.type, "length ", len(rr.rdata)
+# OPT has length 0 - it should have no rdata
+ rdata.to_wire(fp)
+ except:
+
+ try:
+# if rr.rdata[0] != '\#':
+ rdata = dns.rdata.from_text(rr.rclass, rr.type, rr.rdata)
+ try:
+ fp.write(pack('H', len(rdata)))
+ except:
+ # no length - no way to know wire length
+ try:
+# print "unknown length for type", rr.type
+# if rr.type == 2:
+# fp.seek(1, 1)
+# old = fp.tell()
+# rdata.to_wire(fp)
+# size = fp.tell() - old
+# fp.seek(-(size + 1), 1)
+# fp.write(pack('B', size))
+# fp.seek(0, 2)
+# else:
+ rdata.to_wire(fp)
+ except Exception as e:
+ print 'Error, exiting: ', e
+ sys.exit(-1)
+ except Exception as e:
+ print 'Error,', e
+ print 'could not parse rdata type: ', rr.type
+ print 'dumping directly (hopefully it is SOA)'
+# i need to do some kind of rollback here...
+ fp.write(pack('H', len(rr.rdata)))
+ fp.write(rr.rdata)
+
+
+ if rr.type == 50:
+ f = open('nsec3debug', 'wb')
+ rdata.to_wire(f)
+ f.close()
+
+def chop_and_write_section_response(section):
+ if section == None:
+ return
+ i = 0
+ rr = section.getlayer(i);
+ while rr != None:
+ chop_and_write_rr_response(rr)
+ i += 1
+ rr = section.getlayer(i)
+
+def chop_and_write_section_query(section):
+ if section == None:
+ return
+ i = 0
+ rr = section.getlayer(i);
+ while rr != None:
+ chop_and_write_rr_query(rr)
+ i += 1
+ rr = section.getlayer(i)
+
+def chop_and_write_packet(packet):
+ fp.write(pack('H', packet.id))
+# fp.write(pack('H', packet.qr))
+# fp.write(pack('H', packet.opcode))
+# fp.write(pack('H', packet.aa)) #TODO these are not uint16_t
+# fp.write(pack('H', packet.rcode))
+ fp.write(pack('H', packet.qdcount))
+ fp.write(pack('H', packet.ancount))
+ fp.write(pack('H', packet.nscount))
+ fp.write(pack('H', packet.arcount))
+
+#write query flag
+ fp.write(pack('H', packet.qr))
+
+ chop_and_write_section_query(packet.qd)
+ chop_and_write_section_response(packet.an)
+ chop_and_write_section_response(packet.ns)
+ chop_and_write_section_response(packet.ar)
+
+packets = rdpcap(sys.argv[1])
+
+total_length = len(packets)
+
+fr.write(pack('L', total_length))
+fp.write(pack('L', total_length))
+
+for packet in packets:
+ try:
+ data = a2b_hex(str(packet['DNS']).encode('hex'))
+ fr.write(pack('H', packet.qr))
+ fr.write(pack('H', len(data)))
+ fr.write(data)
+ chop_and_write_packet(packet['DNS'])
+ except IndexError:
+ print 'non-DNS packet'
+ total_length -= 1
+
+fr.seek(0)
+fp.seek(0)
+
+fr.write(pack('L', total_length))
+fp.write(pack('L', total_length))
+
+print 'written ', total_length, 'packets'
+
+fr.close()
+fp.close()