首页 > 其他 > 详细

用Lua写Wireshark插件

时间:2015-11-22 11:15:02      阅读:458      评论:0      收藏:0      [点我收藏+]

Create Wireshark Dissector by Lua

东方瀞
ylxxwx@gmail.com

1. Why Wireshark dissector

Wireshark supports thousands of protocols now. But there are still some new protocols not supported and private protocols are not either. Fortunately, we can write dissectors by ourselves and add them to wireshark without changing wireshark source code.

2. Lua vs. C for Wireshark dissector

Wireshark supports plug-ins developed by C or Lua. Comparing with C, Lua is a script language, platform independent and easy for debugging. Here is an example of developing wireshark plug-in by Lua.

3. Simple Example for Lua dissector

Suppose we want to develop a dissector for DHCPv4 Bulk Leasequery. It is TCP based protocol and one DHCPv4 Bulk Leasequery packet includes two parts, 1: size of the remaining part (2 bytes), 2: a bootp packet contains Leasequery information.

3.1 Simple dissector

To make it simple, we take an assumption, one TCP packet contains only one Leasequery packet and there is no TCP reassemble issue.

In the script, first, we define a new protocol p_lqv4 and the two fields f_size, f_text, which consist of leasequery packet. Then the most important part, dissector function p_lqv4.dissector(buf, pkt, root), the input paramter buf is the data buffer for this dissector to parse and the pkt is the packets information for reassemble, etc; and the root is the parsed protocol tree shown in the “Packet Details” pane.

do
    local p_lqv4 = Proto("lqv4","Leasequery v4");
    local f_size = ProtoField.uint16("lqv4.size","size",base.DEC)
    local f_text = ProtoField.string("lqv4.content","bin")

    p_lqv4.fields = { f_size, f_text }

    function p_lqv4.dissector(buf, pkt, root)
        local totalsize = buf:len()
        if leftsize <= 2 then
           return
        end
        local size = buf(0,2):uint()
        local t = root:add(p_lqv4,buf(0,totalsize))
        t:add(f_size,buf(0,2))
        local dissector = Dissector.get("bootp")
        if dissector ~= nil then
          dissector:call(buf(2,size):tvb(),pkt,t)
        end
    end

    local wtap_encap_table = DissectorTable.get("wtap_encap")
    local tcp_encap_table = DissectorTable.get("tcp.port")
    wtap_encap_table:add(wtap.USER15,p_lqv4)
    wtap_encap_table:add(wtap.USER12,p_lqv4)
    tcp_encap_table:add(67,p_lqv4)
end

3.2 Multi-Leasequery messages in one packet

When there are multi-leasequery messages in one TCP packet, we can use a cursor offset to indicate the start of one leasequery packet and use while to go through each leasequery packet inside the TCP packet.

do
    local p_lqv4 = Proto("lqv4","Leasequery v4");
    local f_size = ProtoField.uint16("lqv4.size","size",base.DEC)
    local f_text = ProtoField.string("lqv4.content","bin")

    p_lqv4.fields = { f_size, f_text }

    function p_lqv4.dissector(buf, pkt, root)
        local offset = 0
        local totalsize = buf:len()
        local leftsize = buf:len()

        while leftsize > 0 do
          local size = buf(offset,2):uint()
          local nxtpdu = offset + size + 2

          local t = root:add(p_lqv4,buf(offset,2))
          t:add(f_size,buf(offset,2))
          local dissector = Dissector.get("bootp")
          if dissector ~= nil then
            dissector:call(buf(offset+2,size):tvb(),pkt,t)
          end

          offset = nxtpdu
          leftsize = buf(offset):tvb():len()
        end
    end

    local wtap_encap_table = DissectorTable.get("wtap_encap")
    local tcp_encap_table = DissectorTable.get("tcp.port")
    wtap_encap_table:add(wtap.USER15,p_lqv4)
    wtap_encap_table:add(wtap.USER12,p_lqv4)
    tcp_encap_table:add(67,p_lqv4)
end

3.3 Reassemble TCP packets

In order to support TCP reassemble, we need to us two parameters desegment_len and desegment_offset in the input parameter pkt. desegment_len is a variable to indicate wireshark how many bytes needed to complete this parse, wireshark will try to find the following packets to reassemble them together. desegment_offset is a cursor indicates how many bytes have been processed.

do
    local p_lqv4 = Proto("lqv4","Leasequery v4");
    local f_size = ProtoField.uint16("lqv4.size","size",base.DEC)
    local f_text = ProtoField.string("lqv4.content","bin")

    p_lqv4.fields = { f_size, f_text }

    function p_lqv4.dissector(buf, pkt, root)
        local offset = pkt.desegment_offset or 0
        local totalsize = buf:len()
        local leftsize = buf:len() - offset

        if leftsize < 2 then
            pkt.desegment_len = DESEGMENT_ONE_SEGMENT
            pkt.desegment_offset = offset
            return
        end

        local size = buf(offset,2):uint()
        local nxtpdu = offset + size + 2
        if nxtpdu > totalsize then
          pkt.desegment_len = nxtpdu - buf:len()
          pkt.desegment_offset = offset
          return
        end

        local t = root:add(p_lqv4,buf(offset,2))
        t:add(f_size,buf(offset,2))
        local dissector = Dissector.get("bootp")
        if dissector ~= nil then
          dissector:call(buf(offset+2,size):tvb(),pkt,t)
        end
    end
    local wtap_encap_table = DissectorTable.get("wtap_encap")
    local tcp_encap_table = DissectorTable.get("tcp.port")
    wtap_encap_table:add(wtap.USER15,p_lqv4)
    wtap_encap_table:add(wtap.USER12,p_lqv4)
    tcp_encap_table:add(67,p_lqv4)
end

4. DHCPv4 Bulk Leasequery dissector

Combining the above three parts described in Chapter 3 together, then we have a full-featured dissector shown as below. This DHCPv4 Leasequery dissector supports multi leasequery messages within one TCP packet and TCP reassemble for Leasequery message. The following gives the complete code of this dissector.

--[[
  This is for DHCPv4 Bulk leasequery dissector,
  For Windowns, cp this file to System\Program Files\Wireshark
  For Linux, cp this file to /etc/wireshark
  Add "dofile("packet_lqv4.lua")" to the bottom of File "init.lua"
  Author: ylxxwx@gmail.com
--]]
do
    local p_lqv4 = Proto("lqv4","Leasequery v4");
    local f_size = ProtoField.uint16("lqv4.size","size",base.DEC)
    local f_text = ProtoField.string("lqv4.text","Text")
    local p_port = 67

    p_lqv4.fields = { f_size, f_text }

    function p_lqv4.dissector(buf,pkt,root)
        local offset = pkt.desegment_offset or 0
        local totalsize = buf:len()
        local leftsize = buf:len() - offset

        while leftsize > 0 do
          if leftsize < 2 then
            pkt.desegment_len = DESEGMENT_ONE_SEGMENT
            pkt.desegment_offset = offset
            return offset
          end

          local size = buf(offset,2):uint()
          local nxtpdu = offset + size + 2

          if nxtpdu > totalsize then
            pkt.desegment_len = nxtpdu - totalsize
            pkt.desegment_offset = offset
            return
          end

          local lqblock = root:add(p_lqv4,buf(offset,size + 2))
          lqblock:add(f_size,buf(offset,2))
          local dissector = Dissector.get("bootp")
          if dissector ~= nil then
            dissector:call(buf(offset+2,size):tvb(),pkt,lqblock)
          end
          pkt.cols.protocol = "DHCPv4BulkLeasequery"

          offset = nxtpdu
          leftsize = buf(offset):tvb():len()
          if leftsize == 0 then
             pkt.desegment_len = 0
             pkt.desegment_offset = 0
             return
          end
        end
    end
    local wtap_encap_table = DissectorTable.get("wtap_encap")
    local tcp_encap_table = DissectorTable.get("tcp.port")
    wtap_encap_table:add(wtap.USER15,p_lqv4)
    wtap_encap_table:add(wtap.USER12,p_lqv4)
    tcp_encap_table:add(p_port,p_lqv4)
end

5. Add the new dissector into wireshark

5.1 Check if your wireshark supports Lua?

Click Menu->Help->About Wireshark. If you find without Lua, you need to upgrade wireshark to the latest version. If you find with Lua 5.2, congratulations. You can go to 5.2.

5.2 Copy the new dissector to wireshark directory

Copy the dissector to wireshark directory. In different system the wireshark directory is different, shown below.

SystemPath
windows System\Program Files\Wireshark
Linux /etc/wireshark

5.3 Enable the new plug-in

Add dofile("[dissector file]") to the file init.lua which locates in the wireshark directory. Then restart wireshark. It works.

?

用Lua写Wireshark插件

原文:http://www.cnblogs.com/ylxxwx/p/4985379.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!