共享字段的两个 Wireshark 解剖器

我正在编写一个用于自定义协议的 Wireshark 解剖器。该协议有两个变体,在转储文件中通常无法区分。因此,用户通常会选择正确的变体进行解码。

两个变体共享许多“ProtoField”和许多结构,这就是我希望只编写大部分解剖代码并将两个顶层解剖器调用这些组件的原因。

大致想法是:

local custom_var1 = Proto("custom_var1", "我的自定义协议变体1")
local custom_var2 = Proto("custom_var2", "我的自定义协议变体2")

-- 实际的头部和数据块比单个整数复杂得多
local header = ProtoField.uint8("custom.head", "头部")
local data1 = ProtoField.uint64("custom.data1", "数据1")
local data2 = ProtoField.uint32("custom.data2", "数据2")
local data3 = ProtoField.uint8("custom.data3", "数据3")

custom_var1.fields = {header, data1, data2}
custom_var2.fields = {header, data1, data2, data3}

local function dissect_header(tvb, tree)
    tree:add(header, tvb(0, 1))
end

local function dissect_data1(tvb, tree)
    tree:add(data1, tvb(0, 8))
end

local function dissect_data2(tvb, tree)
    tree:add(data2, tvb(0, 4))
end

local function dissect_data3(tvb, tree)
    tree:add(data3, tvb(0, 1))
end

function custom_var1.dissector(tvb, pinfo, root)
    pinfo.cols.protocol:set(custom_var1.name)
    local tree = root:add(custom_var1, tvb(0, 13))

    dissect_header(tvb(0), tree)
    dissect_data1(tvb(1), tree)
    dissect_data2(tvb(9), tree)
end

function custom_var2.dissector(tvb, pinfo, root)
    pinfo.cols.protocol:set(custom_var2.name)
    local tree = root:add(custom_var2, tvb(0, 14))

    dissect_header(tvb(0), tree)
    dissect_data2(tvb(1), tree)
    dissect_data1(tvb(5), tree)
    dissect_data3(tvb(13), tree)
end

tcp_port = DissectorTable.get("tcp.port")
tcp_port:add(31337,custom_var1)
tcp_port:add(31337,custom_var2)

我的问题:当我将 lua 文件放入我的插件目录中并启动 wireshark 时,我会看到一个带有黑色背景的“Wireshark Debug Console”(不是白色的),带有 lua 控制台的消息“18:08:56.505 Err LUA PANIC: fields can be registered only once”,然后是“按任意键退出”,在我做任何其他事情之前。按下一个键后,wireshark 立即退出。

如何编写具有共享字段的两个解剖器,而不需要太多的代码复制?

点赞
用户2755698
用户2755698

为什么不只编写一个解析器,并为用户添加首选项,以选择应用哪个变体?例如:

-- 协议
local p_custom = Proto("custom", "我的定制协议")
local data_dis = Dissector.get("data")

-- 首选项
local default_settings = {
    variant = 1
}

local variant_pref_enum = {
    { 1, "1", 1 },
    { 2, "2", 2 }
}

p_custom.prefs.variant = Pref.enum("Variant", default_settings.variant,
    "变体", variant_pref_enum)

-- 字段
local pf = {
    header = ProtoField.bytes("custom.head", "头部"),
    data1 = ProtoField.uint64("custom.data1", "数据 1"),
    data2 = ProtoField.uint32("custom.data2", "数据 2"),
    data3 = ProtoField.uint8("custom.data3", "数据 3")
}
p_custom.fields = pf

-- 解析
function p_custom.dissector(tvbuf, pinfo, tree)
    local custom_tree = tree:add(p_custom, tvbuf(0, -1))

    custom_tree:add(pf.header, tvbuf(0, 1))
    if p_custom.prefs.variant == 1 then
        -- 解析变体 1
        pinfo.cols.protocol:set("CUSTOM 1")
        custom_tree:append_text(": 变体 1")
        custom_tree:add(pf.data1, tvbuf(1, 8))
        custom_tree:add(pf.data2, tvbuf(9, 4))
    elseif p_custom.prefs.variant == 2 then
        -- 解析变体 2
        pinfo.cols.protocol:set("CUSTOM 2")
        custom_tree:append_text(": 变体 2")
        custom_tree:add(pf.data2, tvbuf(1, 4))
        custom_tree:add(pf.data1, tvbuf(5, 8))
        custom_tree:add(pf.data3, tvbuf(13, 1))
    else
        -- 未知变体
        pinfo.cols.protocol:set("CUSTOM ?")
        custom_tree:append_text(": 未知变体")
        data_dis:call(tvbuf:range(1, tvbuf:len() - 1):tvb(), pinfo, tree)
    end
end

-- 注册
local tcp_port = DissectorTable.get("tcp.port")
tcp_port:add(31337, p_custom)

当然,如果通用头部中提供了可用于自动确定应用哪个变体的信息,则根本不需要首选项。

2021-02-05 20:01:59