You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Lua dissector中向子树添加变长int/float/string数组字段

解决Wireshark Lua Dissector动态变长数组解析问题

核心思路

不用预先创建与数组元素数量匹配的ProtoField,而是复用单个通用字段或直接动态指定解析类型,循环解析每个元素时自定义显示名称,以此适配未知长度的统一类型数组。

实现步骤与代码示例

1. 定义协议与偏好设置(加载数组长度)

先创建协议对象,添加偏好项指定存储数组长度的文件路径,同时实现偏好变更时的文件读取逻辑:

local my_proto = Proto("myproto", "My Custom Protocol")

-- 偏好设置:指定存储数组长度的文件路径
local pref_array_len_file = Pref.string("array_length_file", "", "Path to file containing array length")

-- 全局存储从文件读取的数组长度
local array_length = 0

-- 偏好变更时重新读取文件内容
function my_proto.prefs_changed()
    if pref_array_len_file.value ~= "" then
        local f = io.open(pref_array_len_file.value, "r")
        if f then
            array_length = tonumber(f:read("*a")) or 0
            f:close()
        end
    end
end

2. 定义通用字段(按需选择对应类型)

针对统一类型的数组,定义一个通用ProtoField,后续循环解析时复用,仅修改显示名称:

-- 示例:32位无符号整数类型数组
local generic_field = ProtoField.uint32("myproto.array.element", "Array Element", base.DEC)

-- 如果是float类型数组,替换为:
-- local generic_field = ProtoField.float("myproto.array.element", "Array Element")

-- 如果是字符串类型数组(假设每个元素固定16字节),替换为:
-- local generic_field = ProtoField.string("myproto.array.element", "Array Element")

my_proto.fields = { generic_field }

3. 解析函数中处理变长数组

在 dissector 主函数里,定位数组起始偏移后,根据读取到的array_length循环解析每个元素:

function my_proto.dissector(buffer, pinfo, tree)
    pinfo.cols.protocol = my_proto.name
    local subtree = tree:add(my_proto, buffer(), "My Protocol Data")

    -- 假设数组从偏移4字节处开始,根据实际协议调整
    local offset = 4

    -- 仅当数组长度有效时执行解析
    if array_length > 0 then
        local array_subtree = subtree:add(buffer(offset), string.format("Array (%d elements)", array_length))

        for i = 0, array_length - 1 do
            local elem_name = string.format("Element [%d]", i)
            local elem_data = nil

            -- 根据数组类型读取对应长度的数据并解析
            if generic_field.type == ftypes.UINT32 then
                elem_data = buffer(offset, 4)
                array_subtree:add(generic_field, elem_data):set_text(elem_name .. ": " .. elem_data:uint())
                offset = offset + 4
            elseif generic_field.type == ftypes.FLOAT then
                elem_data = buffer(offset, 4)
                array_subtree:add(generic_field, elem_data):set_text(elem_name .. ": " .. elem_data:float())
                offset = offset + 4
            elseif generic_field.type == ftypes.STRING then
                -- 字符串元素长度按需调整,这里假设为16字节
                elem_data = buffer(offset, 16)
                array_subtree:add(generic_field, elem_data):set_text(elem_name .. ": " .. elem_data:string())
                offset = offset + 16
            end
        end
    end
end

-- 注册 dissector(示例:绑定到UDP端口1234,根据实际协议调整)
local udp_port = DissectorTable.get("udp.port")
udp_port:add(1234, my_proto)

关键细节说明

  • 动态显示名称:通过set_text()方法覆盖通用字段的默认名称,实现每个数组元素的个性化标识(如Element [0])。
  • 类型适配:根据数组实际类型调整读取的字节长度和解析方法(uint()/float()/string()),确保解析结果准确。
  • 偏好生效逻辑:在prefs_changed()回调中实时读取文件内容,修改偏好后无需重启Wireshark即可生效。

内容的提问来源于stack exchange,提问作者Arnault Bonafos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 15:03:16