您好,欢迎访问三七文档
当前位置:首页 > 办公文档 > 理论文章 > 如何编写协议解码函数
PacketDecoders这是介绍几个简单的协议解码函数,是参考NetPacket模块中的相关函数修改的。如Windows下通常使用winpcap库抓包,使用模块是Net::Pcap和Net::PcapUtils,其中Net::Pcap是Perl的winpcap库接口,Net::PcapUtils里映射了一些Net::Pcap中常用的函数,提供了更方便些的接口。写协议分析程序一般步骤是:1、打开设备;2、循环抓包,对每个包进行逐层解码,在每层解码后进行相关字段的过滤;3、最后将满足过滤条件的包输出;4、加上对中断信号的处理,各种统计Counter等其他特性;举例来说,打开Eth0设备,循环抓包,最初获得ethframe,用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取得整字节后移位获得,如IPHeader的结构是:012301234567890123456789012345678901+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|Version|IHL|TypeofService|TotalLength|-CCn+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|Identification|Flags|FragmentOffset|-nn+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|TimetoLive|Protocol|HeaderChecksum|-CCn+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|SourceAddress|-N+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|DestinationAddress|-N+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|Options|Padding|-a*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ExampleInternetDatagramHeader参考rfc791.txt,对应的解码函数可以写成:subip_decode{my$packet=shift;my$ippkt_ref={};my@fields=qw/tmptoslenidfoffsetttlprotocksumsrc_ipdest_ipoptions/;my@values=unpack('CCnnnCCnNNa*',$packet);map{$ippkt_ref-{$fields[$_]}=$values[$_]}(0..$#fields);#Extractbitfields$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;#Decodevariablelengthheaderoptionsandremainingdatainfield#Optionlengthisnumberof32bitswordsmy$olen=($ippkt_ref-{hlen}-5)?($ippkt_ref-{hlen}-5)*4:0;($ippkt_ref-{options},$ippkt_ref-{data})=unpack('a'.$olen.'a*',$ippkt_ref-{options});#Convert32bitipaddressestodottedquadnotation$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;}--PacketDecoderseXamples--#Packetsdecoderssubeth_decode{my$packet=shift;my$ethframe_ref={};my@fields=qw/sm_losm_hidm_lodm_hitypedata/;my@values=unpack('NnNnna*',$packet);map{$ethframe_ref-{$fields[$_]}=$values[$_]}(0..$#fields);#ConvertMACaddressestohexstringtoavoidrepresentationproblems$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_losm_hidm_lodm_hi/);return$ethframe_ref;}subarp_decode{my$packet=shift;my$arppkt_ref={};my@fields=qw/htypeprotohlenplenopcodeshaspathatpadata/;my@values=(unpack('nnCCnH12H8H12H8',$packet),undef);map{$arppkt_ref-{$fields[$_]}=$values[$_]}(0..$#fields);return$arppkt_ref;}subppp_decode{my$packet=shift;my$ppppkt_ref={};my@fields=qw/codeidlengthdata/;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/typelengthMRUdata/if($ppppkt_ref-{type}==PPP_TYPE_MRU);@fields=qw/typelengthauthdata/if($ppppkt_ref-{type}==PPP_TYPE_AUTHPROTO);@fields=qw/typelengthqualitydata/if($ppppkt_ref-{type}==PPP_TYPE_QUALPROTO);@fields=qw/typelengthmagicdata/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_ECHOREQor$ppppkt_ref-{code}==PPP_CODE_ECHOREPLY){my@fields=qw/magicdata/;my@values=unpack('Na*',$ppppkt_ref-{data});map{$ppppkt_ref-{$fields[$_]}=$values[$_]}(0..$#fields);}return$ppppkt_ref;}subip_decode{my$packet=shift;my$ippkt_ref={};my@fields=qw/tmptoslenidfoffsetttlprotocksumsrc_ipdest_ipoptions/;my@values=unpack('CCnnnCCnNNa*',$packet);map{$ippkt_ref-{$fields[$_]}=$values[$_]}(0..$#fields);#Extractbitfields$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;#Decodevariablelengthheaderoptionsandremainingdatainfield#Optionlengthisnumberof32bitswordsmy$olen=($ippkt_ref-{hlen}-5)?($ippkt_ref-{hlen}-5)*4:0;($ippkt_ref-{options},$ippkt_ref-{data})=unpack('a'.$olen.'a*',$ippkt_ref-{options});#Convert32bitipaddressestodottedquadnotation$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$
本文标题:如何编写协议解码函数
链接地址:https://www.777doc.com/doc-390908 .html