lua - 两个具有共享字段的 Wireshark 解剖器
问题描述
我正在为自定义协议编写一个wireshark 解剖器。该协议有两种变体,在查看转储时通常无法区分。所以通常用户会简单地选择正确的变体来解码。
这两个变体共享很多ProtoField
s 和很多结构,这就是为什么我希望只编写一次大部分剖析代码,然后有两个顶级剖析器调用这些组件。
粗略的想法是:
local custom_var1 = Proto("custom_var1", "My custom protocol Variant 1")
local custom_var2 = Proto("custom_var2", "My custom protocol Variant 2")
-- my actual header and data blocks are a lot more complex than single integers of course
local header = ProtoField.uint8("custom.head", "Header")
local data1 = ProtoField.uint64("custom.data1", "Data 1")
local data2 = ProtoField.uint32("custom.data2", "Data 2")
local data3 = ProtoField.uint8("custom.data3", "Data 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
,Press any key to exit
然后我可以做任何其他事情。按下一个键后,wireshark 立即存在。
如何编写两个具有共享字段的剖析器,而无需过多的代码重复?
解决方案
为什么不只写一个解析器并添加一个偏好让用户选择应用哪个变体?例如:
-- Protocol
local p_custom = Proto("custom", "My custom protocol")
local data_dis = Dissector.get("data")
-- Preferences
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,
"The variant", variant_pref_enum)
-- Fields
local pf = {
header = ProtoField.bytes("custom.head", "Header"),
data1 = ProtoField.uint64("custom.data1", "Data 1"),
data2 = ProtoField.uint32("custom.data2", "Data 2"),
data3 = ProtoField.uint8("custom.data3", "Data 3")
}
p_custom.fields = pf
-- Dissection
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
-- Dissect Variant 1
pinfo.cols.protocol:set("CUSTOM 1")
custom_tree:append_text(": Variant 1")
custom_tree:add(pf.data1, tvbuf(1, 8))
custom_tree:add(pf.data2, tvbuf(9, 4))
elseif p_custom.prefs.variant == 2 then
-- Dissect Variant 2
pinfo.cols.protocol:set("CUSTOM 2")
custom_tree:append_text(": Variant 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
-- Unknown Variant
pinfo.cols.protocol:set("CUSTOM ?")
custom_tree:append_text(": Unknown Variant")
data_dis:call(tvbuf:range(1, tvbuf:len() - 1):tvb(), pinfo, tree)
end
end
-- Registration
local tcp_port = DissectorTable.get("tcp.port")
tcp_port:add(31337, p_custom)
当然,如果公共标头中有可用信息可以帮助确定自动应用哪个变体,则根本不需要首选项。
推荐阅读
- pytest - 使用 pytest 运行并行测试套件,而无需在每个测试套件中重新排序测试
- python - 将 python 请求与代理一起使用时出错
- javascript - 如何使用时刻比较javascript中的日期和时间
- python - 如何在 Python 中触发值变化函数?
- reactjs - 如何设置功能组件的打开/关闭状态
- javascript - 我的不和谐机器人对踢命令没有响应
- css - :first-line css – 在 Safari 中工作,而不是在 Firefox/Chrome 中
- sql - 将 SQL 转换为 SQLAlchemy 一
- python - 如何将具有相同 ID 的一列与 Pandas 中的其余列连接?
- python - 多次执行“finish_bundle”方法:Apache beam、Google Dataflow