I'm writting a lua script as wireshark(1.12.4) plugin to dissect my private protocols,I can get it work as normal dissector,which binding a certain port(such as 80) to DissectorTable "tcp.port".The pseudo-code as follows:
local my_pro = Proto("MyPro","My Protocol")
local my_pro_field_1 = ProtoField.uint16("MyPro.filed_1","Field 1",base.HEX)
local my_pro_field_2 = ProtoField.uint16("MyPro.filed_2","Field 2",base.HEX)
my_pro.fields = {my_pro_field_1,my_pro_field_2}
local data_dis = Dissector.get("data")
function my_pro.dissector(buf,pkt,root)
if (buf(0,2):uint() ~= 1 or buf(2,2):uint() ~= 1) then
data_dis:call(buf,pkt,root)
return false
end
pkt.cols.protocol = "My Protocol"
local tree = root:add(my_pro,buf(0,buf:len()))
tree:add_le(my_pro_field_1,buf(0,2))
tree:add_le(my_pro_field_2,buf(2,2))
return true
end
local tcp_encap_table = DissectorTable.get("tcp.port")
tcp_encap_table:add(80,my_pro)
The problem is:
What if My protocol is not running on a certain port,as I don't want to modify the port above every time,I actually want the dissector to be wise enough to dynamically identify some kind of pattern and do the right dissecting then.
I've searched out there's a so called "heuristic" dissector,I add codes below to test but I could't get it work.
local function my_heur_dissector(buf,pkt,root)
local ret = my_pro.dissector(buf,pkt,root)
if (not ret) then
return false
end
pkt.conversation = my_pro
return true
end
my_pro:register_heuristic("tcp",my_heur_dissector)
When I change the port,the packets're not parsed as my protocol,so I have to use "Decode as" menu.
So,how can I get the heuristic dissector work base on my code?Have I missed something?
BTW,the answer with code is appreciated.
Sadly, if you need a heuristic dissector (HD) it cannot be done in a plugin manner, and you need to write a new HD.
https://github.com/wireshark/wireshark/blob/master/doc/README.heuristic
(Yes, it has been over 2 years, but if some future-googler finds it...)
Related
Here is an example
local CustomLoad = function(l) loadstring(l) end
CustomLoad("print('hi')")
Please let me know, beacuse I got into this like a week ago, and I've been trying to make it, yet I coudln't. Can some of you tell me if it's even possible?
If you aren't trying to run "print('hi')" in that example, then I do believe you're missing a return statement.
local CustomLoad = function(l) return loadstring(l) end
But if you are, then:
local CustomLoad = function(l) return loadstring(l) end
CustomLoad("print('hi')")()
or
local CustomLoad = function(l) local f = loadstring(l); f() end
CustomLoad("print('hi')")
Because loadstring creates a function, which, when run, executes the code in the string.
Hope that helped!
I'm writing lua script to dissect coap protocol. However I cannnot get coap options(URI-Path) of 2nd or later if there are several same options.
do
local test_proto = Proto("test_proto", "Test Protocol")
local test_uripath = ProtoField.string("test.uripath", "Uri-Path")
test_proto.fields = {test_uripath}
local coap_uripath = Field.new("coap.opt.uri_path")
function test_proto.dissector(tvbuffer, pinfo, treeitem)
local subtree = treeitem:add(test_proto)
subtree:add(test_uripath, tostring(coap_uripath().value))
end
register_postdissector(test_proto)
end
Only first URI-Path is displayed at subtree even if coap URI-Path option has several values like the following.
Opt Name: #1: URI-Path: XXX
Opt Name: #2: URI-Path: YYY
I can only get XXX by using coap.opt.uri_path. How can I get 2nd or later same option fields?
If you're interested in all fields and not just the first one, then you'll need to process the entire table. For example:
do
local test_proto = Proto("test_proto", "Test Protocol")
local test_uripath = ProtoField.string("test.uripath", "Uri-Path")
test_proto.fields = {test_uripath}
local coap_uripath = Field.new("coap.opt.uri_path")
function test_proto.dissector(tvbuffer, pinfo, treeitem)
local subtree = treeitem:add(test_proto)
local coap_uripath_table = { coap_uripath() }
for i,uripath in ipairs(coap_uripath_table) do
subtree:add(test_uripath, tostring(uripath.value))
end
end
register_postdissector(test_proto)
end
See also:
https://osqa-ask.wireshark.org/questions/35682/lua-accessing-multiple-smb2msg_id-values
https://osqa-ask.wireshark.org/questions/1579/fetching-multiple-named-values-with-lua
I want to get the frame time (relative) of the first packet that is not communicating on sos and DIS ports and ip address is not the one mentioned in the if statement. But the packet should be utilizing port 24111. However, the code below is not working for this purpose. It works, until I add udp_port~=24111. After that it gives me no results, which means that it doesn't go inside that conditional statement. I have tried to write the condition in multiple ways, even separating it out into a new if statement but it doesn't work. What I am doing wrong here. Thanks for suggestions in advance.
Here is the piece of code that I have at the moment
local first_outpacket = 0
local flag = 0
function stats_first_packet()
local udp_port
local frame_time
local ip_addr
frame_time = time_relative_extractor()
udp_port = udp_port_extractor()
ip_addr = ip_addr_extractor()
if ( udp_port ) then
if (not (udp_port == 3000 or udp_port==3838 or flag==1 or ip_addr=="192.168.1.2" or udp_port~=24111)) then
first_outpacket = frame_time
print(frame_time)
flag = 1
else
-- print("tcp_src_port already recorded")
end
else
-- print("no tcp_src_port")
end
end
The problem apparently lies in the data type returned by the extractor() functions. In order to compare them with another value in the if statement they have to be converted into strings using tostring() function.
For example:
if (not (tostring(udp_port) == "3000" or tostring(udp_port)=="3838" or flag==1))
First of all, I'm new to Lua altogether, and this is my first attempt at writing a wireshark dissector.
My protocol is straightforward - a 2 byte length field, followed by a string of that length.
When I run the code through the Lua console, everything works as expected.
When the code is added to the Wireshark plugins directory, I get the error
Lua Error: [string "C:\Users...\AppData\Roaming\Wireshark..."]:15: calling 'add' on bad self (number expected, got string)
Line 15 corresponds is the t:add(f_text... line.
Can anyone explain the discrepancy between the execution methods?
do
local p_multi = Proto("aggregator","Aggregator");
local f_len = ProtoField.int16("aggregator.length","Length",base.DEC)
local f_text = ProtoField.string("aggregator.text","Text")
p_multi.fields = { f_len, f_text }
local data_dis = Dissector.get("data")
function p_multi.dissector(buf,pkt,root)
pkt.cols.protocol = "Aggregator"
local len = buf(0,2):int()
local t = root:add(p_multi,buf(0,len+2))
t:add(f_len,buf(0,2),"Length: " .. buf(0,2):int())
t:add(f_text,buf(2,len),"Text: " .. buf(2,len):string())
end
local tcp_encap_table = DissectorTable.get("tcp.port")
tcp_encap_table:add(4321,p_multi)
end
Your dissector code is very close to correct, but you're doing extra work that the interface won't accept. If you change your dissector function like so,
function p_multi.dissector(buf,pkt,root)
pkt.cols.protocol = "Aggregator"
local len = buf(0,2):int()
local t = root:add(p_multi,buf(0,len+2))
t:add(f_len,buf(0,2)) --let Wireshark do the hard work
t:add(f_text,buf(2,len)) --you've already defined their labels etc.
end
you'll get the desired behavior. The labels "Text" and "Length" are already defined for your fields, so there is no need to provide them again on lines 15 and 16.
I'm generating some (non-html) documentation for a Lua library that I developed. I will generate the documentation by hand, but I'd appreciate some kind of automation if possible (i.e. generating skeletons for each function so I can fill them in)
I'd like to know if there's a way for lua to know the names of the parameters that a function takes, from outside it.
For example, is there a way to do this in Lua?
function foo(x,y)
... -- any code here
end
print( something ... foo ... something)
-- expected output: "x", "y"
Thanks a lot.
ok,here is the core code:
function getArgs(fun)
local args = {}
local hook = debug.gethook()
local argHook = function( ... )
local info = debug.getinfo(3)
if 'pcall' ~= info.name then return end
for i = 1, math.huge do
local name, value = debug.getlocal(2, i)
if '(*temporary)' == name then
debug.sethook(hook)
error('')
return
end
table.insert(args,name)
end
end
debug.sethook(argHook, "c")
pcall(fun)
return args
end
and you can use like this:
print(getArgs(fun))
Try my bytecode inspector library. In Lua 5.2 you'll be able to use debug.getlocal.
Take a look at debug.getinfo, but you probably need a parser for this task. I don't know of any way to fetch the parameters of a function from within Lua without actually running the function and inspecting its environment table (see debug.debug and debug.getlocal).
function GetArgs(func)
local args = {}
for i = 1, debug.getinfo(func).nparams, 1 do
table.insert(args, debug.getlocal(func, i));
end
return args;
end
function a(bc, de, fg)
end
for k, v in pairs(GetArgs(a)) do
print(k, v)
end
will print
1 bc
2 de
3 fg
Basically we use debug.getinfo to retrieve the nparams attribute (which gives us the information of how many parameters the function takes) and debug.getlocal to access the name of the parameters.
Tested and working with Lua 5.4
Take a look at the luadoc utility. It is sort of like Doxygen, but for Lua. It is intended to allow the documentation to be written in-line with the source code, but it could certainly be used to produce a template of the documentation structure to be fleshed out separately. Of course, the template mechanism will leave you with a maintenance issue down the road...