python解析数据包_Python解析DNS数据包 - 于乐乐

该代码段实现了解析DNS响应消息体的功能,同时能够识别TCP和UDP协议。通过读取pcap文件,它能捕获IP包,并从中提取DNS请求和响应的详细信息,包括源IP、目标IP、端口号以及DNS查询类型。当接收到DNS响应且查询类型为A记录时,会解析并返回对应的IP地址。
摘要由CSDN通过智能技术生成

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()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值