1 #!/usr/bin/python
2 #coding = utf-8
3 importstruct4 importdpkt5 importsys6 importsocket7 importbinascii8
9 DNS_Q =010 DNS_R = 1
11
12 #Opcodes
13 DNS_QUERY =014 DNS_IQUERY = 1
15 DNS_STATUS = 2
16 DNS_NOTIFY = 4
17 DNS_UPDATE = 5
18
19 #Flags
20 DNS_CD = 0x0010 #checking disabled
21 DNS_AD = 0x0020 #authenticated data
22 DNS_Z = 0x0040 #unused
23 DNS_RA = 0x0080 #recursion available
24 DNS_RD = 0x0100 #recursion desired
25 DNS_TC = 0x0200 #truncated
26 DNS_AA = 0x0400 #authoritative answer
27
28 #Response codes
29 DNS_RCODE_NOERR =030 DNS_RCODE_FORMERR = 1
31 DNS_RCODE_SERVFAIL = 2
32 DNS_RCODE_NXDOMAIN = 3
33 DNS_RCODE_NOTIMP = 4
34 DNS_RCODE_REFUSED = 5
35 DNS_RCODE_YXDOMAIN = 6
36 DNS_RCODE_YXRRSET = 7
37 DNS_RCODE_NXRRSET = 8
38 DNS_RCODE_NOTAUTH = 9
39 DNS_RCODE_NOTZONE = 10
40
41 #RR types
42 DNS_A = 1
43 DNS_NS = 2
44 DNS_CNAME = 5
45 DNS_SOA = 6
46 DNS_PTR = 12
47 DNS_HINFO = 13
48 DNS_MX = 15
49 DNS_TXT = 16
50 DNS_AAAA = 28
51 DNS_SRV = 33
52
53 #RR classes
54 DNS_IN = 1
55 DNS_CHAOS = 3
56 DNS_HESIOD = 4
57 DNS_ANY = 255
58
59 defaddr2str(addrobj):60 if len(addrobj) != 4:61 return "addr error!"
62 else:63 return str(ord(addrobj[0]))+"."+str(ord(addrobj[1]))+"."+str(ord(addrobj[2]))+"."+str(ord(addrobj[3]))64
65 defTCPorUDP(obj):66 if (ord(obj) == 0x01):67 return "ICMP"
68 elif (ord(obj) == 0x02):69 return "IGMP"
70 elif (ord(obj) == 0x06):71 return "TCP"
72 elif (ord(obj) == 0x08):73 return "EGP"
74 elif (ord(obj) == 0x09):75 return "IGP"
76 elif (ord(obj) == 0x11):77 return "UDP"
78 elif (ord(obj) == 41):79 return "IPv6"
80 elif (ord(obj) == 89):81 return "OSPF"
82 else:83 return "error"
84
85 def dns_response_body_parse(body): #parse the response message's body
86 identification = body[0:2]87 flag = body[2:4]88 num_ques = body[4:6]89 num_ans_RR = body[6:8]90 num_auth_RR = body[8:10]91 num_addi_RR = body[10:12]92 query_name = ''
93 ans_ip =[]94 flag = 12
95 while(ord(body[flag])!=0x0):96 query_name = query_name + body[flag+1:flag+ord(body[flag])+1]97 flag = flag + ord(body[flag]) + 1
98 try:99 if ord(body[flag]) != 0x0:100 query_name = query_name+'.'
101 exceptException, e:102 print "error when parse query domain name"
103 #print query_name
104 flag = flag + 1
105 query_type = ord(body[flag])*256 + ord(body[flag+1])106 if query_type == 0x01: #use domain query IP addr
107 flag = flag + 4
108 i = 1
109 answer_num = ord(num_ans_RR[0])*256 + ord(num_ans_RR[1])110 while(i<=answer_num):111 if ord(body[flag]) == 0xc0:112 flag = flag + 2
113 else:114 while(ord(body[flag])!=0x0):115 flag = flag + ord(body[flag]) + 1
116 flag = flag + 1
117 if ( ord(body[flag])*256+ord(body[flag+1]) ==DNS_A118 and ord(body[flag+2])*256+ord(body[flag+3]) ==DNS_IN):119 flag = flag + 8
120 RR_data_len = ord(body[flag])*256 + ord(body[flag+1])121 if RR_data_len == 4:122 ans_ip.append(addr2str(body[flag+2:flag+6]))123 flag = flag + ord(body[flag])*256 + ord(body[flag+1]) + 2
124 else:125 flag = flag + 8
126 flag = flag + ord(body[flag])*256 + ord(body[flag+1]) + 2
127 i = i + 1
128 else:129 print "query type is PTR not A"
130 return
131 return "%s\t%s"%(query_name,ans_ip)132
133 defmain():134 paralen =len(sys.argv)135 if paralen != 3:136 print ("there is only %d parameter, %s"%(paralen,sys.argv))137 print "no enough parameter!"
138 print "command should be: python *.py result.txt src_pcap_file.pcap"
139 return
140
141 print "parse result will write to:"+sys.argv[1]142 print "strat parse the pcap file:"+sys.argv[2]143
144 fw = open(sys.argv[1],"w")145 f = file(sys.argv[2],"rb")146 pcap =dpkt.pcap.Reader(f)147 for ts,buf inpcap:148 #fw.writelines("timestamp:"+str(ts)+"\tpacket len:"+str(len(buf))+"\n")
149 ethheader = buf[0:14]150 dstmac = ethheader[0:6]151 srcmac = ethheader[6:12]152 netlayer_type = ethheader[12:14]153 #fw.writelines("dstMAC:"+str(binascii.b2a_hex(dstmac))+"\tsrcMAC:"+str(binascii.b2a_hex(srcmac))+"\n")
154
155 pktheader = buf[14:34]156 trans_type = pktheader[9]157 srcip = pktheader[12:16]158 dstip = pktheader[16:20]159
160 #fw.writelines("dstIP:"+addr2str(dstip)+"\tsrcIP:"+addr2str(srcip)+"\n")
161 #fw.writelines("packet type:"+TCPorUDP(trans_type)+"\n")
162
163 if (ord(trans_type) == 0x11): #UDP
164 udpheader = buf[34:42]165 srcport = udpheader[0:2]166 dstport = udpheader[2:4]167 udplen = udpheader[4:6]168 #fw.writelines("srcport:"+str(ord(srcport[1])+ord(srcport[0])*16*16)+"\tdstport:"+str(ord(dstport[1])+ord(dstport[0])*16*16)+"\n\n")
169 bodylen = ord(udplen[0])*256+ord(udplen[1])-8
170 print "\ndns body length is"+str(bodylen)171 dnsbody = buf[42:(42+bodylen)]172 if (ord(dstport[0]) == 0x00 and ord(dstport[1]) == 0x35):173 print "this is a DNS Request"
174 elif (ord(srcport[0]) == 0x00 and ord(srcport[1]) == 0x35):175 print "this is a DNS Response"
176 fw.writelines(dns_response_body_parse(dnsbody)+"\n") #wirte result to file
177 else:178 printord(srcport[0]),ord(srcport[0])179 elif (ord(trans_type) == 0x06): #TCP
180 tcpheader = buf[34:54]181 srcport = tcpheader[0:2]182 dstport = tcpheader[2:4]183 #fw.writelines("srcport:"+str(ord(srcport[1])+ord(srcport[0])*16*16)+"\tdstport:"+str(ord(dstport[1])+ord(dstport[0])*16*16)+"\n\n")
184 f.close()185 print ("process %s has finished, the result was in file %s"%(sys.argv[2],sys.argv[1]))186 if __name__ == "__main__":187 main()