wincap函数用法简述

函数说明:

Net::Pcap的功能由winpcap提供.

 

Net::Pcap::findalldevs(\$err [,\%description])

返回一个能被函数Net::Pcap::open_live()利用的所有网络设备的名字的列表,这些名字分别是%description中的键,如果提供了可选参数-散列%description,则它存放所有对应与前面的网络设备的描述信息;如果发生错误,则$err中会存放相应的错误消息。

 

Net::Pcap::open_live($dev, $snaplen, $promisc, $to_ms, \$err)

该函数返回一个用来在网络上捕获包的描述符,$dev指定从哪个网络接口上捕获包,$snaplen设定捕获包的最大字节数,$promisc指定是否将该网络接口设置为混合模式,$to_ms设定以毫秒度量的读超时时间,这是每次读取的时间阀值,如果有错误发生,则不会定义这个描述符,同时将这个错误信息写入参数$err中。

 

Net::Pcap::sendpacket($pcap_t, $packet)

该函数用来发送数据包,$pcap_t是指定通过哪个网络接口来发送数据包的设备描述符,$packet是要发送的数据,这个数据中不需要包含MAC CRC ,因为网络接口的驱动会自动完成计算并添加。

 

Net::Pcap::close($pcap_t)

关闭描述符$pcap_t所对应的的网络接口。

 

Net::Pcap::next($pcap_t, \%hdr)

从描述符$pcap_t关联的的接口上抓取包,这些包的一些信息被放到hash表%hdr中。如果没有获取包,则返回值和头部都会被设成无定义。

%hdr内容:

len--

报文的总长度

caplen--

包数据的实际长度

tv_sec

秒级别的时间戳值

tv_usec

毫秒级别的时间戳值

 

Net::Pcap::compile($pcap_t, \$filter_t, $filter_str, $optimize, $netmask) $pcap_t 关联一个网络接口,$filter_str存放过滤字段描述,函数执行后把编译的结果放到\$filter_t中,如果$optimize为真,则对$filter_str进行优化处理。

 

Net::Pcap::setfilter($pcap_t, $filter_t);

将过滤规则$filter_t应用到$pcap_t上去。

 

Net::Pcap::stats($pcap, \%stats)

该函数返回指定接口上的报文捕获的信息,$pcap关联设备,%stats为一散列,存放报文捕获信息,它的结构如下:

ps_recv

由抓包软件捕获的报文数量,但是报文较多是会不准

ps_drop

由抓包软件丢弃的报文的数量

ps_ifdrop

由网络接口丢弃的报文的数量

 

 

常用过滤器写法:

  1. 过滤ip,arp…等在帧类型字段有对应值的报文

ether proto \ip(由于ip是关键字,前面要加”\”,“\ip”也可以用相应的协议对应的数值来代替)

 

  1. 过滤特定ip地址的报文

\ip src  a.b.c.d

\ip dst  a.b.c.d

3.过滤封装在ip包内的特定报文,如icmp,igmp等

 \ip proto 1 (过滤icmp,也可直接用关键字 \icmp) 

4.过滤特定的端口号,如

Port  port_num   双向过滤

Src  port  port_num 只过滤源端口号匹配的报文

dst  port  port_num 只过滤目的端口号匹配的报文

混合使用:

可以通过and ,or,not来合理组合过滤字段,如过滤源ip为a.b.c.d,目的ip为e.f.g.h的报文

\ip src a.b.c.d and dst e.f.g.h

 

 

 

Packet Decoders

 

这是介绍几个简单的协议解码函数,是参考NetPacket模块中的相关函数修改的。如Windows下通常使用winpcap库抓包,使用模块是        

Net::Pcap和Net::PcapUtils,其中Net::Pcap是Perl的winpcap库接口,Net::PcapUtils里映射了一些Net::Pcap中常用的函数,

提供了更方便些的接口。写协议分析程序一般步骤是:

 

1、打开设备;

2、循环抓包,对每个包进行逐层解码,在每层解码后进行相关字段的过滤;

3、最后将满足过滤条件的包输出;

4、加上对中断信号的处理,各种统计Counter等其他特性;

 

举例来说,打开Eth0设备,循环抓包,最初获得eth frame,用eth_decode函数处理,获得帧的src_mac、dest_mac、type和data字段,

其中data字段里是上层协议数据。然后根据type字段指示的上层协议类型,对data字段的值应用相应的解码函数,如type是“0x0800”,

则表明这个以太帧里面是IP包-对应就是以太帧的data字段,用ip_decode函数处理这个字段,继而获得这个IP包中的各个字段,

同理它的data字段就是IP层的上层协议包的内容,又IP包中的proto字段指示四层协议的类型,如IP的proto字段是6,

则表明四层是TCP协议,那么就对IP包data字段应用tcp_decode函数进行解析,依此类推。

 

综上,每层协议头中必定定义了某个字段(如eth.type,ip.proto,ppp.code, etc.)指示如何解析该层携带的上层数据包(data)。

具体解码做法就是参考协议的RFC文档,使用unpack逐层解码、计算生成每层相关字段。当编写某个协议的解码函数时,

可以参考下面几个decode函数,其中关键是unpack的使用,因为是解析网络中的数据包,当然使用网络字节顺序来unpack,

常用下面几个字符:

 

N - 32bits 网络字节顺序

n - 16bits 网络字节顺序

C - 8bits 网络字节顺序

a - 任意二进制

 

对于非整字节的字段(如4bits和13bits等),按C或n取得整字节后移位获得,如IP Header的结构是:

 

    0                   1                   2                   3  

    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1

   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   |Version|  IHL  |Type of Service|          Total Length         | <-CCn

   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   |         Identification        |Flags|      Fragment Offset    | <-nn

   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   |  Time to Live |    Protocol   |         Header Checksum       | <-CCn

   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   |                       Source Address                          | <-N

   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   |                    Destination Address                        | <-N

   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   |                    Options                    |    Padding    | <-a*

   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

 

                    Example Internet Datagram Header

 

参考rfc791.txt,对应的解码函数可以写成:

 

sub ip_decode {

    my $packet = shift;

    my $ippkt_ref = {};

    my @fields = qw/tmp tos len id foffset ttl proto cksum src_ip dest_ip options/;

    my @values = unpack("CCnnnCCnNNa*" , $packet);

 

    map { $ippkt_ref->{$fields[$_]} = $values[$_] } (0..$#fields);

 

    #Extract bit fields

    $ippkt_ref->{ver} = ($ippkt_ref->{tmp} & 0xf0) >> 4;

    $ippkt_ref->{hlen} = $ippkt_ref->{tmp} & 0x0f;

    $ippkt_ref->{flags} = $ippkt_ref->{foffset} >> 13;

    $ippkt_ref->{foffset} = ($ippkt_ref->{foffset} & 0x1fff) << 3;

 

    #Decode variable length header options and remaining data in field

    #Option length is number of 32 bits words

    my $olen = ($ippkt_ref->{hlen} - 5) ? ($ippkt_ref->{hlen} - 5) * 4 : 0;

 

    ($ippkt_ref->{options}, $ippkt_ref->{data}) = unpack("a".$olen."a*", $ippkt_ref->{options});

 

    #Convert 32 bit ip addresses to dotted quad notation

    $ippkt_ref->{src_ip} = to_dotquad($ippkt_ref->{src_ip});

    $ippkt_ref->{dest_ip} = to_dotquad($ippkt_ref->{dest_ip});

 

    undef $ippkt_ref->{tmp};

    return $ippkt_ref;

}

 

--Packet Decoders eXamples--

 

#Packets decoders

sub eth_decode {

    my $packet = shift;

    my $ethframe_ref = {};

    my @fields = qw/sm_lo sm_hi dm_lo dm_hi type data/;

    my @values = unpack("NnNnna*", $packet);

    map { $ethframe_ref->{$fields[$_]} = $values[$_] } (0..$#fields);

 

    #Convert MAC addresses to hex string to avoid representation problems

    $ethframe_ref->{src_mac} = sprintf("%08x%04x", $ethframe_ref->{sm_hi}, $ethframe_ref->{sm_lo});

    $ethframe_ref->{dest_mac}= sprintf("%08x%04x", $ethframe_ref->{dm_hi}, $ethframe_ref->{dm_lo});

 

    undef $ethframe_ref->{$_} foreach(qw/sm_lo sm_hi dm_lo dm_hi/);

    return $ethframe_ref;

}

 

sub arp_decode {

    my $packet = shift;

    my $arppkt_ref = {};

    my @fields = qw/htype proto hlen plen opcode sha spa tha tpa data/;

    my @values = (unpack("nnCCnH12H8H12H8", $packet), undef);

 

    map { $arppkt_ref->{$fields[$_]} = $values[$_] } (0..$#fields);

 

    return $arppkt_ref;

}

 

sub ppp_decode {

    my $packet = shift;

    my $ppppkt_ref = {};

    my @fields = qw/code id length data/;

    my @values = unpack("ccna*", $packet);

 

    map { $ppppkt_ref->{$fields[$_]} = $values[$_] } (0..$#fields);

 

    if($ppppkt_ref->{code} =~ m/[1-4]/) {

        $ppppkt_ref->{type} = unpack("c", $ppppkt_ref->{data});

 

        my @fields;

 

        @fields = qw/type length MRU data/ if($ppppkt_ref->{type} == PPP_TYPE_MRU);

        @fields = qw/type length auth data/ if($ppppkt_ref->{type} == PPP_TYPE_AUTHPROTO);

        @fields = qw/type length quality data/ if($ppppkt_ref->{type} == PPP_TYPE_QUALPROTO);

        @fields = qw/type length magic data/ if($ppppkt_ref->{type} == PPP_TYPE_MAGICNUM);

 

        my @values = unpack("ccna*", $ppppkt_ref->{data});

 

        map { $ppppkt_ref->{$fields[$_]} = $values[$_] } (0..$#fields);

    }

 

    if($ppppkt_ref->{code} == PPP_CODE_ECHOREQ or $ppppkt_ref->{code} == PPP_CODE_ECHOREPLY) {

        my @fields = qw/magic data/;

        my @values = unpack("Na*", $ppppkt_ref->{data});

 

        map { $ppppkt_ref->{$fields[$_]} = $values[$_] } (0..$#fields);

    }

 

    return $ppppkt_ref;

}

 

sub ip_decode {

    my $packet = shift;

    my $ippkt_ref = {};

    my @fields = qw/tmp tos len id foffset ttl proto cksum src_ip dest_ip options/;

    my @values = unpack("CCnnnCCnNNa*" , $packet);

 

    map { $ippkt_ref->{$fields[$_]} = $values[$_] } (0..$#fields);

 

    #Extract bit fields

    $ippkt_ref->{ver} = ($ippkt_ref->{tmp} & 0xf0) >> 4;

    $ippkt_ref->{hlen} = $ippkt_ref->{tmp} & 0x0f;

    $ippkt_ref->{flags} = $ippkt_ref->{foffset} >> 13;

    $ippkt_ref->{foffset} = ($ippkt_ref->{foffset} & 0x1fff) << 3;

 

    #Decode variable length header options and remaining data in field

    #Option length is number of 32 bits words

    my $olen = ($ippkt_ref->{hlen} - 5) ? ($ippkt_ref->{hlen} - 5) * 4 : 0;

 

    ($ippkt_ref->{options}, $ippkt_ref->{data}) = unpack("a".$olen."a*", $ippkt_ref->{options});

 

    #Convert 32 bit ip addresses to dotted quad notation

    $ippkt_ref->{src_ip} = to_dotquad($ippkt_ref->{src_ip});

    $ippkt_ref->{dest_ip} = to_dotquad($ippkt_ref->{dest_ip});

 

    undef $ippkt_ref->{tmp};

    return $ippkt_ref;

}

 

sub icmp_decode {

    my $packet = shift;

    my $icmppkt_ref = {};

    my @fields = qw/type code cksum data/;

    my @values = unpack("CCna*", $packet);

 

    map { $icmppkt_ref->{$fields[$_]} = $values[$_] } (0..$#fields);

 

    return $icmppkt_ref;

}

 

sub tcp_decode {

    my $packet = shift;

    my $tcppkt_ref = {};

    my @fields = qw/src_port dest_port seqnum acknum tmp winsize cksum urg options/;

    my @values = unpack("nnNNnnnna*", $packet);

 

    map { $tcppkt_ref->{$fields[$_]} = $values[$_] } (0..$#fields);

 

    #Extract flags

    $tcppkt_ref->{hlen} = ($tcppkt_ref->{tmp} & 0xf000) >> 12;

    $tcppkt_ref->{reserved} = ($tcppkt_ref->{tmp} & 0x0f00) >> 8;

    $tcppkt_ref->{flags} = $tcppkt_ref->{tmp} & 0x00ff;

 

    #Decode variable length header and remaining data

    my $olen = ($tcppkt_ref->{hlen} - 5) ? ($tcppkt_ref->{hlen} - 5) * 4 : 0;

 

    ($tcppkt_ref->{options}, $tcppkt_ref->{data}) = unpack("a".$olen."a*", $tcppkt_ref->{options});

 

    undef $tcppkt_ref->{tmp};

    return $tcppkt_ref;

}

 

sub udp_decode {

    my $packet = shift;

    my $udppkt_ref = {};

    my @fields = qw/src_port dest_port len cksum data/;

    my @values = unpack("nnnna*", $packet);

 

    map { $udppkt_ref->{$fields[$_]} = $values[$_] } (0..$#fields);

 

    return $udppkt_ref;

}

---

#who"s r00t?

my $r00t = "fat root";

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值