成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

開發(fā) 前端 網(wǎng)絡(luò)管理
本文的目的是通過隨機(jī)截取的一段網(wǎng)絡(luò)數(shù)據(jù)包,然后根據(jù)協(xié)議類型來解析出這段內(nèi)存。希望對你有所幫助!

[[416402]]

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

學(xué)習(xí)本文需要掌握的基礎(chǔ)知識(shí):

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

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

一文包你學(xué)會(huì)網(wǎng)絡(luò)數(shù)據(jù)抓包

視頻教學(xué)鏈接如下:

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

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

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

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

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

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

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

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

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

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

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

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

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

以太頭:

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

IP頭

  1. include\uapi\linux\ip.h  
  1. struct iphdr { 
  2. #if defined(__LITTLE_ENDIAN_BITFIELD)  //小端模式 
  3.  __u8 ihl:4, 
  4.   version:4; 
  5. #elif defined(__BIG_ENDIAN_BITFIELD)    //大端模式 
  6.  __u8 version:4, 
  7.   ihl:4; 
  8. #endif 
  9.  __u8 tos; 
  10.  __u16 tot_len; 
  11.  __u16 id; 
  12.  __u16 frag_off; 
  13.  __u8 ttl; 
  14.  __u8 protocol; 
  15.  __u16 check
  16.  __u32 saddr; 
  17.  __u32 daddr; 
  18.  /*The options start here. */ 
  19. }; 

tcp頭

  1. include\uapi\linux\tcp.h 
  1. struct tcphdr { 
  2.  __be16 source; 
  3.  __be16 dest; 
  4.  __be32 seq; 
  5.  __be32 ack_seq; 
  6. #if defined(__LITTLE_ENDIAN_BITFIELD) 
  7.  __u16 res1:4, 
  8.   doff:4, 
  9.   fin:1, 
  10.   syn:1, 
  11.   rst:1, 
  12.   psh:1, 
  13.   ack:1, 
  14.   urg:1, 
  15.   ece:1, 
  16.   cwr:1; 
  17. #elif defined(__BIG_ENDIAN_BITFIELD) 
  18.  __u16 doff:4, 
  19.   res1:4, 
  20.   cwr:1, 
  21.   ece:1, 
  22.   urg:1, 
  23.   ack:1, 
  24.   psh:1, 
  25.   rst:1, 
  26.   syn:1, 
  27.   fin:1; 
  28. #else 
  29. #error "Adjust your <asm/byteorder.h> defines" 
  30. #endif  
  31.  __be16 window; 
  32.  __sum16 check
  33.  __be16 urg_ptr; 
  34. }; 

因?yàn)閰f(xié)議頭長度都是按照標(biāo)準(zhǔn)協(xié)議來定義的,

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

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

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

三、解析以太頭

  1. #define MAC_ARG(p) p[0],p[1],p[2],p[3],p[4],p[5] 
  1. struct ethhdr *ethh; 
  2.  unsigned char *p = pkt; 
  3.   
  4.  ethh = (struct ethhdr *)p; 
  5.  
  6.  printf("h_dest:%02x:%02x:%02x:%02x:%02x:%02x \n", MAC_ARG(ethh->h_dest)); 
  7.  printf("h_source:%02x:%02x:%02x:%02x:%02x:%02x \n", MAC_ARG(ethh->h_source)); 
  8.  printf("h_proto:%04x\n",ntohs(ethh->h_proto)); 
  • 注意,數(shù)據(jù)包中的數(shù)據(jù)是網(wǎng)絡(luò)字節(jié)序,如果要提取數(shù)據(jù)一定要注意字節(jié)序問題 ethh->h_proto 是short類型,占2個(gè)字節(jié),所以存儲(chǔ)到本地需要使用函數(shù)ntohs 其中:
  • n:network 網(wǎng)絡(luò)字節(jié)序
  • h:host 主機(jī)字節(jié)序
  • s:short 2個(gè)字節(jié) l:
  • long 4個(gè)字節(jié)
  • ntohl() :4字節(jié)網(wǎng)絡(luò)字節(jié)序數(shù)據(jù)轉(zhuǎn)換成主機(jī)字節(jié)序
  • htons() :2字節(jié)主機(jī)字節(jié)序數(shù)據(jù)轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序
  • ntohs() :2字節(jié)網(wǎng)絡(luò)字節(jié)序數(shù)據(jù)轉(zhuǎn)換成主機(jī)字節(jié)序
  • htonl() :4字節(jié)主機(jī)字節(jié)序數(shù)據(jù)轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序

當(dāng)執(zhí)行下面這條語句時(shí),

  1. ethh = (struct ethhdr *)p; 

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

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

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

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

四、解析ip頭

解析ip頭思路很簡單,

就是從pkt頭開始偏移過以太頭長度(14字節(jié))就可以找到IP頭,

解析代碼如下:

  1. #define IP_ARG(p)  p[0],p[1],p[2],p[3] 
  1. /* 
  2.  解析IP頭 
  3. */ 
  4. if(ntohs(ethh->h_proto) == 0x0800) 
  5.  
  6.  iph = (struct iphdr *)(p + sizeof(struct ethhdr)); 
  7.  
  8.  q = (unsigned char *)&(iph->saddr); 
  9.  printf("src ip:%d.%d.%d.%d\n",IP_ARG(q)); 
  10.  
  11.  q = (unsigned char *)&(iph->daddr); 
  12.  printf("dest ip:%d.%d.%d.%d\n",IP_ARG(q)); 
一文教你如何用C代碼解析一段網(wǎng)絡(luò)數(shù)據(jù)包?「含代碼」

Iiph

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

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

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

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

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

五、解析tcp頭

查找tcp頭思路很,

就是從pkt頭開始偏移過以太頭長度(14字節(jié))、和IP頭長度(20字節(jié))就可以找到tcp頭,

  1. switch(iph->protocol) 
  2.  { 
  3.   case 0x1: 
  4.    //icmp 
  5.    break; 
  6.   case 0x6: 
  7.    //tcp     
  8.    tcph = (struct tcphdr *)(p + sizeof(struct ethhdr) + sizeof(struct iphdr)); 
  9.    printf("source:%d dest:%d \n",ntohs(tcph->source),ntohs(tcph->dest);  
  10.  
  11.    break; 
  12.   case 0x11: 
  13.    //udp 
  14.     
  15.    break; 
  16.  } 

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

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

打印結(jié)果如下:

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

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

在實(shí)際項(xiàng)目中,可能我們解析的并不是標(biāo)準(zhǔn)的TCP/IP協(xié)議數(shù)據(jù)包,

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

只要掌握了上述方法,

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

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

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

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

1. 按字節(jié)打印

代碼如下:

  1. for(i=0;i<400;i++) 
  2.  printf("%02x ",pkt[i]); 
  3.  if(i%20 == 19) 
  4.  { 
  5.   printf("\n"); 
  6.  } 
一文教你如何用C代碼解析一段網(wǎng)絡(luò)數(shù)據(jù)包?「含代碼」

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

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

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

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

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

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

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

本例因?yàn)槭蔷W(wǎng)絡(luò)字節(jié)序數(shù)據(jù)轉(zhuǎn)換成主機(jī)字節(jié)序,

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

  1. //轉(zhuǎn)變short型字節(jié)序 
  2. void indian_reverse(unsigned short arr[],int num) 
  3.  int i; 
  4.  unsigned short temp
  5.  
  6.  for(i=0;i<num;i++) 
  7.  { 
  8.   temp = 0; 
  9.  
  10.   temp = (arr[i]&0xff00)>>8; 
  11.   temp |= (arr[i]&0xff)<<8; 
  12.   arr[i] = temp
  13.  } 
  14. main() 
  15.  unsigned short spkt[200]; 
  16.   
  17.  ……………… 
  18.  memcpy(spkt,pkt,sizeof(pkt)); 
  19.  
  20.  indian_reverse(spkt,ARRAY_SIZE(spkt)); 
  21.   
  22.  for(i=0;i<200;i++) 
  23.  { 
  24.   printf("%04x ",spkt[i]); 
  25.   if(i%10 == 9) 
  26.   { 
  27.    printf("\n"); 
  28.   } 
  29.  } 
  30.  ……………… 

結(jié)果如下:

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

轉(zhuǎn)載本文請聯(lián)系一口Linux公眾號。

 

責(zé)任編輯:姜華 來源: 今日頭條
相關(guān)推薦

2023-05-11 08:26:56

2021-12-07 06:02:15

Redis Docker運(yùn)維

2022-09-05 07:32:46

mock數(shù)據(jù)Stream

2024-12-19 15:00:00

數(shù)據(jù)清洗Python

2024-11-20 16:42:03

Python科學(xué)計(jì)算

2023-07-31 21:56:54

哨兵系統(tǒng)redis

2022-02-20 09:56:28

TCPIP網(wǎng)絡(luò)協(xié)議

2023-12-27 07:40:43

HTTP服務(wù)器負(fù)載均衡

2024-11-18 17:16:18

Python性能優(yōu)化編程

2024-11-20 16:12:31

Python圖像處理計(jì)算機(jī)視覺

2021-01-15 13:18:39

數(shù)據(jù)模型領(lǐng)域模型代碼

2015-03-27 11:34:59

JavaJava編寫引發(fā)內(nèi)存泄露

2021-01-27 09:34:51

Visual C++Dev C++codelite

2022-08-26 07:02:57

Python工具分割

2019-07-23 07:30:16

2020-12-22 10:02:53

ZabbixMySQL數(shù)據(jù)庫

2025-05-30 01:00:00

RAG大模型流程

2025-06-20 08:00:00

硬路由軟路由網(wǎng)絡(luò)

2018-06-23 08:02:31

程序員代碼故事

2020-03-23 10:06:05

工具代碼開發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 97精品国产97久久久久久免费 | 超碰日本 | 欧美a∨| 中文字幕亚洲一区二区三区 | 国产伦一区二区三区久久 | 亚洲自拍偷拍av | www.天天操 | dy天堂| 天堂久久av | 亚洲播放 | 一区二区精品在线 | 国产欧美一级 | 国产成人午夜精品影院游乐网 | 在线免费观看黄色av | 99精品久久 | 亚洲v区| 国产精品三级 | 亚洲视频在线观看免费 | 亚洲欧美高清 | 嫩草一区二区三区 | 国产色 | 国产在线观看一区二区 | 51ⅴ精品国产91久久久久久 | 精品国产一区二区在线 | 国产探花在线精品一区二区 | 毛片视频免费观看 | 日韩一区二区三区在线观看 | 久久久久久久久久久久亚洲 | 日韩毛片在线视频 | 午夜精品久久 | 成人做爰www免费看 午夜精品久久久久久久久久久久 | 精品一区二区三区中文字幕 | 91精品国产色综合久久不卡98口 | 欧美日韩综合精品 | 91视频在线观看免费 | 国产亚洲一区二区三区在线观看 | 亚洲影音 | 日韩在线中文字幕 | 成人午夜影院 | 成人精品 | 中文字幕av一区二区三区 |