分析802.11無線報文hexdump內容:利用wireshark自帶二進位制工具text2pcap將hexdump內容轉換為pcap檔案
阿新 • • 發佈:2018-12-11
除錯wifi驅動,有時會將報文內容以16進位制形式打印出來,如下是一個beacon報文的內容:
0000 80 00 00 00 ff ff ff ff ff ff 40 e3 d6 cb fe d0 0010 40 e3 d6 cb fe d0 70 29 7b 00 55 41 00 00 00 00 0020 64 00 11 01 00 06 50 61 72 72 6f 74 01 06 98 a4 0030 30 48 60 6c 03 01 95 05 04 00 01 00 00 20 01 00 0040 23 02 1b 00 30 14 01 00 00 0f ac 04 01 00 00 0f 0050 ac 04 01 00 00 0f ac 02 28 00 2d 1a ef 09 17 ff 0060 ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0070 00 0000 00 00 00 3d 16 95 0d 11 00 00 00 00 00 0080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 7f 08 0090 04 00 08 00 00 40 00 40 bf 0c 91 59 82 0f ea ff 00a0 00 00 ea ff 00 00 c0 05 00 00 00 00 00 c3 03 01 00b0 3c 3c dd 07 00 0b 86 01 04 08 1b dd 18 00 50 f2 00c0 02 01 01 80 00 03 a4 00 00 27 a4 00 00 42 43 5e 00d0 00 62 32 2f 00
如果用這個16進位制的內容自己去解析報文,分析各個IE,是不是很頭疼?wireshark可以幫助你解決這個問題,下面介紹兩種方法:
1、使用命令列將hexdump檔案轉換為pcap檔案,再用wireshark開啟pcap檔案
將上述beacon內容儲存到beacon.txt檔案中,然後用text2pcap命令進行轉換:
text2pcap -l 105 beacon.txt beacon.pcap
引數“-l 105”是在指定報文型別,105代表的是LINKTYPE_IEEE802_11即要把beacon.txt的內容轉換為802.11格式的報文。然後用wireshark開啟beacon.pcap即可,效果如下圖所示:
2.使用wireshark圖形介面匯入hexdump檔案進行解析
具體步驟如下:
最終結果如下圖所示:
在進行轉換的時候需要注意一下幾點:
1、text2pcap工具只能接受一定格式的hexdump,更詳盡的用法:https://www.wireshark.org/docs/man-pages/text2pcap.html
2、出了802.11格式的報文外,text2pcap還可以處理很多種報文型別,詳見:http://www.tcpdump.org/linktypes.html
3、hexdump的內容開始要是802.11頭,結尾沒有4位元組FCS校驗,如果有請去掉,不然報文解析會有問題。
4、有時候我們列印報文可能並不是從802.11頭開始列印的,找到802.11頭,去掉前面的內容後會變成如下這種樣子:
0000 80 00 00 00 ff ff ff ff ff ff 40 e3 d6 cb 0020 fe d0 40 e3 d6 cb fe d0 70 29 7b 00 55 41 00 00 0030 00 00 64 00 11 01 00 06 50 61 72 72 6f 74 01 06 0040 98 a4 30 48 60 6c 03 01 95 05 04 00 01 00 00 20 0050 01 00 23 02 1b 00 30 14 01 00 00 0f ac 04 01 00 0060 00 0f ac 04 01 00 00 0f ac 02 28 00 2d 1a ef 09 0070 17 ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 0080 00 00 00 00 00 00 00 00 3d 16 95 0d 11 00 00 00 0090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00a0 7f 08 04 00 08 00 00 40 00 40 bf 0c 91 59 82 0f 00b0 ea ff 00 00 ea ff 00 00 c0 05 00 00 00 00 00 c3 00c0 03 01 3c 3c dd 07 00 0b 86 01 04 08 1b dd 18 00 00d0 50 f2 02 01 01 80 00 03 a4 00 00 27 a4 00 00 42 00e0 43 5e 00 62 32 2f 00 da e2 e8 16
除最後一行外,有可能會出現每行不是16個位元組,如果手動去把每行搞成16個位元組並且把第一列每行的開始位元組索引搞對會非常費勁,並且還容易出現手誤,把某個位元組給刪掉的情況,影響工作效率。
下面我寫了一個程式transform來解決這個問題,有3種用法,如下:
a) ./transform src.txt dst.txt
b) cat src.txt | ./transform dst.txt
c) cat src.txt | ./transform (會將結果打印出來)
transform原始碼如下:
1 #include <stdio.h> 2 #include <string.h> 3 #define BYTES_PER_LINE (16) 4 #define SPACE_PER_LINE (BYTES_PER_LINE) 5 #define PREFIX_NUM (6) 6 7 int process(char *src, char *dst) 8 { 9 static int line = 0; 10 char *pchar = NULL; 11 int offset = 0; 12 13 if (NULL == src || NULL == dst) 14 { 15 printf("Err: src:%p dst:%p\n",src, dst); 16 return -1; 17 } 18 19 offset = strlen(dst); 20 if (0 == offset) 21 { 22 sprintf(dst,"%06x ",line*BYTES_PER_LINE); 23 offset = strlen(dst); 24 } 25 26 pchar = strtok(src, " "); 27 while (pchar = strtok(NULL, " ")) 28 { 29 /* solve problems caused by Windows and linux line breaks \n \r\n*/ 30 if ((2 != strlen(pchar))) 31 { 32 if (!((3 == strlen(pchar) && pchar[2] != '\n') || 33 (4 == strlen(pchar) && 0 == strncmp(&pchar[2], "\r\n", 2)))) 34 { 35 continue; 36 } 37 } 38 else if ((strncmp(pchar, "\r\n", 2) == 0)) 39 { 40 continue; 41 } 42 43 dst[offset++] = pchar[0]; 44 dst[offset++] = pchar[1]; 45 if (((offset - 1 - line*2) % (BYTES_PER_LINE*2 + PREFIX_NUM + SPACE_PER_LINE -1)) == 0) 46 { 47 dst[offset++] = '\n'; 48 line++; 49 sprintf(&dst[offset],"%06x ", line*BYTES_PER_LINE); 50 offset += PREFIX_NUM + 1; 51 } 52 else 53 { 54 dst[offset++] = ' '; 55 } 56 } 57 } 58 59 int main(int argc, char *argv[]) 60 { 61 FILE *fpsrc = NULL; 62 FILE *fpdest = NULL; 63 char buf[1024]; 64 char *pchar = NULL; 65 int ret = 0; 66 char context[65535] = {0}; 67 int offset = 0; 68 69 switch (argc) 70 { 71 case 1: 72 /* Read from stdin and write to stdout */ 73 case 2: 74 { 75 /* Read from stdin and write to dest file */ 76 memset(buf, 0, sizeof(buf)); 77 while (fgets(buf, sizeof(buf), stdin) != NULL) 78 { 79 ret = process(buf, context); 80 if (0 != ret) 81 { 82 return ret; 83 } 84 memset(buf, 0, sizeof(buf)); 85 } 86 if (argc == 2) 87 { 88 fpdest = fopen(argv[1], "w"); 89 } 90 else 91 { 92 fpdest = stdout; 93 } 94 if (NULL == fpdest) 95 { 96 printf("Err can't open dst:%s\n", argv[2]); 97 return -1; 98 } 99 break; 100 } 101 case 3: 102 { 103 /* Read from src file and write to dest file*/ 104 fpsrc = fopen(argv[1], "r"); 105 if (fpsrc == NULL) 106 { 107 printf("Err: can't open src:%s\n",argv[1]); 108 return -1; 109 } 110 while(!feof(fpsrc)) 111 { 112 memset(buf, 0, sizeof(buf)); 113 fgets(buf, sizeof(buf), fpsrc); 114 ret = process(buf, context); 115 if (0 != ret) 116 { 117 return ret; 118 } 119 } 120 fpdest = fopen(argv[2], "w"); 121 if (NULL == fpdest) 122 { 123 printf("Err can't open dst:%s\n", argv[2]); 124 return -1; 125 } 126 127 break; 128 } 129 default: 130 printf("Err: argc:%d Wrong number of parameters!\n",argc); 131 return argc; 132 133 break; 134 } 135 136 fputs(context, fpdest); 137 138 printf("\ntransform success!\n"); 139 }