首页 > 编程 > PHP > 正文

用PHP分析PCAP(草稿)

2020-03-22 16:27:54
字体:
来源:转载
供稿:网友
  • <html><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312" /><title>PCAP Parser</title></head><table border="1"><tr align="center" bgcolor="#66cc66"><td><b>Subject</b></td><td><b>Content</b></td></tr><?phpdate_default_timezone_set('PRC');// PCAP文件路径$fpath = "./22-srcport-80-qq.pcap";// 计算PCAP文件大小,单位byte$TotalSize = filesize($fpath);echo "<tr><td><b>".$fpath."</b> Size is:</td><td>".$TotalSize."</td></tr>";// 打开PCAP文件$f = fopen($fpath, "rb");// 读取PCAP文件头,长度 24 bytes.$FileHeader = fread($f, 24);// 显示文件头信息,这里就不处理文件头信息了.// 将2进制文件头信息转成16进制的字符// 这里1个16进制的字符等于实际文件中的4bits长度,即半个byte的长度.// 1byte = 8bits, 1个16进制的位等同于4个二进制位, 如:(dec)15=(hex)F=(bin)1111// (24bytes * 8bits/byte) / 4bits = 48// 所以在用16进制字符显示PCAP文件头信息时会看到有48个字符.$FileHeader = bin2hex($FileHeader);// 按32位字符长度分切,便于查看.$FileHeader = chunk_split($FileHeader, 32, "<br />/r/n");// 显示头信息echo "<tr><td>FileHeader is:</td><td>".$FileHeader."</td></tr>";echo "<tr bgcolor=/"#ff0000/" ><td colspan=2></td></tr>";// $position文件指针位置,初始化为24,跳过文件头,从24bytes后开始读取第一个数据包$position = 24;// 数据包序列$n = 0;// 从24bytes后开始读取文件直至文件结束while($position < $TotalSize) {    // 自定义的数据包序列    $n++;    echo "<tr bgcolor=/"#0066cc/" ><td colspan=2>Pack $n </td></tr>";    // 移动文件指针至24bytes的位置    fseek($f, $position);    // 读取16bytes的PCAP包头信息(PackHeader)    $PackHeader = fread($f, 16);    // 将PackHeader转成16进制的字符串    $PackHeader = bin2hex($PackHeader);    echo "<tr><td>PackHeader is:</td><td>".$PackHeader."</td></tr>";    // 从PackHeader截取8个16进制的字符串(即2进制的4*8=32bits,4个字节的长度)    // Timestamp:时间戳高位,精确到seconds    $Sec = substr($PackHeader, 0, 8);    $Sec = substr($Sec, 6, 2).substr($Sec, 4, 2).substr($Sec, 2, 2).substr($Sec, 0, 2);    $Sec = hexdec($Sec);    // Timestamp:时间戳低位,精确到microseconds    $nSec = substr($PackHeader, 8, 8);    $nSec = substr($nSec, 6, 2).substr($nSec, 4, 2).substr($nSec, 2, 2).substr($nSec, 0, 2);    $nSec = hexdec($nSec);    // 得出获取这一数据帧的时间    $DateTime = date("Y-m-d H:i:s", $Sec);    echo "<tr><td>DateTime:</td><td>".$DateTime.".".$nSec."</td></tr>";    // pack length    // Caplen:当前数据区的长度,即抓取到的数据帧长度,由此可以得到下一个数据帧的位置。    $Caplen = substr($PackHeader, 16, 8);    $Caplen = substr($Caplen, 6, 2).substr($Caplen, 4, 2).substr($Caplen, 2, 2).substr($Caplen, 0, 2);    $Caplen = hexdec($Caplen);    echo "<tr><td>Pack Caplen is:</td><td>".$Caplen."</td></tr>";    // 移动文件指针跳过PCAP包头.    fseek($f, $position+16);    // 按PCAP包头里的Caplen长度读取PCAP包体内容.一个PCAP包体就相当于OSI中的数据链路层(Data Link)的一个帧.    // 这里说"相当于"是因为在网络上实际传输的数据包在数据链路层上每一个Packet开始都会有7个用于同步的字节(10101010, 10101010, 10101010, 10101010, 10101010, 10101010, 10101010,)和一个用于标识该Packet开始的字节(10101011),最后还会有四个CRC校验字节;而PCAP文件中会把前8个字节和最后4个校验自己去掉,因为这些信息对于协议分析是没有用处的。    $PackData = fread($f, $Caplen);    // 取MAC地址,6个字节,48bits.转成16进制表示,字符长度为12.即平时在系统看到的物理地址.    // 注意:这里PHP函数substr直接从$PackData的二进制内容里取内容,函数参数的单位为Byte.而不是字符串的字符个数了.    $Dst = bin2hex(substr($PackData, 0, 6));    $Src = bin2hex(substr($PackData, 6, 6));    echo "<tr><td>Src MAC is:</td><td>".$Src."</td></tr>";    echo "<tr><td>Dst MAC is:</td><td>".$Dst."</td></tr>";    // 取以太网类型,2个字节.并转成16进制表示.    $Ethertype = bin2hex(substr($PackData, 12, 2));    echo "<tr><td>Ethertype is:</td><td>".$Ethertype."</td></tr>";    // 这里只分析以太网类型为0800的数据包,即只分析IP包,其他的arp什么的完蛋去~    // 这里就开始进入OSI的网络层(Network)    if ($Ethertype == "0800") {                // IP包头里4bits的版本和4bits的首部长度连续共占1个字节.取1个字节.并转成16进制        $IPVersion_and_HeaderLen = bin2hex(substr($PackData, 14, 1));                // IP版本号4bits,就取一个16进制的字符,转成10进制.        $IPVersion = hexdec(substr($IPVersion_and_HeaderLen, 0, 1));        echo "<tr><td>IP Version is:</td><td>".$IPVersion."</td></tr>";        // IP首部长度4bits,也取一个16进制的字符,转成10进制并乘以4.这里乘以4是因为IP首部长度的单位是以32bits为一个单位,即4个byte为1个单位.        // 从这步得出的首部长度的单位为byte.基本上都是20        $IPHeaderLen = hexdec(substr($IPVersion_and_HeaderLen, 1, 1)) * 4;        echo "<tr><td>IP Header Len is:</td><td>".$IPHeaderLen."(bytes)</td></tr>";                // 14-->32         // 总共跳过8个字节不做处理.(偷懒).        // 1字节的服务类型TOS(8bits),        // 2字节的IP包总长度(16bits),        // 2字节的标识(16bits)        // 2字节的标志和片偏移(3bits标识,13bits片偏移)        // 1字节的生存时间TTL(8bits)                // 第23字节开始取1个字节,8bits的协议类型.就是用来表示上层协议类型的东西(如:TCP,UDP).转成16进制表示.        $Proctol = bin2hex(substr($PackData, 23, 1));        // 取4个字节的源IP地址.并转成常见的4段表示格式.        $SrcIP = bin2hex(substr($PackData, 26, 4));        $SrcIP = hexdec($SrcIP[0].$SrcIP[1])."."                .hexdec($SrcIP[2].$SrcIP[3])."."                .hexdec($SrcIP[4].$SrcIP[5])."."                .hexdec($SrcIP[6].$SrcIP[7]);        // 取4个字节的目标IP地址.并转成常见的4段表示格式.        $DecIP = bin2hex(substr($PackData, 30, 4));        $DecIP = hexdec($DecIP[0].$DecIP[1])."."                .hexdec($DecIP[2].$DecIP[3])."."                .hexdec($DecIP[4].$DecIP[5])."."                .hexdec($DecIP[6].$DecIP[7]);        echo "<tr><td>SrcIP Addr is:</td><td>".$SrcIP."</td></tr>";        echo "<tr><td>DecIP Addr is:</td><td>".$DecIP."</td></tr>";                // 根据协议类型开始处理OSI的传输层的数据.        // 一般的协议类型:6 TCP, 17 UDP, 1 ICMP        // 在这里只处理TCP类型的协议.        if ($Proctol == "06") {            echo "<tr><td>Data Proctol is:</td><td>".$Proctol."(TCP)</td></tr>";            $SrcPort = hexdec(bin2hex(substr($PackData, 34, 2)));            $DecPort = hexdec(bin2hex(substr($PackData, 36, 2)));            echo "<tr><td>Src Port is:</td><td>".$SrcPort."</td></tr>";            echo "<tr><td>Dec Port is:</td><td>".$DecPort."</td></tr>";                        $SEQ = hexdec(bin2hex(substr($PackData, 38, 4)));            $NSEQ = hexdec(bin2hex(substr($PackData, 42, 4)));            echo "<tr><td>SEQ -> NSEQ is:</td><td>".$SEQ."->".$NSEQ."</td></tr>";            // ...                         $Data = substr($PackData, 54);            $DataLen = strlen($Data);            $HexData = bin2hex($Data);            echo "<tr bgcolor=/"#ff6600/"><td>Data Len is:</td><td>".$DataLen."</td></tr>";            echo "<tr><td>Hex Data is:</td><td><textarea rows=/"10/" style=/"word-break:break-all;width:600px;/">".chunk_split($HexData, 32, "/r/n")."</textarea></td></tr>";            echo "<tr bgcolor=/"#ffcc66/"><td>Binary Data is:</td><td><textarea rows=/"10/" style=/"word-break:break-all;width:600px;/">".$Data."</textarea></td></tr>";        } else {            echo "<tr bgcolor=red><td>WARNING:</td><td>This is not an TCP Data, I will jump to NEXT.</td></tr>";        }    } else {        echo "<tr bgcolor=red><td>WARNING:</td><td>This is not an IP PackData, I will jump to NEXT.</td></tr>";    }    //-- --/*    $PackData = bin2hex($PackData);    $PackData = chunk_split($PackData, 32, "<br />/r/n");    echo "<tr><td>Hex PackData is:</td><td>".$PackData."</td></tr>";*/        $position = $position + 16 + $Caplen;}fclose($f);?></table>

    PHP编程

    郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

  • 发表评论 共有条评论
    用户名: 密码:
    验证码: 匿名发表