Wireshark Lua TCP反混淆插件开发:两项技术问题求助
解决Wireshark TCP反混淆插件的两个核心问题
问题1:获取TCP头并正确调用TCP解析器
你当前代码直接处理的tvb仅包含TCP载荷部分,TCP头已被Wireshark原生TCP解析器处理完毕。要重新构造完整TCP报文并调用解析器,需从原始数据包中提取TCP头:
- 从父层缓冲区获取IP+TCP完整数据:通过
tvb:parent()拿到包含IP头和TCP头的原始缓冲区。 - 计算IP头长度:IPv4头长度由IP头第一个字节的高4位决定(值×4),以此定位TCP头起始位置。
- 计算TCP头长度:TCP头第一个字节的高4位×4,截取对应长度的TCP头数据。
- 拼接TCP头与解密后的载荷,构造完整的TCP报文缓冲区。
核心代码片段:
-- 获取包含IP+TCP的父层缓冲区 local parent_tvb = tvb:parent() if not parent_tvb then return end -- 计算IPv4头长度(若为IPv6,头长度固定40字节) local ip_hdr_len = (parent_tvb:get_index(0) & 0xF0) >> 2 local tcp_hdr_start = ip_hdr_len -- 计算TCP头长度 local tcp_hdr_len = (parent_tvb:get_index(tcp_hdr_start) & 0xF0) >> 2 local tcp_hdr_tvb = parent_tvb:range(tcp_hdr_start, tcp_hdr_len) -- 拼接TCP头与解密后的载荷,生成完整TCP报文tvb local full_tcp_bytes = tcp_hdr_tvb:bytes() .. decrypted_payload_tvb:bytes() local full_tcp_tvb = ByteArray.tvb(full_tcp_bytes, "Decrypted TCP")
问题2:避免递归调用
由于你将自定义 dissector 注册到了tcp.port的8000端口,调用原生TCP解析器时会再次触发端口匹配,导致递归。两种解决方法:
方法1:临时修改端口信息
调用TCP解析器前,临时将端口改为非8000值,解析完成后恢复原始端口:
-- 保存原始端口 local original_dst_port = pinfo.dst_port local original_src_port = pinfo.src_port -- 临时切换到非8000端口 if pinfo.dst_port == 8000 then pinfo.dst_port = 8001 end if pinfo.src_port == 8000 then pinfo.src_port = 8001 end -- 调用TCP解析器 Dissector.get("tcp"):call(full_tcp_tvb, pinfo, tree) -- 恢复原始端口 pinfo.dst_port = original_dst_port pinfo.src_port = original_src_port
方法2:直接调用下层协议解析器
若已知解密后载荷的具体协议(如HTTP),可跳过TCP端口匹配,直接调用对应协议的 dissector:
-- 直接调用HTTP解析器处理解密后的载荷 Dissector.get("http"):call(decrypted_payload_tvb, pinfo, tree)
完整修改后的代码
local NAME = "test" local test = Proto(NAME, "test TCP Protocol") local fields = test.fields function test.dissector(tvb, pinfo, tree) if pinfo.dst_port == 8000 or pinfo.src_port == 8000 then -- 执行0xAA异或解密载荷 local tmp = tvb:bytes() for i=0, tmp:len() - 1 do local value = tmp:get_index(i) tmp:set_index(i, value ~ 0xAA) end local decrypted_payload_tvb = tmp:tvb() -- 获取TCP头并构造完整TCP报文 local parent_tvb = tvb:parent() if not parent_tvb then return end -- 适配IPv4,若为IPv6需改为固定40字节 local ip_hdr_len = (parent_tvb:get_index(0) & 0xF0) >> 2 local tcp_hdr_start = ip_hdr_len local tcp_hdr_len = (parent_tvb:get_index(tcp_hdr_start) & 0xF0) >> 2 local tcp_hdr_tvb = parent_tvb:range(tcp_hdr_start, tcp_hdr_len) local full_tcp_bytes = tcp_hdr_tvb:bytes() .. decrypted_payload_tvb:bytes() local full_tcp_tvb = ByteArray.tvb(full_tcp_bytes, "Decrypted TCP") -- 临时修改端口避免递归 local original_dst_port = pinfo.dst_port local original_src_port = pinfo.src_port if pinfo.dst_port == 8000 then pinfo.dst_port = 8001 end if pinfo.src_port == 8000 then pinfo.src_port = 8001 end Dissector.get("tcp"):call(full_tcp_tvb, pinfo, tree) -- 恢复原始端口 pinfo.dst_port = original_dst_port pinfo.src_port = original_src_port end end DissectorTable.get("tcp.port"):add(8000, test)
内容的提问来源于stack exchange,提问作者kaho J
相关产品推荐
相关产品推荐

