Wireshark Lua脚本如何按序列号匹配请求对应应答报文编号
Wireshark Lua 私有协议请求应答匹配实现
Wireshark Lua 没有内置类SQL风格的跨报文查询接口,要实现序列号匹配请求-应答报文的功能,核心思路是通过监听器预扫描所有报文,缓存应答报文的序列号与报文编号的映射关系,解析请求报文时直接查表获取匹配结果,性能和逻辑都满足需求。
- 初始化全局缓存
Wireshark加载Lua脚本后全局变量会常驻内存,先初始化缓存表避免重复加载脚本时数据错乱:-- 序列号-应答报文编号映射缓存 if not seq_answer_map then seq_answer_map = {} proto_listener = nil end - 注册报文监听器预缓存应答报文信息
用Wireshark提供的Listener接口遍历所有命中私有协议的报文,提取应答包的序列号和自身报文编号存入缓存,注意要先移除旧监听器避免重复注册:-- 移除已存在的旧监听器 if proto_listener then proto_listener:remove() end -- 替换成你自己注册的Proto名称,监听器只会处理对应协议的报文 proto_listener = Listener.new(nil, "your_proto_name") -- 每个匹配的报文都会触发这个函数 function proto_listener.packet(pinfo, tvb, tapdata) -- 替换成你协议里判断应答包的字段逻辑,比如req/resp标志位 local is_resp_pkt = MyProto.flag_is_answer.value if is_resp_pkt then local resp_seq = MyProto.AnswerSequenceNumber.value -- pinfo.number就是Wireshark列表里显示的报文编号 seq_answer_map[resp_seq] = pinfo.number end end -- 捕获文件重载、打开新文件时清空缓存 function proto_listener.reset() seq_answer_map = {} end - 解析请求报文时查表获取匹配的应答编号
在你自己的协议解析主函数(dissector)里,判断当前包是请求包时,直接用请求序列号查缓存表即可,逻辑和你预期的完全一致:-- dissector函数内,判断当前是请求包 local is_req_pkt = MyProto.flag_is_request.value local AnswerMessageNumber = nil if is_req_pkt then local req_seq = MyProto.RequestSequenceNumber.value -- 查到就返回对应报文编号,查不到默认就是nil AnswerMessageNumber = seq_answer_map[req_seq] end -- 后续可以把匹配结果加到解析树、做着色规则判断等 subtree:add(MyProto.matched_answer_num, AnswerMessageNumber or "无匹配应答")
注意事项:
- 首次加载脚本、打开新捕获文件后,按
Ctrl+R重载捕获文件,让监听器从头扫描所有报文生成完整缓存,否则会出现早于脚本加载的报文匹配不到的问题- 如果你的协议存在同序列号重复应答的异常场景,可以把缓存值改成数组结构,存储所有匹配的应答报文编号
- 不要在dissector里循环遍历所有报文做匹配,捕获包数量大时会导致Wireshark卡顿,监听器预缓存是官方推荐的跨包关联方案
内容的提问来源于stack exchange,提问作者Arkony
相关产品推荐
相关产品推荐

