好记性不如铅笔头

C && C++, Lua, 编程, 网络通讯

使用LUA脚本来扩展wireshark的功能

当我们需要拓展wireshark的功能时,有2种办法,一种是直接修改源代码,重新编译,发布,这种方式比较复杂,但是可以改动到非常底层的功能,另一种是写lua插件注册到wireshark中,这种方式比较简单,但是功能有限,不过一般情况下都可以满足我们的需求。
wireshark的官方文档第二章节【 II. Wireshark Development 】描述了如何定制和开发wireshark第10节【 10. Lua Support in Wireshark 】和第11节【 11. Wireshark’s Lua API Reference Manual 】描述了wireshark的LUA支持情况,由于官方文档写的非常清楚,这里就简单的笔记几个实例来描述如何使用wireshark的lua脚本功能。

参考文档

https://www.wireshark.org/docs/wsdg_html_chunked/wsluarm.html
https://www.cnblogs.com/zzqcn/p/4827251.html

lua插件最简单实现

新建一个hello_wireshark.lua文件,内容如下:

window = nil

local function demo_main_dlg(user_input)
    window = TextWindow.new("hello_wireshark demo")
    window:append(user_input)
end

local function demo_input_dlg()
    new_dialog("input demo",demo_main_dlg,"please input:")
end

register_menu("lua_demo/hello_wireshark",demo_input_dlg,MENU_TOOLS_UNSORTED)

然后打开wireshark,点击菜单栏【 帮助 】->【 关于wireshark 】->【 文件夹 】,找到< 全局配置 >,如下图:

然后打开全局配置文件夹,修改文件夹下的init.lua,将 hello_wireshark.lua 注册到Wireshark中 。如下图:

重新打开wireshark,点击菜单栏【 工具 】,就可以看到我们的插件了,如下图:

如果我们修改了lua插件,可以点击菜单栏【 分析 】-> 【 重新载入Lua插件 】,或者快捷键< Ctrl + Shift + L > 来生效,不用重启wireshark。

过滤IP脚本

下面我们笔记一个可以简单过滤IP的lua脚本,内容如下:

window = nil

-- 判断指定元素value是否在数组tab中
local function is_include(value, tab)
    for k,v in ipairs(tab) do
      if v == value then
            return true
      end
    end
    return false
end

-- 将一个字符串分割为一个数组
local function split_string(input, delimiter)
    input = tostring(input)
    delimiter = tostring(delimiter)
    if(delimiter=='') then return false end
    local pos,arr = 0, {}
    for st,sp in function() return string.find(input, delimiter, pos, true) end do
        table.insert(arr, string.sub(input, pos, st - 1))
        pos = sp + 1
    end
    table.insert(arr, string.sub(input, pos))
    return arr
end

-- 支持多个IP地址输入,每个IP间使用','进行分割
-- 输入的IP数组
local input_ip_table = nil
local function demo_main_dlg(input_ips)
    input_ip_table = split_string(input_ips, ",")

    window = TextWindow.new("hello_wireshark demo")
    local tap = Listener.new() 
    
    local function remove()
        tap:remove()
    end
    window:set_atclose(remove)
    
    function tap.packet(pinfo,tvb)
        if(not ( is_include(tostring(pinfo.src), input_ip_table) or is_include(tostring(pinfo.dst), input_ip_table) ) )  then
            return
        end
        content = string.format("idx:%d\t %s:%d ==>> %s:%d",pinfo.number, pinfo.src, pinfo.src_port, pinfo.dst, pinfo.dst_port)
        window:append(content.."\n")
    end

    function tap.draw()
    end

    function tap.reset()
        window:clear()
    end

    retap_packets()
    
    -- 将输入的IP地址做成filter字符串,放到wireshark主进程里面
    local filter_pattern = nil
    for i, dev_ip in ipairs(input_ip_table) do
        if(filter_pattern == nil) then
            filter_pattern = string.format("ip.addr ==%s", dev_ip)
        else
            filter_pattern = filter_pattern..string.format(" or ip.addr ==%s", dev_ip)
        end
    end 
    set_filter( filter_pattern )
    apply_filter()

end

local function demo_input_dlg()
    new_dialog("input ipaddr",demo_main_dlg,"ips:")
end

register_menu("lua_demo/hello_wireshark",demo_input_dlg,MENU_TOOLS_UNSORTED)

我们可以测试下该插件的效果,使用wireshark打开一个抓包报文文件,然后重新载入下Lua插件,然后输入IP:255.255.255.255,可以看到效果了。如下图:

Leave a Reply

15 − 3 =

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据