pcap文件头 pcap文件头参见官方说明 http://www./docs/docs_412/html/structpcap__file__header.html 用python代码表达结构如下,I是32位无符号数,下面的定义均采用32位方式 # bpf_u_int32 magic; 固定为0xA1B2C3D4,表示pcap包文件 # u_short version_major; 主版本号 # u_short version_minor; 分支版本号 # bpf_int32 thiszone; 时区 # bpf_u_int32 sigfigs; # bpf_u_int32 snaplen; 每个包的最大长度 # bpf_u_int32 linktype; 链路层协议族 self.struct_pcap_file_header = '!I2H4I'
pcap每个包的头参见 http://www./docs/docs_412/html/structpcap__pkthdr.html # struct timeval ts; # bpf_u_int32 caplen; # bpf_u_int32 len; self.struct_pcap_pkthdr = '!4I' timeval是c的时间戳结构体,前面一个整型数是秒数偏置,后面一个整型数是微秒偏置,详情可以查阅相关文档
生成pcap文件
使用python简单生成,写入到test.pcap文件,写入了两个包到该文件,linktype设置为162,在wireshark源码中表示保留给用户的USER15 类型 # -*-coding:utf-8-*- """ Author:yinshunyao Date:2017/3/24 0024上午 10:47 """ import unittest import struct
class PacpTest(unittest.TestCase): def setUp(self): # pcap文件头格式 # http://www./docs/docs_412/html/structpcap__file__header.html # bpf_u_int32 magic; 固定为0xA1B2C3D4,表示pcap包文件 # u_short version_major; 主版本号 # u_short version_minor; 分支版本号 # bpf_int32 thiszone; 时区 # bpf_u_int32 sigfigs; # bpf_u_int32 snaplen; 每个包的最大长度 # bpf_u_int32 linktype; 链路层协议族 self.struct_pcap_file_header = '!I2H4I' # pcap包头格式 # http://www./docs/docs_412/html/structpcap__pkthdr.html # struct timeval ts; # bpf_u_int32 caplen; # bpf_u_int32 len; self.struct_pcap_pkthdr = '!4I'
# 文件头 self.file_header = struct.pack( self.struct_pcap_file_header, 0xA1B2C3D4, 4, 1, 0, 0, 0xFFFF, 162 # USER15 )
def test_generate_pcap(self): # 消息体内容 pkg_content1 = struct.pack('!2I', 100, 101) pkg_content2 = struct.pack('!2I', 101, 100) # pkg_header = struct.pack( self.struct_pcap_pkthdr, 0x4A5B1784, 0x00081C6D, len(pkg_content1), len(pkg_content1) ) with open('test.pcap', 'wb') as test: test.write(self.file_header+pkg_header+pkg_content1+pkg_header+pkg_content2)
wireshark解析效果
用自定义的wireshark插件协议解析整体效果如下,后面具体介绍插件内容,可以看到Encapsulation type字段值是60,协议是USER15
这个值跟前面文件头里面的link162的映射关系,在wireshark中完成,具体处理可以查看wireshark的C源码。
协议名称和消息体解析,需要捕获这个数据流在自定义的协议插件中处理,下一章会提到。
两个包的时间戳一样,是因为前面写入文件的包头是一样的。
wireshark lu解析脚本
local serial_encap_table = DissectorTable.get("wtap_encap") --截取所有的bsap协议 --USER0~USER15是45到60,可以自定义解析,参见源码wtap.h serial_encap_table:add(60, p_bsap)
上面两行代码,截取type为60的文件和包进行解析。p_bsap是自定义的解析插件,详细的使用方法和语言基础参见wireshark的官方文档lu部分
do --协议名称是BSAP, 在Packet Details窗格显示为 local p_bsap = Proto("bsap2","Bristol Standard Asynchronous Protocol") --头协议各个字段含义,需要放到此处注册 local f_src = ProtoField.uint32("bsap2.src","Source", base.DEC) local f_des = ProtoField.uint32("bsap2.des","Destination", base.DEC) p_bsap.fields = {f_src, f_des} --指纹信息协议 local p_finger = Proto("BSAP_FR", "BSAP Device Information") --获取数据 local data = Dissector.get("data") local device = {} local offset = 0 --数据分析函数 local function bsap_dissector(buf,pkg,root) local buf_len = buf:len() -- 协议信息展示a pkg.cols.protocol = "BSAP2" --添加头 local header = root:add(p_bsap, buf) header:add(f_src, buf(0,4)) header:add(f_des, buf(4,4)) device = {['Source']=buf(0,4):uint()} pkg.cols.info = "Message: src is "..tostring(device['Source']) offset = buf_len return true end --解析函数,注意,该function前面不能添加local function p_bsap.dissector(buf,pkg,root) --如果解析符合本协议 if bsap_dissector(buf,pkg,root) then --有效的协议,未处理完的字段调用其他协议继续解析 local buf_len = buf:len() if offset + 1 < buf_len then data:call(buf(offset, buf_len-offset), pkg, root) end --如果解析不符合本协议,返回给主程序继续遍历其他协议 else data:call(buf,pkg,root) end end local serial_encap_table = DissectorTable.get("wtap_encap") --截取所有的bsap协议 --USER0~USER15是45到60,可以自定义解析,参见源码wtap.h serial_encap_table:add(60, p_bsap) end
|