Last active
November 19, 2022 14:22
-
-
Save xWTF/e124db3e48abc92184e583168fea5edb to your computer and use it in GitHub Desktop.
Wireshark Lua Dissector: Yamux (Yet another Multiplexer) by HashiCorp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
Wireshark Lua Dissector | |
Protocol: [Yamux](https://github.com/hashicorp/yamux) by HashiCorp | |
Get updates from [this gist](https://gist.github.com/xWTF/e124db3e48abc92184e583168fea5edb) | |
Copyright © 2022 xWTF | |
This work is free. You can redistribute it and/or modify it under the | |
terms of the Do What The Fuck You Want To Public License, Version 2, | |
as published by Sam Hocevar. See the COPYING file or http://www.wtfpl.net/ | |
for more details. | |
--]] | |
local yamux_protocol = Proto("Yamux", "Yamux Protocol"); | |
local types = { | |
[0x0] = "Data", | |
[0x1] = "Window Update", | |
[0x2] = "Ping", | |
[0x3] = "Go Away" | |
} | |
local flagMasks = { | |
[0x0] = "", | |
[0x1] = "SYN", | |
[0x2] = "ACK", | |
[0x4] = "FIN", | |
[0x8] = "RST" | |
} | |
local goAwayErrors = { | |
[0x0] = "Normal termination", | |
[0x1] = "Protocol error", | |
[0x2] = "Internal error" | |
} | |
local f_version = ProtoField.uint8("yamux.version", "Version") | |
local f_type = ProtoField.uint8("yamux.type", "Type", base.HEX, types) | |
local f_flags = ProtoField.uint16("yamux.flags", "Flags", base.HEX, flagMasks, 0xFF) | |
local f_stream = ProtoField.uint32("yamux.stream", "Stream ID") | |
local f_length = ProtoField.uint32("yamux.len", "Length") | |
local f_payload = ProtoField.bytes("yamux.payload", "Yamux payload") | |
yamux_protocol.fields = {f_version, f_type, f_flags, f_stream, f_length, f_payload} | |
local function dissect(offset, buf, tree) | |
local tvb_len = buf:len() - offset | |
-- minimal header length is 12 bytes | |
if tvb_len < 12 then | |
return tvb_len - 12 | |
end | |
-- the version field is always set to 0 | |
local version = buf(offset, 1) | |
if version:uint() ~= 0 then | |
return 0 | |
end | |
local type = buf(offset + 1, 1):uint() | |
if types[type] == nil then | |
return 0 | |
end | |
local t = tree:add(yamux_protocol, buf(offset, 12)) | |
t:add(f_version, version) | |
t:add(f_type, buf(offset + 1, 1)) | |
t:add(f_flags, buf(offset + 2, 2)) | |
t:add(f_stream, buf(offset + 4, 4)) | |
local payload_len = buf(offset + 8, 4) | |
local item_length = t:add(f_length, payload_len) | |
payload_len = payload_len:uint() | |
tvb_len = tvb_len - 12 | |
if type == 0x0 then | |
if tvb_len < payload_len then | |
return tvb_len - payload_len | |
end | |
t:add(f_payload, buf(offset + 12, payload_len)) | |
t:set_len(12 + payload_len) | |
return 12 + payload_len | |
elseif type == 0x3 then | |
item_length:set_text(goAwayErrors[payload_len]) | |
end | |
return 12 | |
end | |
function yamux_protocol.dissector(buf, pkt, tree) | |
local tvb_len = buf:len() | |
if tvb_len < 12 then | |
return 0 | |
end | |
local offset = pkt.desegment_offset or 0 | |
while offset < tvb_len do | |
local count = dissect(offset, buf, tree) | |
if count == 0 then | |
return offset | |
end | |
pkt.cols.protocol = yamux_protocol.name | |
if count < 0 then | |
pkt.desegment_len = -count | |
pkt.desegment_offset = offset | |
return count | |
end | |
offset = offset + count | |
end | |
return offset | |
end | |
local tcp_port_table = DissectorTable.get("tcp.port") | |
-- register your port here | |
tcp_port_table:add(4647, yamux_protocol) | |
tcp_port_table:add(7000, yamux_protocol) | |
tcp_port_table:add(8300, yamux_protocol) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment