First time here? Check out the FAQ!
THIS IS A TEST INSTANCE. Feel free to ask and answer questions, but take care to avoid triggering too many notifications.
0

LUA: tlv_tree:add "hex data sequence"

  • retag add tags

Hello,

One TLV has length 18... If I try to add to the display tree using:

f.tlvvalue_hex = ProtoField.uint32 ("myproto.tlvvalue_hex", "TLV Value", base.HEX)
tlv_tree:add (f.tlvvalue_hex, buffer(offset, tlvlen))

I get following [(Warning/Malformed) Trying to fetch an unsigned integer with length 18]

How can I just have an hex data sequence displayed instead ? Maybe leveraging on ByteArray ?

Thx!

sezb51's avatar
9
sezb51
asked 2021-07-29 21:21:03 +0000
edit flag offensive 0 remove flag close merge delete

Comments

this seems to do the trick...

  local bytearr = {}
  for i = 1, tlvlen do
    bytearr[i] = string.format("%X", buffer(offset + i, 1):uint())
  end
  local results = table.concat(bytearr)
  tlv_tree:add (f.tlvvalue_string, results)
  tlv_tree:append_text (": " .. results)

However selecting such information does not get reflected in the raw packet hightlighted... :(

sezb51's avatar sezb51 (2021-07-30 18:55:43 +0000) edit

What I'm really looking after is to implement a kinda of payload concept like this:

payload_example

There the amount of selected data is arbitrary yet it still get highlighted.

Any idea ?

sezb51's avatar sezb51 (2021-07-30 19:05:36 +0000) edit
add a comment see more comments

2 Answers

0

Final code. I'm happy with that :)

function hex2string(buffer, offset, len)
  local bytearr = {}
  for i = 1, len do
    bytearr[i] = string.format("%.2X", buffer(offset +i-1, 1):uint())
  end
  return table.concat(bytearr)
end

function hex2ascii(buffer, offset, len)
  local bytearr = {}
  for i = 1, len do
    bytearr[i] = string.char(buffer(offset +i-1, 1):uint())
  end
  return table.concat(bytearr)
end


    f.data = ProtoField.bytes ("S8HR_proto.data", "Data Hex")

    local tlv_data = tlv_tree:add (f.data, buffer(offset, tlvlen))
    local data_hex = hex2string(buffer, offset, tlvlen)
    local data_ascii = hex2ascii(buffer, offset, tlvlen)
    tlv_data:set_text("Data Hex: " .. data_hex .. ", Data Ascii: '".. data_ascii .. "'")

It basically set the tree with f.data (so it get highlighted when selected). It also read the sequence and store as hex-string and ascii-string. Finally it update the tree's text with that value.

Hope it could be of any help for other Lua's newbies.

sezb51's avatar
9
sezb51
answered 2021-07-31 13:06:45 +0000
edit flag offensive 0 remove flag delete link

Comments

add a comment see more comments
0

I think there's an even easier way to achieve the same results using something like this:

f.data = ProtoField.bytes("S8HR_proto.data", "Data Hex")

local tvbr = buffer(offset, tlvlen)
tlv_tree:add(f.data, tvbr):
    append_text(", Data ASCII: " .. Struct.fromhex(tostring(tvbr:bytes())))

Unfortunately, at least as far as I can tell, neither solution displays non-printable characters very well, and if there's a 0 in the bytestream, then the string will be truncated. So to deal with that, here's an alternate solution:

function bytes2ascii(bytearr)
    local ascii = {}

    for i = 1, bytearr:len() do
        local b = bytearr:get_index(i - 1)
        if b >= 32 and b <= 127 then
            ascii[i] = string.char(b)
        else
            ascii[i] = '.'
        end
    end
    return table.concat(ascii)
end

f.data = ProtoField.bytes("S8HR_proto.data", "Data Hex")

local tvbr = buffer(offset, tlvlen)
tlv_tree:add(f.data, tvbr):
    append_text(", Data ASCII: " .. bytes2ascii(tvbr:bytes()))

And if you want to be able to filter the field separately between binary and ASCII data, then you might consider adding separate fields, e.g.:

f.data = ProtoField.bytes("S8HR_proto.data", "Data Hex", base.NONE)
f.asciidata = ProtoField.string("S8HR_proto.asciidata", "Data ASCII", base.ASCII)

local tvbr = buffer(offset, tlvlen)
tlv_tree:add(f.data, tvbr)
tlv_tree:add(f.asciidata, tvbr, bytes2ascii(tvbr:bytes()))

You can also mark it as a Generated field too if you'd like:

tlv_tree:add(f.data, tvbr, bytes2ascii(tvbr:bytes())):set_generated()

There may be other solutions too, depending on what you're expecting for your output. For example, unless I'm misreading the documentation then at least in theory it should be possible to call tvbr:string(), as per the documentation in section 11.8.3.18. tvbrange:string([encoding]); however that didn't work in my testing, so I suspect there's a Wireshark bug here, either in the implementation or in the documentation, because it doesn't work as advertised, namely:

Returns
A string containing all bytes in the TvbRange including all zeroes (e.g., "a\000bc\000").

cmaynard's avatar
11.1k
cmaynard
answered 2021-08-01 23:54:37 +0000, updated 2021-08-01 23:56:31 +0000
edit flag offensive 0 remove flag delete link

Comments

add a comment see more comments

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account. This space is reserved only for answers. If you would like to engage in a discussion, please instead post a comment under the question or an answer that you would like to discuss.

Add Answer