【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子菜單來觸發。此插件的運行效果如下圖:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM