This is a static archive of our old Q&A Site. Please post any new questions and answers at ask.wireshark.org.

Fetch Unsigned Int 8 Bytes + show ASCII value

0

Hello,

First of all I would like to say that this is my first dissector that I've ever done and that I am completely new to Lua. So, sorry if the question is silly or for my way of saying what I need.

I want to access some data in the package for the dissector tree. The problem is that the data I am trying to get is 8 byte long, but, it goes from lets say, byte number 0 to byte number 9, but the first 4 bits of the first byte and the last 4 bits of the last byte are from other fields...

alt text

Any suggestion is welcome, Thanks in advance.

Some parts of my code, I know they are not right (I wouldnt be here if they were :P):

Definition of the field

local blas_ id  =ProtoField.new   ("Blas ID", "myudp.blas_id", ftypes.UINT64, nil, base.DEC, 0x0FFFFFFFFFFFFFFFF0)

tree:add(blas_id, tvbuf:range(0,9))

EDIT 1:

So now the blas_id field is defined on the next way:

local blas_id = ProtoField.uint64 ("myProto.blas_id",  "Blas ID", base.HEX)
local blas_id_long= tvbuf:range(0,9)
tree:add(blas_id, blas_id_long:bitfield(4,64))

Seems like this field is going to be the pain in the …. from the project…

What I’ve got so far until now is this:

Blas ID: 0x0000000000313030

I would like to visualize it like this, whith the (ASCII encoded):

Blas ID: 0x0000000000313030 (100)

I don’t have very clear how to access the data in the protofields to treat it and then show it how I want.

Any advice is welcome, thank you

asked 01 Aug ‘17, 00:25

iparra's gravatar image

iparra
6114
accept rate: 0%

edited 08 Aug ‘17, 04:05

wait a second… are there 8 bytes binary encoded or ASCII encoded?

Blas ID: 0x0000000000313030 (100) suggests a weird ASCII encoding (weird because the leading characters before the first significant digit are NUL), whereas the uint64 value of Blas ID: 0x0000000000313030 would be 3223600.

So what does the protocol specification say about this?

(08 Aug ‘17, 02:39) sindy

I selected the UINT64 format because it was the only way I managed to see the data on the packet details panel. But, what I really need is the ASCII code of the HEX value. I’ve tried to define it as a string, but failed to visualize it. Any suggestion?

(08 Aug ‘17, 02:47) iparra
1

There are two issues to deal with. One is the bit position of your 64 bits regardless their interpretation and the other one is the encoding.

So what I would do would be to create a dynamic tvb of 8 bytes, copy the interesting part of the original TVB to it, shifting it by 4 bits, and add a plain uint64 or string field to the dissection tree, referring to that created TVB rather than the original data. If you choose the field type to be string with base.ASCII, causing character 4 to be displayed for byte value of 0x34, and you get nothing or nonsense displayed as the string value, the next step would be to either replace 0x00 (NUL) by 0x20 (SP) while copying data from source tvb to the auxiliary tvb or to identify the position of the first digit and set the starting position and size of the field accordingly when adding it to the tree.

The drawback of this workaround is that if you click the item in the dissection tree, the corresponding bytes will not be highlighted in the original packet bytes pane but in the tab representing the auxiliary tvb.

The suggestion below is a blind shot in the part of converting the original tvb into the hexdigit string you need to create the auxiliary tvb, so you’ll likely have to fight the battle with type mismatch yourself.

local UselessString,MyString = tvb:range(start_position,9):bytes():string():match(".(.*).")
local MyArray = ByteArray.new(MyString)
local MyTvb = ByteArray.tvb(MyArray,"Blas ID")
tree:add(MyBlasID,MyTvb:range(0))

It is up to you whether you define MyBlasID as ProtoField.uint64 or as ProtoField.string.

(08 Aug ‘17, 03:36) sindy

I think I might be doing something wrong… Or this what you expected when you said “fight the battle with type mismatch yourself”. When I copy the code you wrote I get the following error: No such ‘string’ method/field for object type ‘ByteArray’

Thank you for your answer, I really appreciate your help.

(08 Aug ‘17, 04:13) iparra

It’s part of the battle, I’ve sincerely warned you it was a blind shot. On the first line, the proper function is tostring() instead of just string().

(08 Aug ‘17, 04:23) sindy

See my question in Stack Overflow, where I got some very interesting answers for the problem that I was facing. Hope this helps someone else

(11 Aug ‘17, 06:42) iparra
showing 5 of 6 show 1 more comments


One Answer:

0

I managed to solve the problem I was having. I created a TVB for the 9 bytes range and then I added to the tree the bitfield for 8 bytes with an offset of 4 bits

local blas_id_long= tvbuf:range(0,9)
tree:add(blas_id, blas_id_long:bitfield(4,64))

answered 01 Aug '17, 06:17

iparra's gravatar image

iparra
6114
accept rate: 0%

1

To solve or to work around? I would expect that you want that field to be applicable for display filtering (like myudp.blas_id == 12345678), and I think this expression won't work with a bitfield?

(01 Aug '17, 08:39) sindy

You are absolutelly right! I want to be able to filter the packages. So, do you have any suggestion to achieve what you suggested?

(01 Aug '17, 22:49) iparra

do you have any suggestion

Unfortunately not, otherwise I would have provided it already. But this is a Q&A site so I wanted to make sure that the answer is complete.

I'm not a Wireshark developer so I am unable to look into the code to confirm whether what you ask for is possible in a direct way. I only suspect that the source area for uint64 cannot be larger than 8 bytes.

I can suggest you a more complex workaround which would allow to treat the protocol field as uint64 but the cost would be a need to create an auxiliary tvb, which is so ugly that I wanted to allow some time for a better answer from Wireshark developers before publishing it. If you are nevertheless interested, let me convert the rough idea into a tested code before publishing it.

(02 Aug '17, 00:20) sindy

Okay, it's fine! I really appreciate your effort and your answers. I think that for now the work around that I found should be enough for me.

You are right on your suspicion, it doesn't allow to "trying to fetch an unsigned integer with length 9" , I got that error some times before coming here looking for an answer.

This question is quite similar to what I am trying to get, but for now I will leave it just like this.

(02 Aug '17, 00:52) iparra

sindy, check my edit please. Thank you

(08 Aug '17, 00:32) iparra

So to sort things out:

  1. an actual usigned 64-bit integer value can be extracted from the tvb even if it is not byte-aligned. To do so, it is necessary to use tvb:range(pos,9):bitfield(4,64) instead of just tvb:range(pos,9) as the tvbrange parameter of treeitem:add or tvbrange:uint64(). However, if done this way, the source area of the packet bytes pane is not highlighted when the corresponding tree item is selected. To fix this, it is necessary to use treeitem:set_len(9) (as @cmaynard did in his answer on Stack Overflow)

  2. it is possible to use own code to calculate a value of a field from whatever exotic encoding is used in he protocol, and then add to the tree a protocol field whose type doesn't match by number of bytes, nevertheless indicating those bytes as a source of the field, and set the calculated value.

In this particular case, where the protocol encodes the numeric ID as a right-aligned string of ASCII-encoded digits, left-stuffed with ASCII NUL (0x0), so a 32-bit unsigned integer is sufficient to accomodate the result, the corresponding code would be:

...
local blas_id = ProtoField.uint32 ("myProto.blas_id", "Blas ID", base.DEC)
...
local my_string = tostring(tvbuf:range(0,9)):match(".(.*)."):gsub("00","30",7):gsub("3(%d)","%1",8)
local my_number = tonumber(my_string)
myProto_tree:add(blas_id,buf(0,9),my_number)

The first line of the extraction code could be written in easier to understand individual steps:

step1 = tvbuf:range(0,9)            -- extract the bytes
step2 = tostring(my_tvb_range)      -- step2 now contains each byte as two hex digits 0-F
step3 = step2:match(".(.*).")       -- step3 now contains the interesting part, without the first and last nibble, as hex digits
step4 = step3:gsub("00","30",8)     -- hex digit pairs 00 are replaced by hex digit pairs 30
step5 = step4:gsub("3(%d)","%1",8)  -- each hex digit pair (30..39) is replaced by the character representing the digit itself

This way, the value of the field, which can be used in display filter, is the final numeric one. So if the source 9 bytes would be e.g. f0000003132333435f, the corresponding display filter would be myProto.blas_id == 12345.

The code does not handle exceptions. If any other ASCII characters than NUL and digits 0-9 occur in the source tvb range, the resulting field value becomes incorrect.

(11 Aug '17, 10:46) sindy
showing 5 of 6 show 1 more comments