电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
一文教你如何用C代码解析一段网络数据包?【含代码】
分 享
扫描二维码分享
一文教你如何用C代码解析一段网络数据包?【含代码】
C语言
网络
一口Linux
关注
发布时间: 2021-08-10
丨
阅读: 2749
本文的目的是通过随机截取的一段网络数据包,然后根据协议类型来解析出这段内存。 学习本文需要掌握的基础知识: 1. 网络协议 2. C语言 3. Linux操作 4. 抓包工具的使用 其中抓包工具的安装和使用见下文: 《[一文包你学会网络数据抓包](https://mp.weixin.qq.com/s?__biz=MzUxMjEyNDgyNw==&mid=2247490595&idx=1&sn=11fb56cb4d18da0c3da5cad1cded52b5&chksm=f9686ed7ce1fe7c1de117abf6d3b09ba85b76da3855b5676b65b9f2fd14de807607a1dabf3a2&scene=21&token=2078275313&lang=zh_CN#wechat_redirect)》 视频教学链接如下: 《[教你如何抓取网络中的数据包!黑客必备技能](https://mp.weixin.qq.com/s?__biz=MzUxMjEyNDgyNw==&mid=2247491157&idx=1&sn=7c78bb12094fa7415e6fdc56b7cadb77&chksm=f9686ca1ce1fe5b784d65de153901a317e6b97c3043f88e74a2f2e5186d42520207da3e3f4f0&scene=21&token=2078275313&lang=zh_CN#wechat_redirect)》 ## 一、截取一个网络数据包 通过抓包工具,随机抓取一个tcp数据包 ![ ](https://img-blog.csdnimg.cn/f8a74216b9db4b87ac6474981843dbf2.jpg) 科莱抓包工具解析出的数据包信息如下: ![ ](https://img-blog.csdnimg.cn/734595f24ca04822bb61b50e59a6c2db.png) 数据包的内存信息: ![ ](https://img-blog.csdnimg.cn/996b64acbb9146549fec96ab3449e6a4.png) 数据信息可以直接拷贝出来: ![ ](https://img-blog.csdnimg.cn/8c8541f163c442e7997d362d4d92fa1e.png) ## 二、用到的结构体 下面,一口君就手把手教大家如何解析出这些数据包的信息。 我们可以从Linux内核中找到协议头的定义 * 以太头: ```bash drivers\staging\rtl8188eu\include\if_ether.h ``` ```c 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头 ```bash include\uapi\linux\ip.h ``` ```c 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头 ```bash include\uapi\linux\tcp.h ``` ```c 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
defines" #endif __be16 window; __sum16 check; __be16 urg_ptr; }; ``` 因为协议头长度都是按照标准协议来定义的, 所以以太长度是14, IP头长度是20, tcp头长度是20, 各个协议头对应的内存空间如下: ![ ](https://img-blog.csdnimg.cn/57dd1814b17d4258bbba6d38723de389.png) ## 三、解析以太头 ```c #define MAC_ARG(p) p[0],p[1],p[2],p[3],p[4],p[5] ``` ```c 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字节主机字节序数据转换成网络字节序 当执行下面这条语句时, ```c ethh = (struct ethhdr *)p; ``` 结构体指针变量**eth**的成员对应关系如下: ![以太头](https://img-blog.csdnimg.cn/ad01a28601f4461192d1a20ddd85391c.png) 最终打印结果如下: ![ ](https://img-blog.csdnimg.cn/aad8413a23ea48ecb157510446566517.png) ## 四、解析ip头 解析ip头思路很简单, 就是从pkt头开始偏移过以太头长度(14字节)就可以找到IP头, 解析代码如下: ```c #define IP_ARG(p) p[0],p[1],p[2],p[3] ``` ```c /@@* 解析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.%d\n",IP_ARG(q)); q = (unsigned char *)&(iph->daddr); printf("dest ip:%d.%d.%d.%d\n",IP_ARG(q)); } ``` ![Iiph](https://img-blog.csdnimg.cn/1977d17171fe40bf8e3a538aa810eafc.png) 最终解析结果如下: ![ ](https://img-blog.csdnimg.cn/f5b83646db9c455c8d3e6210d6f5f3ef.png)可以看到我们正确解析出了IP地址, 结果与抓包工具分析出的数据保持了一致。 其中protocol字段表示了ip协议后面的额协议类型,常见的值如下: |数值 | 描述 | |--|:--| | 0 | 保留字段,用于IPv6(跳跃点到跳跃点选项)| | 1| Internet控制消息 (ICMP)| | 2 |Internet组管理 (IGMP)| |3 |网关到网关 (GGP)| |4 |1P中的IP(封装)| |6 |传输控制 (TCP)| |7 |CBT| |8 |外部网关协议 (EGP)| |9 |任何私有内部网关(Cisco在它的IGRP实现中使用) (IGP)| |10| BBNRCC监视| |11| 网络语音协议| |12| PUP| |13| ARGUS| |14| EMCON| |15| 网络诊断工具| |16| 混乱(Chaos)| |17| 用户数据报文 (UDP)| |41| 1Pv6| |58| 1Pv6的ICMP| |59| 1Pv6的无下一个报头| |60| IPv6的信宿选项| |89| OSPF IGP| |92| 多播传输协议| |94| IP内部的IP封装协议| |95| 可移动网络互连控制协议| |96| 旗语通讯安全协议| |97| IP中的以太封装| |98| 封装报头| |100 |GMTP| |101 |Ipsilon流量管理协议| |133~254 |未分配| |255 |保留| ## 五、解析tcp头 查找tcp头思路很, 就是从pkt头开始偏移过以太头长度(14字节)、和IP头长度(20字节)就可以找到tcp头, ```c 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; } ``` 结构体与内存对应关系 ![ ](https://img-blog.csdnimg.cn/b527013facca426a96de4062948f35f4.png) 打印结果如下: ![ ](https://img-blog.csdnimg.cn/45711999c8ef4522bc774a08f27b8870.png) ## 六、学会用不同格式打印这块内存 在实际项目中,可能我们解析的并不是标准的TCP/IP协议数据包, 可能是我们自己的定义的协议数据包, 只要掌握了上述方法, 所有的协议分析都能够手到擒来! 有时候我们还需要打印对方发送过来的数据帧内容, 往往我们会以16进制形式将所有数据打印出来, 这样是最有利于我们分析数据内容的。 ### 1. 按字节打印 代码如下: ```c for(i=0;i<400;i++) { printf("%02x ",pkt[i]); if(i%20 == 19) { printf("\n"); } } ``` ![ ](https://img-blog.csdnimg.cn/79c8a1a169634768b099c7bbb44164e8.png) ## 2. 按short类型分析一段内存 我们接收数据时,虽然使用一个unsigned char型数组, 但是有时候对方发送过来的数据可能是2个字节的数组, 那我们只需要用short类型的指针,指向内存的头, 然后就可以通过该指针访问到对方发送的数据, **这个时候一定要注意字节序问题,** 不同场景可能不一样,所以一定要具体问题具体分析, 本例因为是网络字节序数据转换成主机字节序, 所以需要转换字节序。 ```c //转变short型字节序 void indian_reverse(unsigned short arr[],int num) { int i; unsigned short temp; for(i=0;i
>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"); } } ……………… } ``` 结果如下: ![ ](https://img-blog.csdnimg.cn/aeeb26d5406f483fa0fbc7ee18a1e3c4.png) 完整代码请关注:一口Linux,回复:**数据包解析**
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
一口Linux
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交