日韩在线不卡免费视频一区,日韩欧美精品一区二区三区经典,日产精品码2码三码四码区,人妻无码一区二区三区免费,日本feerbbwdh少妇丰满

一口Linux
認證:優(yōu)質(zhì)創(chuàng)作者
所在專題目錄 查看專題
c語言實現(xiàn)MD5摘要認證,如此簡單
C語言實現(xiàn)MD5加密,竟如此簡單!
從0寫一個電話號碼管理的C入門項目【適合初學者】
Linux字節(jié)對齊的那些事
一文教你如何用C代碼解析一段網(wǎng)絡數(shù)據(jù)包?【含代碼】
你見過最垃圾的代碼長什么樣?
作者動態(tài) 更多
為什么對技術(shù)人員的考核大多都只看加班時間?
5天前
某通信公司筆試題,你會做幾道?
2星期前
10種初學者最常見的c語言段錯誤實例及原因分析
05-30 12:13
linux系統(tǒng)監(jiān)控工具小神器:btop
05-17 17:37
有沒有權(quán)貴開后門讓子女做軟件開發(fā)人員?
05-10 23:36

一文教你如何用C代碼解析一段網(wǎng)絡數(shù)據(jù)包?【含代碼】

本文的目的是通過隨機截取的一段網(wǎng)絡數(shù)據(jù)包,然后根據(jù)協(xié)議類型來解析出這段內(nèi)存。

學習本文需要掌握的基礎(chǔ)知識:

  1. 網(wǎng)絡協(xié)議
  2. C語言
  3. Linux操作
  4. 抓包工具的使用

其中抓包工具的安裝和使用見下文:

一文包你學會網(wǎng)絡數(shù)據(jù)抓包

視頻教學鏈接如下:

教你如何抓取網(wǎng)絡中的數(shù)據(jù)包!黑客必備技能

一、截取一個網(wǎng)絡數(shù)據(jù)包

通過抓包工具,隨機抓取一個tcp數(shù)據(jù)包

科萊抓包工具解析出的數(shù)據(jù)包信息如下:

數(shù)據(jù)包的內(nèi)存信息:

數(shù)據(jù)信息可以直接拷貝出來:

二、用到的結(jié)構(gòu)體

下面,一口君就手把手教大家如何解析出這些數(shù)據(jù)包的信息。

我們可以從Linux內(nèi)核中找到協(xié)議頭的定義

  • 以太頭:
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;
};

因為協(xié)議頭長度都是按照標準協(xié)議來定義的,

所以以太長度是14, IP頭長度是20, tcp頭長度是20,

各個協(xié)議頭對應的內(nèi)存空間如下:

三、解析以太頭

#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));

注意,數(shù)據(jù)包中的數(shù)據(jù)是網(wǎng)絡字節(jié)序,如果要提取數(shù)據(jù)一定要注意字節(jié)序問題 ethh->h_proto 是short類型,占2個字節(jié),所以存儲到本地需要使用函數(shù)ntohs 其中: n:network 網(wǎng)絡字節(jié)序 h:host 主機字節(jié)序 s:short 2個字節(jié) l:long 4個字節(jié) ntohl() :4字節(jié)網(wǎng)絡字節(jié)序數(shù)據(jù)轉(zhuǎn)換成主機字節(jié)序 htons() :2字節(jié)主機字節(jié)序數(shù)據(jù)轉(zhuǎn)換成網(wǎng)絡字節(jié)序 ntohs() :2字節(jié)網(wǎng)絡字節(jié)序數(shù)據(jù)轉(zhuǎn)換成主機字節(jié)序 htonl() :4字節(jié)主機字節(jié)序數(shù)據(jù)轉(zhuǎn)換成網(wǎng)絡字節(jié)序

當執(zhí)行下面這條語句時,

ethh = (struct ethhdr *)p;

結(jié)構(gòu)體指針變量eth的成員對應關(guān)系如下:

最終打印結(jié)果如下:

四、解析ip頭

解析ip頭思路很簡單,

就是從pkt頭開始偏移過以太頭長度(14字節(jié))就可以找到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.%d\n",IP_ARG(q));

		q = (unsigned char *)&(iph->daddr);
		printf("dest ip:%d.%d.%d.%d\n",IP_ARG(q));
	}

Iiph

最終解析結(jié)果如下:

可以看到我們正確解析出了IP地址, 結(jié)果與抓包工具分析出的數(shù)據(jù)保持了一致。

其中protocol字段表示了ip協(xié)議后面的額協(xié)議類型,常見的值如下:

數(shù)值 描述 0 保留字段,用于IPv6(跳躍點到跳躍點選項) 1 Internet控制消息 (ICMP) 2 Internet組管理 (IGMP) 3 網(wǎng)關(guān)到網(wǎng)關(guān) (GGP) 4 1P中的IP(封裝) 6 傳輸控制 (TCP) 7 CBT 8 外部網(wǎng)關(guān)協(xié)議 (EGP) 9 任何私有內(nèi)部網(wǎng)關(guān)(Cisco在它的IGRP實現(xiàn)中使用) (IGP) 10 BBNRCC監(jiān)視 11 網(wǎng)絡語音協(xié)議 12 PUP 13 ARGUS 14 EMCON 15 網(wǎng)絡診斷工具 16 混亂(Chaos) 17 用戶數(shù)據(jù)報文 (UDP) 41 1Pv6 58 1Pv6的ICMP 59 1Pv6的無下一個報頭 60 IPv6的信宿選項 89 OSPF IGP 92 多播傳輸協(xié)議 94 IP內(nèi)部的IP封裝協(xié)議 95 可移動網(wǎng)絡互連控制協(xié)議 96 旗語通訊安全協(xié)議 97 IP中的以太封裝 98 封裝報頭 100 GMTP 101 Ipsilon流量管理協(xié)議 133~254 未分配 255 保留

五、解析tcp頭

查找tcp頭思路很,

就是從pkt頭開始偏移過以太頭長度(14字節(jié))、和IP頭長度(20字節(jié))就可以找到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;
		}

結(jié)構(gòu)體與內(nèi)存對應關(guān)系

打印結(jié)果如下:

六、學會用不同格式打印這塊內(nèi)存

在實際項目中,可能我們解析的并不是標準的TCP/IP協(xié)議數(shù)據(jù)包,

可能是我們自己的定義的協(xié)議數(shù)據(jù)包,

只要掌握了上述方法,

所有的協(xié)議分析都能夠手到擒來!

有時候我們還需要打印對方發(fā)送過來的數(shù)據(jù)幀內(nèi)容,

往往我們會以16進制形式將所有數(shù)據(jù)打印出來,

這樣是最有利于我們分析數(shù)據(jù)內(nèi)容的。

1. 按字節(jié)打印

代碼如下:

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

2. 按short類型分析一段內(nèi)存

我們接收數(shù)據(jù)時,雖然使用一個unsigned char型數(shù)組,

但是有時候?qū)Ψ桨l(fā)送過來的數(shù)據(jù)可能是2個字節(jié)的數(shù)組,

那我們只需要用short類型的指針,指向內(nèi)存的頭,

然后就可以通過該指針訪問到對方發(fā)送的數(shù)據(jù),

這個時候一定要注意字節(jié)序問題,

不同場景可能不一樣,所以一定要具體問題具體分析,

本例因為是網(wǎng)絡字節(jié)序數(shù)據(jù)轉(zhuǎn)換成主機字節(jié)序,

所以需要轉(zhuǎn)換字節(jié)序。

//轉(zhuǎn)變short型字節(jié)序
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");
		}
	}
	………………
}

結(jié)果如下:

完整代碼請關(guān)注公眾號:一口Linux,回復:數(shù)據(jù)包解析

聲明:本內(nèi)容為作者獨立觀點,不代表電子星球立場。未經(jīng)允許不得轉(zhuǎn)載。授權(quán)事宜與稿件投訴,請聯(lián)系:editor@netbroad.com
本篇所含全部資料,點擊此處留下郵箱我會發(fā)給你
資料明細:配套代碼
覺得內(nèi)容不錯的朋友,別忘了一鍵三連哦!
贊 3
收藏 3
關(guān)注 181
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧