wireshark lua脚本开发

1.  需求

在各个行业中,产品(模块)往往需要与其他产品进行数据交互,尤其是不同生产商,会采用非标准协议,通过抓包工具抓到报文分析问题时,只能看到二进制字节,不能对这些报文进行详细分析,对问题分析带来较大不便。

wireshark支持通过编辑lua脚本实现通信协议的分析。问题说明:

1.1.      数据帧在网络中会出现合包、分包。即一个包中可能包含x.y个数据帧,其中x≥1,y≥0,如果需要解析一个完整的数据帧,可能需要将上一帧的数据带到下一帧中解析;

1.2.      点击每个解析树节点时,是否可以直接对应到报文窗口中的每个字节;

1.3.      解析时是否支持中文;

2.  解决方案

通过编辑wireshark安装目录中init.lua文件,最后几行中可以列出所有自定义协议的lua文件:

dofile(DATA_DIR.."console.lua")

dofile(DATA_DIR.."zyhd/zj104.lua")

编辑zj104.lua文件:

local my_proto = Proto ("zj104","zhejiang 104 protocol")

function my_proto.dissector(buffer,pinfo,tree)

       local pktlen = buffer:len()

    local bytes_consumed = 0   

   

--逐个解析每个数据帧,如果数据帧不完整,则将不完整的部分保留到下一个数据帧中,解决问题1.1

    while bytes_consumed < pktlen do

              local result = dissectFrm(buffer, pinfo, tree, bytes_consumed)

              if result > 0 then

                     bytes_consumed = bytes_consumed + result

              elseif result == 0 then

                     return 0

              else

                     pinfo.desegment_offset = bytes_consumed

                     result = -result

                     pinfo.desegment_len = result

                     return pktlen

              end

       end

      

       return bytes_consumed

end

 

--计算数据帧的帧长

checkFpmLength = function (buffer, offset)

       local msglen = buffer:len() - offset

       if msglen ~= buffer:reported_length_remaining(offset) then

              return 0

       end

      

       if msglen < 7 then

              return -DESEGMENT_ONE_MORE_SEGMENT

       end

      

       local length_tvbr = buffer:range(offset + 1, 2)

       local length_val  = length_tvbr:le_uint() + 3

       if msglen < length_val then

              return -(length_val - msglen)

       end

      

       return length_val, length_tvbr

end

 

--对单个数据帧的完整解析

dissectFrm = function (buffer, pinfo, tree, offset)

       local length_val, length_tvbr = checkFpmLength(buffer, offset)

       if length_val <= 0 then

        return length_val

    end

   

       local myProtoTree = tree:add(my_proto, buffer(offset, length_val), "浙江104通信协议@中元华电")

--第二个参数,告诉解析器对应报文窗口中的位置。解决问题1.2

       local apcitree = myProtoTree:add(my_proto, buffer(offset, 7),"APCI")

      

       start = buffer(offset, 1):le_uint()

      

       apcitree:add_le(my_proto,buffer(offset, 1),"起始:",  string.format("0x%x",start))

       offset = offset + 1

 

       frm_len = buffer(offset, 2):le_uint()

       apcitree:add_le(my_proto,buffer(offset, 2),"长度:", frm_len)

       offset = offset + 2

      

       local pbuf3 = buffer(offset, 1):le_uint()

      

       if(frm_len==4) then

              if(bit32.band(pbuf3,3)==1) then

                     --s frame

                            offset=offset+2

                            apcitree:add_le("s frame")

                            apcitree:add_le(my_proto,buffer(offset, 2),"recvSN:", bit32.rshift(buffer(offset, 2):le_uint(),1))                  

              elseif(bit32.band(pbuf3,3)==3) then --u frame

                     apcitree:add_le("u frame")

                     if(bit32.rshift(pbuf3,2)==1) then

                            apcitree:add_le("startDT")

                     elseif(bit32.rshift(pbuf3,3)==1) then

                            apcitree:add_le("startDT ack")

                     elseif(bit32.rshift(pbuf3,4)==1) then

                            apcitree:add_le("stopDT")

                     elseif(bit32.rshift(pbuf3,5)==1) then

                            apcitree:add_le("stopDT ack")

                     elseif(bit32.rshift(pbuf3,6)==1) then

                            apcitree:add_le("testDT")

                     elseif(bit32.rshift(pbuf3,7)==1) then

                            apcitree:add_le("testDT ack")

                     end

              end

       else

      

              apcitree:add_le("I帧")

              --i frame

              local sendSN = buffer(offset, 2):le_uint()

              apcitree:add_le(my_proto,buffer(offset, 2),"发送序号:", bit32.rshift(buffer(offset, 2):le_uint(),1))

              --asdu:add_le("发送序号:", bit32.rshift(buffer(offset, 2):le_uint(),1))

              offset = offset + 2

              apcitree:add_le(my_proto,buffer(offset, 2),"接收序号:", bit32.rshift(buffer(offset, 2):le_uint(),1))

              --local recvSN=buffer(offset, 2):le_uint()

              offset = offset + 2      

              asdutree = myProtoTree:add(my_proto,buffer(offset, length_val-7),"ASDU")

              local asduType=buffer(offset, 1):le_uint()

             

              if(asduType==15 ) then

                            offset = asdu15(buffer,pinfo,asdutree,offset)

              elseif(asduType==16) then

                            offset = asdu16(buffer,pinfo,asdutree,offset)     

              elseif(asduType==13) then

                            offset = asdu13(buffer,pinfo,asdutree,offset)            

              elseif(asduType==14) then

                            offset = asdu14(buffer,pinfo,asdutree,offset)

              elseif(asduType==113) then

                     asdutree:add_le("type:",string.format("%d",asduType),"(call brief report)")      

              elseif(asduType==114) then

                     asdutree:add_le("send brief report")   

              elseif(asduType==1) then

                     asdutree:add_le("switch shift")

              end

       end

      

       return length_val

end

 

--省略asdu13接口等定义

 

--注册解析器

local tcp_port_table = DissectorTable.get("tcp.port")

local my_port = 2404

tcp_port_table:add(my_port, my_proto)

 

lua文件保存为utf8格式后,wireshark解析窗口中可正常显示中文,解决问题1.3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值