第二十九天:DNS数据包分析

   前些日子分析了数据链路,网络层,传输层的数据包后,今天的认为是分析应用层的数据包,应用有千千万万,这次分析的是DNS的数据包。    DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。通过主机名,最终得到该主机名对应的IP地址的过程叫做域名解析(或主机名解析)。DNS协议运行在UDP协议之上,使用端口号53.--摘自百度百科。

  第一步是查找dns协议格式。英文好直接看相关的RFC文档最好,这次就直接看的其它博客的协议介绍。

 下面的协议格式介绍摘自 http://blog.csdn.net/lastsweetop/article/details/5692312

DNS报文格式:

该报文由12字节的首部和4个长度可变的字段组成。

标识字段由客户程序设置并有服务器返回结果。

16bit的标志字段 如下:

QR:0表示查询报文,1表示响应报文

Opcode:通常值为0(标准查询),其他值为1(反向查询)和2(服务器状态请求)。

AA:表示授权回答(authoritative answer).

TC:表示可截断的(truncated)

RD:表示期望递归

RA:表示可用递归

随后3bit必须为0

Rcode:返回码,通常为0(没有差错)和3(名字差错)

后面4个16bit字段说明最后4个变长字段中包含的条目数。

问题部分:

报文格式:

查询名为要查找的名字,它由一个或者多个标示符序列组成。每个标示符已首字节数的计数值来说明该标示符长度,每个名字以0结束。计数字节数必须是0~63之间。该字段无需填充字节。如:gemini.tuc.noao.edu

每个问题有一个查询类型,通常查询类型为A(由名字获得IP地址)或者PTR(获得IP地址对应的域名)

资源记录部分:

报文格式:

DNS最后3个字段,回答字段,授权字段和附加信息字段均采用资源记录RR(Resource Record)的相同格式。

域名是记录中资源数据对应的名字。它的格式和查询名字段格式相同。

类型说明R R的类型码。类通常为1,指I n t e r n e t数据。

生存时间字段是客户程序保留该资源记录的秒数。

资源数据长度说明资源数据的数量。该数据的格式依赖于类型字段的值。对于类型1(A记录)资源数据是4字节的I P地址。

数据包DNS 查询:(DNS query)

0000  00 19 56 6e 19 bf 00 17  a4 1a b2 e0 08 00 45 00   ..Vn.... ......E.

0010  00 3b ed c6 00 00 80 11  e3 c3 ac 15 0f 04 ac 15   .;...... ........

0020  01 f9 04 a9 00 35 00 27  2f bd 3e 3a 01 00 00 01   .....5.‘ /.>:....

0030  00 00 00 00 00 00 03 77  77 77 06 67 6f 6f 67 6c   .......w ww.googl

0040  65 02 63 6e 00 00 01 00  01                        e.cn.... .      

说明:

前面三段分别为以太网包头,ip包头和UDP包头。

从0020行后面开始为DNS数据包.

3e 3a  为标识字段

01 00 为标志字段,该字段设置了TC表示该报文是可截断的。

00 01  查询报文数量为1。

00 00 00 00 00 00 表示回答,授权和额外信息都为0。

03 77  77 77 06 67 6f 6f 67 6c 65 02 63 6e 00 表示查询的名字为www.google.com

00 01 为类型,1表示A查询

00 01 为类,1表示Internet数据。

 

数据包 DNS response (DNS response)

0000  00 17 a4 1a b2 e0 00 19  56 6e 19 bf 08 00 45 00   ........ Vn....E.

0010  00 78 48 af 00 00 7d 11  8b 9e ac 15 01 f9 ac 15   .xH...}. ........

0020  0f 04 00 35 04 a9 00 64  75 db 3e 3a 81 80 00 01   ...5...d u.>:....

0030  00 03 00 00 00 00 03 77  77 77 06 67 6f 6f 67 6c   .......w ww.googl

0040  65 02 63 6e 00 00 01 00  01 c0 0c 00 05 00 01 00   e.cn.... ........

0050  00 05 42 00 11 02 63 6e  01 6c 06 67 6f 6f 67 6c   ..B...cn .l.googl

0060  65 03 63 6f 6d 00 c0 2b  00 01 00 01 00 00 00 5f   e.com..+ ......._

0070  00 04 cb d0 21 65 c0 2b  00 01 00 01 00 00 00 5f   ....!e.+ ......._

0080  00 04 cb d0 21 64                                  ....!d          

说明:

前面三段分别为以太网包头,ip包头和UDP包头。

3e 3a  为标识字段

81 80  为标志字段,其中设置了QR = 1,RD = 1,RA = 1

00 01  问题数100 03  回答数3,其余两个为0

03 77  77 77 06 67 6f 6f 67 6c 65 02 63 6e 00 表示查询的名字为www.google.com

00 01 为类型,1表示A查询

00 01 为类,1表示Internet数据。

接下来为回答报文,

c0 0c 为域名指针

00 05  表示CNAME(规范名称)

00 01  类,表示为Internet数据

00 00 05 42  生存时间

00 11  数据长度

02 63 6e  01 6c 06 67 6f 6f 67 6c 65 03 63 6f 6d 00 为数据 cn.l.google.cn

然后接下来两段为另外两个回答。

最后的数据为IP地址。

今天的程序就是根据上面的格式描述,编写代码,实现的功能是分析dns应答包和请求包内容。将应答包中数据的ip地址显示出来。比如在终端ping www.baidu.com 应答包中就会有百度的ip地址。下面是代码实现: 

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <linux/if_ether.h>
  4 #include <linux/ip.h>
  5 #include <linux/udp.h>
  6 #include <linux/tcp.h>
  7 #include <netinet/in.h>
  8 #include <stdlib.h>
  9 #include <string.h>
 10
 11 #pragma pack(1)
 12 struct my_dnshdr{
 13     unsigned short mark;
 14     unsigned short sign;
 15     unsigned short problem_cout ;
 16     unsigned short resourc_record;
 17     unsigned short accredit_record;
 18     unsigned short extra_record;
 19 };
 20 struct my_dnsrr{
 21     unsigned short domain ;
 22     unsigned short type;
 23     unsigned short class;
 24     unsigned long ttl;
 25     unsigned short len;
 26
 27 };
 28 void show_mac(const unsigned char *data);
 29 void show_ip(const unsigned char *data);
 30 void show_udp(const unsigned char *data);
 31 void show_app(const unsigned char *data);
 32
 33 int main()
 34 {
 35     int fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
 36     if(fd < 0){
 37         perror("socket");
 38         return 1;
 39     }
 40
 41     int ret = 0;
 42     int i = 0;
 43     unsigned char buff[1024] = {0};
 44     while(1){
 45         memset(buff, 0, 1024);
 46         ret = read(fd, buff, 1024);
 47         if(ret < 0){
 48             perror("read");
 49             continue;
 50         }
 51         if(ret < 42)
 52             continue;
 53         unsigned short *tmp = (unsigned short *) (buff + 14 + 20);
 54         unsigned indns = ntohs(*tmp);
 55         unsigned outdns = ntohs(*tmp+1);
 56         if( indns == 53 || outdns == 53){
 57
 58             show_mac(buff);
 59             printf("\n\n\n");
 60         }
 61     }
 62
 63 }
 64
 65 void show_mac(const unsigned char *data){
 66     struct ethhdr *eth = (struct ethhdr *)data;
 67     if(ntohs(eth->h_proto)==0x0800)
 68         show_ip(data+sizeof(struct ethhdr));
 69 }
 70 void show_ip(const unsigned char *data){
 71
 72     struct iphdr *ipth = (struct iphdr *)data;
 73     if(ipth->protocol==17)
 74         show_udp(data+sizeof(struct iphdr));
 75 }
 76 void show_udp(const unsigned char *data){
 77     struct udphdr *udpth = (struct udphdr *)data;
 78     show_app(data+sizeof(struct udphdr));
 79 }
 80 void show_app(const unsigned char *data){
 81
 82     int i = 1;
 83     printf("--------------dns分析-----------\n");
 84     struct my_dnshdr *dns = (struct my_dnshdr*)data;
 85     printf("mark is %x\n",ntohs(dns->mark));
 86     printf("sign is %x\n",ntohs(dns->sign));
 87     printf("problem_cout is %04x\n",ntohs(dns->problem_cout ));
 88         printf("resourc_record is %04x\n",ntohs(dns->resourc_record));
 89         printf("accredit_record is %04x\n",ntohs(dns->accredit_record));
 90         printf("extra_record is %04x\n",ntohs(dns->extra_record));
 91     printf("---------------you ask question is ----------\n");
 92     unsigned char *question_hdr = (unsigned char *)(data + 12);
 93     i = 1;
 94     while(1){
 95         if(*(question_hdr+i) == 0x00)
 96             break;
 97         if(*(question_hdr + i) < 10){
 98             printf(".");
 99             i++;
100             continue;
101         }
102         printf("%c",*(question_hdr + i));
103         i++;
104     }
105     unsigned short *question_type =(unsigned short *)(data + 12 + i + 1);
106     printf("\tthe question_type is %04x",ntohs(*question_type));//类型为一表示A类查询,由名字获取ip
107
108     unsigned short *question_class =(unsigned short *)(data + 12 + i + 1 + 2);
109     printf("\tthe question_class is %04x\n",ntohs(*question_class));//类为一表示internet数据
110
111     printf("---------------resv question is ----------\n");
112     struct my_dnsrr *dnsrr = (struct my_dnsrr *)(data+12+i+1+2+2);
113     printf("domain is %x\n", ntohs(dnsrr->domain));//域名指针
114     printf("type is %04x\n",ntohs(dnsrr->type));//类型
115     printf("class is %04x\n",ntohs(dnsrr->class));//类
116     printf("ttl is %04x\n", ntohl(dnsrr->ttl));//生存时间
117     printf("len is %04x\n",ntohs(dnsrr->len));//资源长度
118     int len = 12+i+1+2+2 + sizeof(struct my_dnsrr) ;
119     if(ntohs(dnsrr->len) == 4){
120         unsigned long *ipaddr = (unsigned long *)(data+len );
121         printf("ip is %s\n",inet_ntoa(*ipaddr));
122
123     }
124     else{
125     i = 1;
126     while(1){
127         if(*(question_hdr+i) == 0x00)
128             break;
129         if(*(question_hdr + i) < 10){
130             printf(".");
131             i++;
132             continue;
133         }
134         printf("%c",*(question_hdr + i));
135         i++;
136     }
137     printf("\n");
138     }
139     if(ntohs(dns->resourc_record) == 3){
140         len = len + ntohs(dnsrr->len);
141             dnsrr = (struct my_dnsrr *)(data + len );
142         printf("domain is %x\n", ntohs(dnsrr->domain));//域名指针
143         printf("type is %04x\n",ntohs(dnsrr->type));//类型
144         printf("class is %04x\n",ntohs(dnsrr->class));//类
145         printf("ttl is %04x\n", ntohl(dnsrr->ttl));//生存时间
146         printf("len is %04x\n",ntohs(dnsrr->len));//资源长度
147         len = len + sizeof(struct my_dnsrr);
148         if(ntohs(dnsrr->len) == 4){
149             unsigned long *ipaddr = (unsigned long *)(data+len );
150             printf("ip is %s\n",inet_ntoa(*ipaddr));
151
152         }
153         len = len + ntohs(dnsrr->len);
154             dnsrr = (struct my_dnsrr *)(data + len );
155         printf("domain is %x\n", ntohs(dnsrr->domain));//域名指针
156         printf("type is %04x\n",ntohs(dnsrr->type));//类型
157         printf("class is %04x\n",ntohs(dnsrr->class));//类
158         printf("ttl is %04x\n", ntohl(dnsrr->ttl));//生存时间
159         printf("len is %04x\n",ntohs(dnsrr->len));//资源长度
160         len = len + sizeof(struct my_dnsrr);
161         if(ntohs(dnsrr->len) == 4){
162             unsigned long *ipaddr = (unsigned long *)(data+len );
163             printf("ip is %s\n",inet_ntoa(*ipaddr));
164
165         }
166
167
168     }
169
170 }

    上面的代码存在的问题:1、重复代码多,后面的记录分析可以写成函数实现。2、查询名代码有bug,当域名中字符超过10个就会出错,编写代码时图方便,不应该,写博客的时候还不改,更不改,还有同样要写成函数。

   下面是运行代码的截图:

  

时间: 2024-10-14 20:52:02

第二十九天:DNS数据包分析的相关文章

Wireshark数据包分析之DNS协议包解读

*此篇博客仅作为个人笔记和学习参考 DNS协议包格式 DNS资源记录类型 DNS数据包分析(查询) Domain Name System (query)[Response In: 16]Transaction ID: 0x0002 #DNS ID号#Flags: 0x0100 Standard query #标志#0... .... .... .... = Response: Message is a query ##响应信息,该值为0,表示一个DNS查询.000 0... .... ....

第二十九天 月出惊山鸟 —Spring的AOP_AspectJ @annotation

6月14日,阴转雨."四面垂杨十里荷,向云何处最花多, 画楼南畔夕阳和.天气乍凉人寂寞, 光阴须得酒消磨,且来花里听笙歌." 面向切面的框架AspectJ邂逅Spring,不仅造就一种简洁,更带来更多的选择空间. 上篇的切面与代理配置方式,麻烦且繁琐.好在Spring 与 AspectJ 进行了集成,从接口和配置的泥潭爬出,善莫大焉. 下面把上一篇Spring的AOP 的例子改写一下,达到同样的效果. 1-3步骤不变. 4.定义一个 Aspect 切面类BallHandler.java

基于Jpcap的TCP/IP数据包分析(一)

基于Jpcap的TCP/IP数据包分析原作:赵新辉目 录第一章 以太网的结构和TCP/IP1.1 以太网的结构1.1.1 基于网络架构的以太网1.1.2 以太网的数据交换1.1.3 以太网帧的结构1.2 IP数据报的构成 1.2.1 IP地址1.2.2 路由1.2.3 IP数据报的构成1.2.4 其他报文结构1.3 TCP/UDP1.3.1 TCP/UDP的作用1.3.2 TCP和UDP报文的结构第二章 Jpcap类库2.1 Jpcap的使用2.1.1 Jpcap的运行环境的安装2.1.2 Jp

Python解析DNS数据包

工作中有时需要对DNS数据包进行解析,抽取出其中的Qurey Name和Answer中的IP地址,今天写了一个简单的脚本分析PCAP包中的DNS,用到了dpkt模块. 我只抽取了关键的Query Name和Answer中的IP地址,没有解析授权和额外信息. 如果不想写脚本,可以使用tshark工具(wireshark的命令行版本),使用简单的命令行即可抽取想要的信息.但是tshark在抽取IP地址的时候,会将授权域和额外域中的IP地址也会一起抽取出来,难以区分. 1 #!/usr/bin/pyt

网络数据包分析 网卡Offload

http://blog.nsfocus.net/network-packets-analysis-nic-offload/ 对于网络安全来说,网络传输数据包的捕获和分析是个基础工作,绿盟科技研究员在日常工作中,经常会捕获到一些大小远大于MTU值的数据包,经过分析这些大包的特性,发现和网卡的offload特性有关,本文对网卡Offload技术做简要描述. 文章目录 网络分片技术 网卡offload机制 发送模式 接收模式 网卡offload模式的设置 Linux windows 网卡Offload

tcprstat源码分析之tcp数据包分析

tcprstat是percona用来监测mysql响应时间的.不过对于任何运行在TCP协议上的响应时间,都可以用. tcprstat和tcpdump一样,使用libpcap库进行抓包,然后再通过程序对抓取的tcp包进行分析. 1.通过分析来源ip和目标ip,看那个ip是本地ip,来判断是进来的包(请求包)还是出去的包(响应包).2.如果包的数据大小为0,那么就跳过,不再处理.数据大小为0的视为tcp控制包.3.如果数据包为进来的包(请求包),则插入一条记录到哈希表.4.如果数据包为出去的包(响应

&nbsp; 使用tshark进行数据包分析

选项说明Options -r 读取数据包 -C 选择对应的配置文件 -d 解码为... -D 通过行进行打印输出 -e 定义需要打印的行内容 -E 定义具体的打印格式 -T 定义具体的打印方式 命令tshark -d <layer type>==<selector>,<decode-as protocol> tshark -r vmx.cap -d tcp.port==446,http 命令注解 在一些分析中可能会遇到接口信息没有采用标准的类型所以可以通过-d选项将其解

firebug登陆之数据包分析

登陆之数据包分析 工具: python-urllib2   |  firefox+firebug或者chrome,用浏览器打开登陆页面之后,按F12键会默认打开开发者工具或者启动firebug,点击network监听数据包,下面以itune的登陆举一个例子. 1. 在浏览器中输入itunes的登陆地址:https://itunesconnect.apple.com/itc/static /login?view=1&path=%2FWebObjects%2FiTunesConnect.woa,同时

数据包分析2

VLAN 数据包分析2 实验拓扑 PC1发送一个目的是PC2的数据包,SW1的G0/1接口接收,因为G0/1是ACCESS口,属于VLAN3,所有打上VLAN 3的标签接收,SW1的G0/2接口是TRUNK,PVID为3,而PC1发送的数据包的标签也是3,所有,脱掉标签发送,SW2的G0/2接口为ACCESS口,属于VLAN3,接收到一个不带标签的数据帧,所有打上VLAN3的标签接收,SW2的G0/1接口是ACCESS ,也属于VLAN3,所有数据帧会在这个接口转发出去,因为SW2的G0/1是A