zoukankan      html  css  js  c++  java
  • 【wireshark】插件开发(四):Lua插件Post-dissector和Listener

    1. Post-dissector

    post-dissector和dissector不同,它会在所有dissectors都执行过后再被执行,这也就post前缀的由来。post-dissector的构建方式和dissector差不多,主要一个区别是注册的方式,post-dissector调用的是register_postdissetor接口。下面给出两个示例。

    1.1 最简单的Post-dissector

    这个示例主要是演示post-dissector脚本的骨架,它的功能是在packet list的所有info列加上了一个字符串"hello world"。

    -- @brief A simple post-dissector, just append string to info column
    -- @author zzq
    -- @date 2015.08.13
    
    local myproto = Proto("hello","Dummy proto to edit info column")
    
    -- the dissector function callback
    function myproto.dissector(tvb,pinfo,tree)
        pinfo.cols.info:append(" hello world")
    end
    
    -- register our new dummy protocol for post-dissection
    register_postdissector(myproto)

    此插件运行效果如下图:

    1.2 识别协议特征

    这个示例简单地演示了如何使用post-dissector来识别协议特征。例子中,通过识别tcp载荷中是否含有字符串”weibo“来判断报文是否为weibo报文,如果是,则在packet list的protocol列标出,并在proto tree添加树节点,给出滑动特征在TCP载荷中的位置。

    代码如下,其中有好多小问题,但这不是重点,重点是了解如何编写Lua插件。

    -- @brief A post-dissector, to indentify pattern in payload
    -- @author zzq
    -- @date 2015.08.26
    
    local weibo = Proto("weibo", "Weibo Service")
    
    local function get_payload_offset(data, proto_type)
        local mac_len = 14;
        local total_len;
        local ip_len = (data(14, 1):uint() - 64) * 4;
        if (proto_type == 0x06) then
            local tcp_len = (data(46, 1):uint()/16) * 4;
            total_len = mac_len + ip_len + tcp_len;
        elseif (proto_type == 0x11) then
            local udp_len = 8;
            total_len = mac_len + ip_len + udp_len;
        end
        return total_len
    end
    
    -- the dissector function callback
    function weibo.dissector(tvb, pinfo, tree)
        local proto_type = tvb(23, 1):uint();
        if(proto_type ~= 0x06) then
            return
        end
        
        local offset = get_payload_offset(tvb, proto_type)
        local data = tvb(offset):string();
        local i, j = string.find(data, "weibo")
        if(i) then
            pinfo.cols.protocol = weibo.name
            local subtree = tree:add(weibo, tvb(offset+i-1))
            subtree:append_text(", ptn_pos: " .. i .. "-" .. j)
        end
    end
    
    -- register our plugin for post-dissection
    register_postdissector(weibo)

    运行效果如下图。

    2. Listener

    Listner用来设置一个监听条件,当这个条件发生时,执行事先定义的动作。

    实现一个Listner插件至少要实现以下接口:

    • 创建Listener
      listener = Listener.new([tap], [filter]),其中tap, filter分别是tap和过滤条件
    • listener.packet
      在条件命中时调用
    • listener.draw
      在每次需要重绘GUI时调用
    • listener.reset
      清理时调用

    以上实现代码一般都包在一个封装函数中,最后把这个函数注册到GUI菜单:

    register_menu(name, action, [group])

    下面的示例代码对pcap文件中的http报文进行了简单的计数统计:

    -- @brief a simple Listener plugin
    -- @author zzq
    -- @date 2015.08.13
    
    local function zzq_listener()
        local pkts = 0
        local win = TextWindow.new("zzq Listener")
        local tap = Listener.new(nil, "http")
        
        win:set_atclose(function() tap:remove() end)
        
        function tap.packet (pinfo, tvb, tapinfo)
            pkts = pkts + 1
        end
        
        function tap.draw()
            win:set("http pkts: " .. pkts)
        end
        
        function tap.reset()
            pkts = 0
        end
        
        -- Rescan all packets and just run taps - don’t reconstruct the display.
        retap_packets()
    end
       
    register_menu("freeland/zzq Listener", zzq_listener, MENU_STAT_GENERIC)

    要查看运行结果,要选择”Statistics“菜单中的freeland/zzq Listerner子菜单来触发。此插件的运行效果如下图:

  • 相关阅读:
    PHP编程基础学习(一)——数据类型
    6-6 带头结点的链式表操作集(20 分)
    6-5 链式表操作集(20 分)
    6-4 链式表的按序号查找(10 分)
    6-3 求链式表的表长(10 分)
    6-2 顺序表操作集(20 分)
    6-1 单链表逆转(20 分)
    学生成绩管理系统(六):项目总结
    学生成绩管理系统(五):系统的完善与数据库的链接
    学生成绩管理系统(四)
  • 原文地址:https://www.cnblogs.com/zzqcn/p/4846745.html
Copyright © 2011-2022 走看看