用PHP分析PCAP

  1 <html>
  2 
  3 <head>
  4 
  5 <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
  6 
  7 <title>PCAP Parser</title>
  8 </head>
  9 <body>
 10 
 11 <table border="1">
 12 
 13 <tr align="center" bgcolor="#66cc66"><td><b>Subject</b></td><td><b>Content</b></td></tr>
 14 
 15 <?php
 16 
 17 date_default_timezone_set('PRC');
 18  
 19  
 20 // PCAP文件路径
 21 if(isset($_GET['type'])  && $_GET['type'] =='tcp'){
 22 
 23 
 24     $fpath = "./192.168.9.246[2089]-239.255.255.250[1900]-17-1556323793.pcap";//TCP
 25 
 26 }else{
 27 
 28       $fpath = "./192.168.9.246[2089]-239.255.255.250[1900]-17-1556323793.pcap";//TCP
 29 }
 30 
 31 
 32 
 33 
 34 // 计算PCAP文件大小,单位byte
 35 
 36 $TotalSize = filesize($fpath);
 37 
 38  
 39 echo "<tr><td><b>".$fpath."</b> Size is:</td><td>".$TotalSize."</td></tr>";
 40 
 41 
 42 
 43 // 打开PCAP文件
 44 
 45 $f = fopen($fpath, "rb");
 46 
 47 
 48 
 49 // 读取PCAP文件头,长度 24 bytes.
 50 
 51 $FileHeader = fread($f, 24);
 52  
 53 
 54 
 55 $vensCaplen = 0;
 56 
 57 //var_dump(file($fpath));exit;
 58 
 59 
 60 // 显示文件头信息,这里就不处理文件头信息了.
 61 
 62 // 将2进制文件头信息转成16进制的字符
 63 
 64 // 这里1个16进制的字符等于实际文件中的4bits长度,即半个byte的长度.
 65 
 66 // 1byte = 8bits, 1个16进制的位等同于4个二进制位, 如:(dec)15=(hex)F=(bin)1111
 67 
 68 // (24bytes * 8bits/byte) / 4bits = 48
 69 
 70 // 所以在用16进制字符显示PCAP文件头信息时会看到有48个字符.
 71 
 72 $FileHeader = bin2hex($FileHeader);
 73 
 74 
 75 
 76 // 按32位字符长度分切,便于查看.
 77 
 78 $FileHeader = chunk_split($FileHeader, 32, "<br />\r\n");
 79 
 80  
 81  
 82 // 显示头信息
 83 
 84 echo "<tr><td>FileHeader is:</td><td>".$FileHeader."</td></tr>";
 85 
 86 echo "<tr bgcolor=\"#ff0000\" ><td colspan=2></td></tr>";
 87 
 88 
 89 
 90 // $position文件指针位置,初始化为24,跳过文件头,从24bytes后开始读取第一个数据包
 91 
 92 $position = 24;
 93 
 94 
 95 
 96  
 97 
 98 if(isset($_GET['page'])  && !empty($_GET['page'])){
 99     
100     $page = $_GET['page']-1;
101 
102 }else{
103     $page = 0;
104 }
105 
106 if($page <0){
107     $page = 0;
108 }
109 
110 if(isset($_GET['vensCaplen'])  && !empty($_GET['vensCaplen'])){
111     $vensCaplen = $_GET['vensCaplen'];
112     $vensCaplenred = $_GET['vensCaplen'];
113  
114 
115 }else{
116     $vensCaplen = 0;
117     $vensCaplenred = 0;
118      
119 }
120 
121 
122 if($page == 0 || $page ==1){
123     $vensCaplenred = 0;
124 }
125   
126         
127 //页大小 
128     $vensnum = 5;
129     $html = '';
130     
131     for($i = 0;$i<$vensnum;$i++){
132     
133         // 移动文件指针至24bytes的位置
134      
135         $vensInitmv = $vensCaplen+ 16*$vensnum*$page+16*$i + $position;
136          
137         //$vensInitmv = $vensCaplen+ 16*$i + $position;
138          
139         
140          
141         fseek($f, $vensInitmv);
142         $PackHeader = fread($f, 16);
143         
144         $PackHeader = bin2hex($PackHeader); 
145  
146         // 从PackHeader截取8个16进制的字符串(即2进制的4*8=32bits,4个字节的长度)
147 
148         // Timestamp:时间戳高位,精确到seconds
149 
150         $Sec = substr($PackHeader, 0, 8);  
151         $Sec = substr($Sec, 6, 2).substr($Sec, 4, 2).substr($Sec, 2, 2).substr($Sec, 0, 2);
152 
153         $Sec = hexdec($Sec); 
154         // Timestamp:时间戳低位,精确到microseconds
155 
156         $nSec = substr($PackHeader, 8, 8);
157 
158         $nSec = substr($nSec, 6, 2).substr($nSec, 4, 2).substr($nSec, 2, 2).substr($nSec, 0, 2);
159 
160         $nSec = hexdec($nSec);
161 
162 
163 
164         // 得出获取这一数据帧的时间
165 
166         $DateTime = date("Y-m-d H:i:s", $Sec);
167         
168         
169     
170         //var_dump($DateTime.".".$nSec); 
171         
172  
173         $Caplen = substr($PackHeader, 16, 8);
174          
175         $Caplen = substr($Caplen, 6, 2).substr($Caplen, 4, 2).substr($Caplen, 2, 2).substr($Caplen, 0, 2);
176         
177         $Caplen = hexdec($Caplen);
178         
179         // 移动文件指针跳过PCAP包头
180         fseek($f, $position+16);
181         
182         // 按PCAP包头里的Caplen长度读取PCAP包体内容.一个PCAP包体就相当于OSI中的数据链路层(Data Link)的一个帧.
183         // 这里说"相当于"是因为在网络上实际传输的数据包在数据链路层上每一个Packet开始都会有7个用于同步的字节
184         //(10101010, 10101010, 10101010, 10101010, 10101010, 10101010, 10101010,)和一个用于标识该Packet开始的字节(10101011),
185         //最后还会有四个CRC校验字节;而PCAP文件中会把前8个字节和最后4个校验自己去掉,因为这些信息对于协议分析是没有用处的。
186         $PackData = fread($f, $Caplen);
187         
188         // 取MAC地址,6个字节,48bits.转成16进制表示,字符长度为12.即平时在系统看到的物理地址. 
189         // 注意:这里PHP函数substr直接从$PackData的二进制内容里取内容,函数参数的单位为Byte.而不是字符串的字符个数了 
190         $Dst = bin2hex(substr($PackData, 0, 6));
191 
192         $Src = bin2hex(substr($PackData, 6, 6));
193         
194         // 取以太网类型,2个字节.并转成16进制表示.
195         $Ethertype = bin2hex(substr($PackData, 12, 2)); 
196         $num = $vensnum*$page+$i+1;
197         $html .= <<<Eof
198             <tr bgcolor="#0066cc" ><td colspan=2>Pack $num </td></tr>
199             <tr><td>PackHeader is:</td><td> $PackHeader </td></tr>
200             <tr><td>DateTime:</td><td> $DateTime.$nSec </td></tr>
201             <tr><td>Pack Caplen is:</td><td> $Caplen </td></tr>
202             <tr><td>Src MAC is:</td><td>$Src</td></tr>
203             <tr><td>Dst MAC is:</td><td>$Dst</td></tr>
204             <tr><td>Ethertype is:</td><td>$Ethertype</td></tr>
205 Eof;
206 
207          
208         $vensCaplen += $Caplen;
209      
210           
211          
212         if ($Ethertype == "0800") {
213         // IP包头里4bits的版本和4bits的首部长度连续共占1个字节.取1个字节.并转成16进制
214  
215         $IPVersion_and_HeaderLen = bin2hex(substr($PackData, 14, 1));
216         
217          // IP版本号4bits,就取一个16进制的字符,转成10进制.
218 
219         $IPVersion = hexdec(substr($IPVersion_and_HeaderLen, 0, 1));
220 
221         // IP首部长度4bits,也取一个16进制的字符,转成10进制并乘以4.这里乘以4是因为IP首部长度的单位是以32bits为一个单位,即4个byte为1个单位.
222 
223         // 从这步得出的首部长度的单位为byte.基本上都是20
224         
225         $IPHeaderLen = hexdec(substr($IPVersion_and_HeaderLen, 1, 1)) * 4; //20  + 12 ()+ 14
226 
227          // 14-->32 
228 
229         // 总共跳过8个字节不做处理.(偷懒).
230 
231         // 1字节的服务类型TOS(8bits),
232 
233         // 2字节的IP包总长度(16bits),
234 
235         // 2字节的标识(16bits)
236 
237         // 2字节的标志和片偏移(3bits标识,13bits片偏移)
238 
239         // 1字节的生存时间TTL(8bits)
240 
241         
242 
243         // 第23字节开始取1个字节,8bits的协议类型.就是用来表示上层协议类型的东西(如:TCP,UDP).转成16进制表示.
244  
245         $Proctol = bin2hex(substr($PackData, 23, 1));
246 
247 
248 
249         // 取4个字节的源IP地址.并转成常见的4段表示格式.
250 
251         $SrcIP = bin2hex(substr($PackData, 26, 4));
252 
253         $SrcIP = hexdec($SrcIP[0].$SrcIP[1])."."
254 
255                 .hexdec($SrcIP[2].$SrcIP[3])."."
256 
257                 .hexdec($SrcIP[4].$SrcIP[5])."."
258 
259                 .hexdec($SrcIP[6].$SrcIP[7]);
260 
261         // 取4个字节的目标IP地址.并转成常见的4段表示格式.
262 
263         $DecIP = bin2hex(substr($PackData, 30, 4));
264 
265         $DecIP = hexdec($DecIP[0].$DecIP[1])."."
266 
267                 .hexdec($DecIP[2].$DecIP[3])."."
268 
269                 .hexdec($DecIP[4].$DecIP[5])."."
270 
271                 .hexdec($DecIP[6].$DecIP[7]);
272         
273            
274         // 根据协议类型开始处理OSI的传输层的数据 
275         // 一般的协议类型:6 TCP, 17 UDP, 1 ICMP
276         
277         // 在这里只处理TCP类型的协议.
278         
279           $html .= <<<Eof
280             <tr><td>IP Version is:</td><td> $IPVersion </td></tr>
281             <tr><td>IP Header Len is:</td><td> $IPHeaderLen (bytes)</td></tr>
282             <tr><td>SrcIP Addr is:</td><td> $SrcIP </td></tr>
283             <tr><td>DecIP Addr is:</td><td> $DecIP </td></tr>
284 Eof;
285             //UDP
286              if ($Proctol == "011") {
287              
288                      
289                 $SrcPort = hexdec(bin2hex(substr($PackData, 34, 2)));
290 
291                 $DecPort = hexdec(bin2hex(substr($PackData, 36, 2)));
292 
293                  
294                 $SEQ = hexdec(bin2hex(substr($PackData, 38, 4)));
295 
296                 $NSEQ = hexdec(bin2hex(substr($PackData, 42, 4)));
297 
298            
299                 $Data = substr($PackData, (14 + $IPHeaderLen + 8));
300 
301                 $DataLen = strlen($Data);
302 
303                 $HexData = bin2hex($Data);
304 
305                 $vensData = str_replace("\r",'.',str_replace("\n", '.', $Data));
306                 $Data1 = $Data;
307                 $Data=    chunk_split($vensData,16,"\r\n");
308                 
309                      $vensc1 = chunk_split(chunk_split($HexData, 2, " "),48,"###");
310                      $vensc2 = chunk_split($vensData,16,"###");
311                      $arrayvensc1 = explode('###', $vensc1);
312                      $arrayvensc2 = explode('###', $vensc2);
313                     $countvens = count($arrayvensc1);
314                     $newData = '';
315                     $newData1 = '';
316                     if($DataLen == 0 || $DataLen ==''){
317                         $newData1 = '';
318                     }else{
319                         $newData1 = '1';
320                         for ($ii=0; $ii <  $countvens; $ii++) { 
321                             if($ii < 10){
322                                         $vi = '00'.$ii;
323                                     }else if($i< 100){
324                                         $vi = '0'.$ii;
325                                     }else{
326                                         $vi = $ii;
327                                     } 
328                                   if($ii == $countvens- 2 || $ii == $countvens- 1){
329                                     $vstrlen = strlen($arrayvensc1[$ii]);
330                                     if($vstrlen<48){
331                                         $cnum = 48 - $vstrlen;
332                                         for($iv=0;$iv<$cnum;$iv++) {
333                                             $arrayvensc1[$ii].=" ";
334                                         } 
335                                     } 
336                                 } 
337                                 $newData .= $vi.' '.$arrayvensc1[$ii].' '.$arrayvensc2[$ii]."\r\n" ;
338                             $newData1 = mb_convert_encoding($newData, 'UTF-8', 'UTF-8');     
339                         }
340                                      
341                     }    
342  
343             $vensChunk =  mb_convert_encoding(chunk_split(chunk_split($HexData, 2, " "),48,"\r\n"), 'UTF-8', 'UTF-8');     
344                 
345      $html .= <<<Eof
346             <tr><td>Data Proctol is:</td><td> $Proctol(UDP) </td></tr>
347             <tr><td>Src Port is:</td><td> $SrcPort </td></tr>
348             <tr><td>Dec Port is:</td><td> $DecPort </td></tr>
349             <tr><td>SEQ -> NSEQ is:</td><td> $SEQ -> $NSEQ </td></tr>
350             <tr bgcolor="#ff6600"><td>Data Len is:</td><td> $DataLen </td></tr>
351             <tr><td>Hex Data is:</td><td><textarea rows="10" style=" -break:break-all;width:600px;"> $vensChunk </textarea></td></tr>
352             <tr bgcolor="#ffcc66"><td>Binary Data is:</td><td><textarea rows="10" style=" -break:break-all;width:600px;"> $Data1 </textarea></td></tr>
353             <tr bgcolor="#ffcc66"><td>Binary Data is:</td><td><textarea rows="10" style=" -break:break-all;width:600px;"> $newData1 </textarea></td></tr>
354 Eof;
355             
356             
357             
358              
359              }else{
360                 $html .= "<tr bgcolor=red><td>WARNING1111:</td><td>This is not an TCP Data, I will jump to NEXT.</td></tr>";
361              
362              }
363         }
364       
365     }
366     echo $html; 
367     
368  // $vensCaplen = 0; //这个值  和页码一起给定   
369   //没有一共页数   
370   //根据文件大小和 便宜量来判断是否有下一页
371   
372  
373     //-- --
374 
375 /*
376 
377     $PackData = bin2hex($PackData);
378 
379     $PackData = chunk_split($PackData, 32, "<br />\r\n");
380 
381     echo "<tr><td>Hex PackData is:</td><td>".$PackData."</td></tr>";
382 
383 */    
384 
385     
386 
387  
388 fclose($f);
389 
390     
391 ?>
392 
393 
394 </table>
395     <a href='http://localhost:8446/tcpudp/phpjiexies.php?type=add&page=<?php echo $page+2;?>&vensCaplen=<?php echo $vensCaplen;?>'><?php echo $page+2;?>下一页<?php echo $vensCaplen;?></a>
396     <a href=''>刷新</a>
397  
398  
399     <a href='http://localhost:8446/tcpudp/phpjiexies.php?type=edit&page=<?php echo $page;?>&vensCaplen=<?php echo $vensCaplenred;?>'><?php echo $page;?>上一页<?php echo $vensCaplenred;?></a>
400  
401  <h1><?php echo $vensCaplen;?></h1>
402  
403 </body>
404 </html>

文件链接:https://pan.baidu.com/s/1KwYZ_-Ot993ocK-2xLVXWg    jadn

posted @ 2019-05-09 17:04  星蛤他叔  阅读(743)  评论(0)    收藏  举报