I'm having trouble dissecting 64-bit hex and from what I'm reading the way to do this is using ProtoField.uint64.
I can see this decoding nicely in Wireshark without protofield, though it doesnt work for uint64.
-- declare our protocol
trivial_proto = Proto("triviala","trivial Protocol")
-- create a function to dissect it
function trivial_proto.dissector(buffer,pinfo,tree)
pinfo.cols.protocol = "TRIVIA"
local subtree = tree:add(trivial_proto,buffer(),"Trivia Protocol Data")
subtree:add(buffer(0,2),"Seq number: " .. buffer(0,2):uint())
subtree:add(buffer(2,4),"Seq number: " .. buffer(2,4):uint())
subtree:add(buffer(6,2),"no messages: " .. buffer(6,2):uint())
--Doesnt work
--subtree:add(buffer(8,8),"no messages: " .. buffer(8,8):uint64())
end
-- load the udp.port table
udp_table = DissectorTable.get("udp.port")
-- register our protocol to handle udp port
udp_table:add(20004,trivial_proto)
udp_table:add(20006,trivial_proto)
udp_table:add(20021,trivial_proto)
Wireshark dissecting msgs
When I try exactly the same thing, with the same pcap using ProtoField, I can see my message type "TRIVIA" in wireshark but nothing decoded in its subtree
-- declare our protocol
trivial_proto = Proto("triviala","Trivia Protocol")
local F = trivial_proto.fields
F.f_1 = ProtoField.uint8("triviala.sessnum","Session Number",base.HEX)
F.f_2 = ProtoField.uint32("triviala.seqnum","Sequence Number",base.HEX)
F.f_3 = ProtoField.uint8("triviala.nomsgs","Number Mesages",base.HEX)
F.f_4 = ProtoField.uint64("triviala.time","Date Time",base.HEX)
-- create a function to dissect it
function trivial_proto.dissector(buffer,pinfo,tree)
pinfo.cols.protocol = "TRIVIA"
local subtree = tree:add(trivial_proto,buffer(),"Trivia Protocol Data")
subtree:add(F.f_1, buffer(0,2))
subtree:add(F.f_2, buffer(2,4))
subtree:add(F.f_3, buffer(6,2))
--subtree:add(F.f_4, buffer(8,8))
end
-- load the udp.port table
udp_table = DissectorTable.get("udp.port")
-- register our protocol to handle udp port
udp_table:add(20004,trivial_proto)
udp_table:add(20006,trivial_proto)
udp_table:add(20021,trivial_proto)
Wireshark not dissecting msgs
Please help !
You need to assign trivial_proto.fields to F, not the other way around.
If you refer to the fpm.lua script that is available on the Wireshark Lua/Examples wiki page, you will see that you need to do something like:
local F =
{
f_1 = ProtoField.uint8("triviala.sessnum","Session Number",base.HEX)
f_2 = ProtoField.uint32("triviala.seqnum","Sequence Number",base.HEX)
f_3 = ProtoField.uint8("triviala.nomsgs","Number Mesages",base.HEX)
f_4 = ProtoField.uint64("triviala.time","Date Time",base.HEX)
}
trivial_proto.fields = F
...
subtree:add(F.f_1, buffer(0,2))
subtree:add(F.f_2, buffer(2,4))
subtree:add(F.f_3, buffer(6,2))
Related
How can I make a Lua dissector/post-dissector/chained dissector that would get attached under the PROFINET IO Cyclic Service Data Unit and for example extract only the last 3 bits of the 5th byte, highlighted in the image below?
All the examples of Lua dissectors I could find are attached to some ports. Profinet does not use TCP/IP layer so there are no ports to attach to.
You should be able to achieve what you want using the following example as a rough guide, where I illustrate both how to add the field to the tree as well as to grab the data and do something with it (e.g., append the relevant data to the Info column):
local pn_io_post = Proto("PNIOPost", "PNIO Postdissector")
local pf = {
afield = ProtoField.uint8("pn_io_post.afield", "A Field", base.DEC, nil, 0x03, "A Field Description")
}
pn_io_post.fields = pf
local pn_io_data = Field.new("pn_io")
function pn_io_post.dissector(tvbuf, pinfo, tree)
local pn_io_post_tree
local pn_io_data_ex = pn_io_data()
if pn_io_data_ex ~= nil then
local pn_io_data_tvb = pn_io_data_ex.range()
local afield
pn_io_post_tree = tree:add(pn_io_post, pn_io_data_tvb(0, -1))
pn_io_post_tree:add(pf.afield, pn_io_data_tvb(4, 1))
afield = pn_io_data_tvb(4, 1):uint()
afield = bit.band(0x03, afield)
pinfo.cols.info:append(" [A Field = " .. afield .. "]")
end
end
register_postdissector(pn_io_post)
I'm trying to execute a custom function call dynamically defined using loadstring inside a Wireshark dissector.
When using this method from inside another similar Lua script, it works fine:
function ftest(s)
return s..s
end
k="knock "
fcallstr="rs = ftest(k)"
loadstring(fcallstr)()
print("now rs = " .. rs)
--now rs = knock knock
But if I try to do the same based on the dissector example (https://wiki.wireshark.org/Lua/Dissectors), I get an error:
function mycustomfnc(buffer, subtree)
print(os.time() .. " " .. "FUNCTION REACHED!")
subtree:add(buffer(4,2),"Plus 5th and 6th bytes!: " .. buffer(4,2):uint())
end
-- declare our protocol
trivial_proto = Proto("trivial","Trivial Protocol")
-- create a function to dissect it
function trivial_proto.dissector(buffer,pinfo,tree)
pinfo.cols.protocol = "TRIVIAL"
local subtree = tree:add(trivial_proto,buffer(),"Trivial Protocol Data")
subtree:add(buffer(0,2),"The first two bytes: " .. buffer(0,2):uint())
subtree = subtree:add(buffer(2,2),"The next two bytes")
subtree:add(buffer(2,1),"The 3rd byte: " .. buffer(2,1):uint())
subtree:add(buffer(3,1),"The 4th byte: " .. buffer(3,1):uint())
-- this works OK
--mycustomfnc(buffer, subtree)
-- this fails:
srcfncall="mycustomfnc(buffer, subtree)"
loadstring(srcfncall)()
-- result:
--Lua Error: [string "mycustomfnc(buffer, subtree)"]:1: attempt to call global 'mycustomfnc' (a nil value)
end
-- load the udp.port table
udp_table = DissectorTable.get("udp.port")
-- register our protocol to handle udp port xxxx
udp_table:add(5001,trivial_proto)
What I'm missing here? Thanks in advance.
I have packet with trailer data after the packet as in ixia timestamp trailer. I am trying to write a dissector for Wireshark that is quite the same as ixia-packet_trailer plugin. https://raw.githubusercontent.com/boundary/wireshark/master/epan/dissectors/packet-ixiatrailer.c
But i wanted to write in Lua, so it is easiest to change.
I did the lua as heuristic with the function is_my_trailer (as proposed in Wireshark Lua dissector plugin table error), it now stop to show the trailer in ethernet tree so i believe it recognize the pattern 0xae12, but it doesn't show my "my trailer" tree
-- declare our protocol
local my_trailer_proto = Proto("my_trailer","my Trailer")
-- Header fields
local timestamp = ProtoField.uint64 ("my_trailer_proto.timestamp", "timestamp", base.HEX)
local proto_flag = ProtoField.uint8 ("my_trailer_proto.proto_flag", "protoFlag", base.HEX)
local msg_id = ProtoField.uint16("my_trailer_proto.msg_id" , "msdId" , base.HEX)
my_trailer_proto.fields = { timestamp, proto_flag, msg_id }
-- does this packet contains a trailer
local function is_my_trailer(buffer,pinfo,tree)
local length = buffer:len()
if length < 12 then return 1 end
local type = buffer(length-12, 2):uint()
if type == 0xae12 then return true end
return false
end
function my_trailer_proto.dissector(buffer, pinfo, tree)
length = buffer:len()
if length == 0 then return end
local subtree = tree:add(my_trailer_proto, buffer(), "my trailer")
-- Header
subtree:add(timestamp, buffer(length-10,8))
subtree:add(proto_flag, buffer(length-3,1))
subtree:add(msg_id, buffer(length-2,2))
pinfo.cols.protocol = my_trailer_proto.name
pinfo.cols.protocol:set("proto_flag")
pinfo.cols.info:set("proto_flag: " .. proto_flag)
end
my_trailer_proto:register_heuristic("eth.trailer", is_my_trailer)
Here is a pcap file example with the trailer https://transfernow.net/87kwt2k0dne7
You forgot a critical line of code:
if type == 0xae12 then return true end
return false
Should be:
if type == 0xae12 then
my_trailer_proto.dissector(buffer, pinfo, tree)
return true
end
return false
You also have another bug. This line is an error:
pinfo.cols.info:set("proto_flag: " .. proto_flag)
It should be something like:
pinfo.cols.info:set("proto_flag: " .. buffer(length-3,1):uint())
Platform: (where Lua and LuaSocket are ported)
An embedded system using ARM 7 development board running 3rd party RTOS with TCP/IP stack.
What works:
Using Lua standard library such as "io" calls, print, assert, etc
sending UDP packets by using the udp = assert(socket.udp) method, assert(udp:send(something))
Problem:
When executing an example smtp lua script:
local smtp = require("socket.smtp")
from = "myEmail"
rcpt = {"<someOne's Email>"}
mesgt = { heasers = {someHeader}, body = "Hello World" }
r, e = smtp.send {
from = from,
rcpt = rcpt,
source = smtp.message(mesgt),
server = "someServer",
port = 25,
}
-- an error returns after execution:
-- lua\socket\smtp.lua:115: attempt to call field 'try' (a nil value)
-- Corresponding code in smtp.lua around line 115:
function open(server, port, create)
local tp = socket.try(tp.connect(server or SERVER, port or PORT,
TIMEOUT, create))
local s = base.setmetatable({tp = tp}, metat)
-- make sure tp is closed if we get an exception
s.try = socket.newtry(function()
s:close()
end)
return s
end
// Where try = newtry() in socket.lua and the corresponding C code is the same
// from the one provided with the library for UNIX:
static int global_newtry(lua_State *L) {
lua_settop(L, 1);
if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing);
lua_pushcclosure(L, finalize, 1);
return 1;
}
Well, since the error says that "try is nil", then my best guess is that the C lib is not correctly, or not completely, linked to your Lua. This could be the result of a faulty installation, a missing lib, or something of that sort.
I would like to do some analysis on top of my custom protocol that is dissected via my lua dissector. Therefore I tried to do this
myproto_proto = Proto("myproto", "Myproto Protocol")
m_dest = ProtoField.uint16("myproto.dest", "Destination", base.HEX)
m_src = ProtoField.uint16("myproto.src", "Source", base.HEX)
myproto_proto.fields = { sm_dest, sm_src }
dofile(MYPROTO_PROTO_PATH.."parser.lua")
function myproto_proto.dissector(buffer, pinfo, tree)
pinfo.cols.protocol = "MYPROTO"
local subtree = tree:add(myproto_proto, buffer(), "Myproto Protocol Data")
parse_msg(buffer, pinfo, subtree) -- does the actual parsing and sets the fields
end
udp_table = DissectorTable.get("udp.port")
udp_table:add(9000,myproto_proto)
-- LISTENER / TAP
f_test = Field.new("myproto.dest") -- fails because "field does not exist"
local function my_tap()
local window = TextWindow.new("Myproto Tap")
local tap = Listener.new(nil, "myproto")
local counter = 0
function remove()
tap:remove()
end
window:set_atclose(remove)
function tap.packet(pinfo, buffer)
counter = counter + 1
end
function tap.draw(t)
window:append("Counter: \t" .. counter .. "\n")
end
function tap.reset()
window:clear()
counter = 0
end
retap_packets()
end
register_menu("My Tap", my_tap, MENU_TOOLS_UNSORTED)
My problem is, I'm unable to access the dissected data with a field extractor. So how else could I get the dissected data in my lua tap?
Thanks in advance.
It's a known problem that custom Lua Field objects aren't usable in OSX (it apparently works in Windows XP but not Windows 7).
There are a few ways to pass data from your dissector to your tap.
Option 1: Use a shared Lua table
Create a global dictionary that is keyed by the packet number (from pinfo.number, which is visible to both dissector and tap).
-- we omit the 'local' keyword to make `dict` a global variable
dict = {}
In your dissector, add the packet data to the dictionary:
dict[pinfo.number] = { dest = m_dest, src = m_src }
In your tap, you can access the data by a simple lookup.
print('dest', dict[pinfo.number].dest )
XXX: Requires a global; Duplicates storage for a variable that is already held in the protocol tree (and should be accessible from the tap).
Option 2: Use pinfo.private
This was added in the dev build (1.7.0). It's similar to the solution above. pinfo.private is a PrivateTable, which is a hash table that stores only strings.
In your dissector, add your data to the packet's private table:
pinfo.private["src"] = tostring(m_src)
pinfo.private["dest"] = tostring(m_dest)
In your tap, access the data from the pinfo object:
print('dest', pinfo.private["dest"] )
XXX: Can only store string values
Option 3: Reparse the buffer
In your tap, call your parser (i.e., from parser.lua) to reparse the data in buffer, which is passed to the tap.
XXX: Duplicates work already done by dissector (can double processing time for X-large capture files)