一文教你如何用C代码解析一段网络数据包?

域名2025-11-04 14:13:355

本文的文教网络目的是通过随机截取的一段网络数据包,然后根据协议类型来解析出这段内存。何用

学习本文需要掌握的码解基础知识:

网络协议 C语言 Linux操作 抓包工具的使用

其中抓包工具的安装和使用见下文:

《一文包你学会网络数据抓包》

视频教学链接如下:

《教你如何抓取网络中的数据包!黑客必备技能》

一、截取一个网络数据包

通过抓包工具,析段随机抓取一个tcp数据包

科莱抓包工具解析出的数据数据包信息如下:

数据包的内存信息:

数据信息可以直接拷贝出来:

二、用到的文教网络结构体

下面,一口君就手把手教大家如何解析出这些数据包的何用信息。

我们可以从Linux内核中找到协议头的码解定义

以太头:

drivers\staging\rtl8188eu\include\if_ether.h   struct ethhdr {  unsigned char h_dest[ETH_ALEN]; /* destination eth addr */  unsigned char h_source[ETH_ALEN]; /* source ether addr */  unsigned short h_proto;  /* packet type ID field */ }; 

IP头

include\uapi\linux\ip.h   struct iphdr { #if defined(__LITTLE_ENDIAN_BITFIELD)  //小端模式  __u8 ihl:4,   version:4; #elif defined(__BIG_ENDIAN_BITFIELD)    //大端模式  __u8 version:4,   ihl:4; #endif  __u8 tos;  __u16 tot_len;  __u16 id;  __u16 frag_off;  __u8 ttl;  __u8 protocol;  __u16 check;  __u32 saddr;  __u32 daddr;  /*The options start here. */ }; 

tcp头

include\uapi\linux\tcp.h  struct tcphdr {  __be16 source;  __be16 dest;  __be32 seq;  __be32 ack_seq; #if defined(__LITTLE_ENDIAN_BITFIELD)  __u16 res1:4,   doff:4,   fin:1,   syn:1,   rst:1,   psh:1,   ack:1,   urg:1,   ece:1,   cwr:1; #elif defined(__BIG_ENDIAN_BITFIELD)  __u16 doff:4,   res1:4,   cwr:1,   ece:1,   urg:1,   ack:1,   psh:1,   rst:1,   syn:1,   fin:1; #else #error "Adjust your <asm/byteorder.h> defines" #endif   __be16 window;  __sum16 check;  __be16 urg_ptr; }; 

因为协议头长度都是按照标准协议来定义的,

所以以太长度是析段14, IP头长度是数据20, tcp头长度是文教网络20,

各个协议头对应的何用内存空间如下:

三、解析以太头

#define MAC_ARG(p) p[0],码解p[1],p[2],p[3],p[4],p[5]  struct ethhdr *ethh;  unsigned char *p = pkt;  ethh = (struct ethhdr *)p;  printf("h_dest:%02x:%02x:%02x:%02x:%02x:%02x \n", MAC_ARG(ethh->h_dest));  printf("h_source:%02x:%02x:%02x:%02x:%02x:%02x \n", MAC_ARG(ethh->h_source));  printf("h_proto:%04x\n",ntohs(ethh->h_proto));  注意,站群服务器数据包中的析段数据是网络字节序,如果要提取数据一定要注意字节序问题 ethh->h_proto 是数据short类型,占2个字节,所以存储到本地需要使用函数ntohs 其中: n:network 网络字节序 h:host 主机字节序 s:short 2个字节 l: long 4个字节 ntohl() :4字节网络字节序数据转换成主机字节序 htons() :2字节主机字节序数据转换成网络字节序 ntohs() :2字节网络字节序数据转换成主机字节序 htonl() :4字节主机字节序数据转换成网络字节序

当执行下面这条语句时,

ethh = (struct ethhdr *)p; 

结构体指针变量eth的成员对应关系如下:

最终打印结果如下:

四、解析ip头

解析ip头思路很简单,

就是从pkt头开始偏移过以太头长度(14字节)就可以找到IP头,

解析代码如下:

#define IP_ARG(p)  p[0],p[1],p[2],p[3]  /*  解析IP头 */ if(ntohs(ethh->h_proto) == 0x0800) {  iph = (struct iphdr *)(p + sizeof(struct ethhdr));  q = (unsigned char *)&(iph->saddr);  printf("src ip:%d.%d.%d.%dn",IP_ARG(q));  q = (unsigned char *)&(iph->daddr);  printf("dest ip:%d.%d.%d.%dn",IP_ARG(q)); } 

Iiph

最终解析结果如下:

可以看到我们正确解析出了IP地址, 结果与抓包工具分析出的数据保持了一致。

其中protocol字段表示了ip协议后面的额协议类型,常见的值如下:

五、解析tcp头

查找tcp头思路很,

就是从pkt头开始偏移过以太头长度(14字节)、和IP头长度(20字节)就可以找到tcp头,

switch(iph->protocol)  {   case 0x1:    //icmp    break;   case 0x6:    //tcp        tcph = (struct tcphdr *)(p + sizeof(struct ethhdr) + sizeof(struct iphdr));    printf("source:%d dest:%d n",ntohs(tcph->source),ntohs(tcph->dest);     break;   case 0x11:    //udp    break;  } 

结构体与内存对应关系

打印结果如下:

六、学会用不同格式打印这块内存

在实际项目中,可能我们解析的并不是标准的TCP/IP协议数据包,

可能是我们自己的服务器托管定义的协议数据包,

只要掌握了上述方法,

所有的协议分析都能够手到擒来!

有时候我们还需要打印对方发送过来的数据帧内容,

往往我们会以16进制形式将所有数据打印出来,

这样是最有利于我们分析数据内容的。

1. 按字节打印

代码如下:

for(i=0;i<400;i++) {  printf("%02x ",pkt[i]);  if(i%20 == 19)  {   printf("n");  } } 

2. 按short类型分析一段内存

我们接收数据时,虽然使用一个unsigned char型数组,

但是有时候对方发送过来的数据可能是2个字节的数组,

那我们只需要用short类型的指针,指向内存的头,

然后就可以通过该指针访问到对方发送的数据,

这个时候一定要注意字节序问题,

不同场景可能不一样,所以一定要具体问题具体分析,

本例因为是网络字节序数据转换成主机字节序,

所以需要转换字节序。

//转变short型字节序 void indian_reverse(unsigned short arr[],int num) {  int i;  unsigned short temp;  for(i=0;i<num;i++)  {   temp = 0;   temp = (arr[i]&0xff00)>>8;   temp |= (arr[i]&0xff)<<8;   arr[i] = temp;  } } main() {  unsigned short spkt[200];  ………………  memcpy(spkt,pkt,sizeof(pkt));  indian_reverse(spkt,ARRAY_SIZE(spkt));  for(i=0;i<200;i++)  {   printf("%04x ",spkt[i]);   if(i%10 == 9)   {    printf("n");   }  }  ……………… } 

结果如下:

转载本文请联系一口Linux公众号。

服务器租用
本文地址:http://www.bhae.cn/news/259c21999521.html
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

全站热门

纽麦平板电脑拆机教程(一步步教你拆解纽麦平板电脑,让你轻松掌握拆机技巧)

主流NoSQL数据库评测之HBase

一个Oracle递归查询的实例代码分析

因盗取裸体照片,iCloud黑客被判9年监禁

一步学会如何制作引导优盘教程(轻松制作引导优盘,让文件传输更便捷)

Nutz1.b.38发布实现Dao更快速的插入

在SQL触发器或存储过程中获取登录用户信息

七个优秀软件供应链安全工具

友情链接

滇ICP备2023000592号-9