perl解析pcap文件

栏目: Perl · 发布时间: 6年前

内容简介:关于

关于 Pcap 文件解析的方法网上有很多相关文章, Pcap 文件的格式以及使用 Wireshark 查看Pcap文件的方法也都有详细教程。然而利用 Perl 脚本语言对 Pcap 文件进行解析的相关代码和文章并没有。本文介绍了如何使用 Perl 脚本语言对 Pcap 文件进行解析。

模块安装

Net::Pcap 模块封装了用于解析Pcap文件的一些方法,首先介绍如何使用CPAN安装 Net::Pcap 模块。

//CPAN相关命令
//获得帮助  
cpan>h  

//列出CPAN上所有模块的列表  
cpan>m  

//安装模块  
cpan>install Net::Pcap 

//退出  
cpan>q 

读取Pcap文件

pcap_loop($pcap, $count, \&callback, $user_data)
从pcap读取count个包,并且调用使用参数user_data调取callback函数。如果count为负,则循环读取直到错误发生。

my $pcap = pcap_open_offline($fileDir, \$err) || die "failed to open pcap file $pcap!";
while(1)
{
    $ret = pcap_loop($pcap, -1, \&load_pcap, $this);
    if($ret == -1)
    {
        print "error on processing packets in pcap file: $@!\n";
        die "error on processing packets in pcap file: $@!\n";
        last;
    }
    elsif($ret == 0 || $ret == -2)
    {
        print "end of pcap processing: $@!\n";
        last;
    }
}

解析数据包

网络数据包格式如下图所示:

perl解析pcap文件

unpack (packformat, formatstr) 函数将以机器格式存贮的值转化成 Perl 中值。packformat代表解析格式,formatstr为要解析的对象。

通过判断各个位置上的值从而确定包的类型。通过记录连接的状态,确定TCP三次握手的建立与解除。具体代码如下:

foreach my $event (sort(keys(%{$packets})))
    {
        print "testlog: a new packet begin----------------------- \n";

        my $packet = $packets->{$event}->{pkt};
        my $proto = unpack("H*", substr($packet, 12, 2));
        if($proto eq "0800") #ipv4
        {
            $count ++;
            my $off = 14;
            my $iphl = (unpack("C", substr($packet, $off, 1)) & 0x0f); # header length  , <<2 is the actual length
            my $ip_payload_len = unpack("n", substr($packet, $off + 2, 2)); #total length
            #print "testlog: packet total length: ". $ip_payload_len ."\n";
            $proto = unpack("C", substr($packet, $off + 9, 1)); #net proto

            my $sip = inet_ntoa(substr($packet, $off + 12, 4)); #source ip addr
            my $dip = inet_ntoa(substr($packet, $off + 16, 4)); #dest ip addr

            # chop the padding bytes off
            $packet = substr($packet, 0, $off + $ip_payload_len); #a full packet

            if($iphl > 5)
            {print "Warning: ip packet with ip option\n";}

            my $ipPayloadLen = unpack("n", substr($packet, $off + 2, 2)) - ($iphl << 2); #total length - header length 

            # skip ipv4 header
            $off += ($iphl << 2);
            if($proto == 6)        # tcp session
            {
                my $tcp_hdrl = unpack("C", substr($packet, $off + 12, 1)) >> 2; # tcp header length , <<2 is the actual length
                my $tcp_flag = unpack("C", substr($packet, $off + 13, 1)); #tcp flag
                #print $tcp_flag . "\n";
                my $sport = unpack("n", substr($packet, $off, 2));    #source port
                my $dport = unpack("n", substr($packet, $off + 2, 2));    #dest port

                if($ipPayloadLen - $tcp_hdrl < 0) # eq 0
                {
                    print "invalid tcp packet: $proto packet not supported!\n";    
                    last;
                }

                my $c = "$sip:$sport<->$dip:$dport";
                my $s = "$dip:$dport<->$sip:$sport";

                # recode session state
                if(!defined($session))
                {
                    print "testlog: session will be defined! \n";
                    $session = {
                        id => $c,
                        cstate => "closed",
                        sip => $sip,
                        dip => $dip,
                        sport => $sport,
                        dport => $dport
                    };
                }

                if($tcp_flag & 0x04)
                {
                    print "Warning: tcp session with RST, need mannual checking!Stop session analyzing: $frameID!\n";
                    $session->{cstate} = "closed";
                }
                print "testlog: session state: ". $session->{cstate} ."\n";
                if($session->{cstate} eq "closed")    # open session
                {
                    if(($tcp_flag & 0x02))        # syn open sesstion
                    {
                        $session->{cstate} = "syn_sent";
                    }
                    else
                    {
                        if(length(substr($packet, $off + $tcp_hdrl)) > 0)
                        {print "Warning: tcp session disordered on closed, need mannual checking!Stop session analyzing: $sip : $sport <-> $dip : $dport \n";}
                    }

                }
                elsif($session->{cstate} eq "syn_sent")
                {
                    #print ($tcp_flag);
                    #print "\n";
                    if(($tcp_flag & 0x12)==0x12){
                        print "ok";
                    };
                    print "\n";
                    if(($tcp_flag & 0x02) && ($sip eq $session->{sip}) && ($sport eq $session->{sport})) # syn from client retransmission
                    {print "tcp retransmission detected!\n";}
                    elsif(($tcp_flag & 0x12) && ($sip eq $session->{dip}) && ($sport eq $session->{dport}))    # syn_ack from server
                    {$session->{cstate} = "syn_rcvd";}
                    else
                    {
                        print "Warning: tcp session disordered on syn_sent, need mannual checking!Stop session analyzing!\n";
                    }

                }
                elsif($session->{cstate} eq "syn_rcvd")
                {
                    if(($tcp_flag & 0x10) && ($sip eq $session->{sip}) && ($sport eq $session->{sport}))  # ack from client
                    {
                        $session->{cstate} = "connected";         # won't check ack
                        print(FD "CONNECT twoarm 1 0 tcp $dip $dport $sip $sport\n\n");
                    }
                    else
                    {print "Warning: none ack packet on syn_rcvd!\n";}
                }
                elsif($session->{cstate} eq "connected")
                {
                    #print "testlog: $sip ---- $session->{sip} ----- $session->{dip}";
                    if($sip eq $session->{sip} && ($sport eq $session->{sport}))        # from client
                    {
                        if($tcp_flag & 0x01)
                        {
                            $session->{FIN} += 1;
                            $session->{FINFrom} = 1; # this is the second FIN, disconnect begin from server
                        }
                        else
                        {
                            if(length(substr($packet, $off + $tcp_hdrl)) > 0) #TCP payload is not empty
                            {
                                $str_temp = unpack('H*',substr($packet, $off + $tcp_hdrl));
                                my @str_temp2 = split(//, $str_temp);
                                my $str_temp3;
                                for($i=0; $i<@str_temp2; $i=$i+2){
                                    $str_temp3 = $str_temp3 . "\\x" . $str_temp2[$i] . $str_temp2[$i+1];
                                }
                                print "$str_temp3 \n";
                                print(FD "SEND 0 #\"$str_temp3\" NOW\n\n");
                            }
                        }
                    }
                    elsif($sip eq $session->{dip} && ($sport eq $session->{dport}))
                    {
                        if($tcp_flag & 0x01)
                        {
                            $session->{FIN} += 1;
                            $session->{FINFrom} = 0; # this is the second FIN, disconnect begin from client
                        }
                        else
                        {
                            if(length(substr($packet, $off + $tcp_hdrl)) > 0)
                            {
                                $str_temp = unpack('H*',substr($packet, $off + $tcp_hdrl));
                                my @str_temp2 = split(//, $str_temp);
                                my $str_temp3;
                                for($i=0; $i<@str_temp2; $i=$i+2){
                                    $str_temp3 = $str_temp3 . "\\x" . $str_temp2[$i] . $str_temp2[$i+1];
                                }
                                print "$str_temp3 \n";
                                print(FD "SEND 1 #\"$str_temp3\" NOW\n\n");
                            }
                        }
                    }
                    else
                    {
                        print "invalid packet on connected tcp session\n";
                    }
                }
                if($session->{cstate} eq "connected" && $session->{FIN} == 2)
                {
                    $FINFrom = $session->{FINFrom};
                    print(FD "DISCONNECT $FINFrom\n");
                    $session->{cstate} = "closed";
                    delete($session->{FIN});
                }
            }
        }
    }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Nine Algorithms That Changed the Future

Nine Algorithms That Changed the Future

John MacCormick / Princeton University Press / 2011-12-27 / GBP 19.95

Every day, we use our computers to perform remarkable feats. A simple web search picks out a handful of relevant needles from the world's biggest haystack: the billions of pages on the World Wide Web.......一起来看看 《Nine Algorithms That Changed the Future》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具