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.
Related
Here I have a loadstring but attacker can just hook it and steal it's content like bellow. I want to make a anti hook so that it can be prevented.
-- Save copies of orignal functions
local o_load = _G["load"]
local o_loadstring = _G["loadstring"]
local o_unpack = _G["unpack"]
local o_pairs = _G["pairs"]
local o_writefile = _G["writefile"]
local o_print = _G["print"]
local o_tostring = _G["tostring"]
-- Dynamic function names
local load_name = tostring(_G["load"])
local loadstring_name = tostring(_G["loadstring"])
local tostring_name = tostring(_G["tostring"])
-- For multiple instances of loadstring or load being used
local files_loadstring = 1
local files_load = 1
-- Hide function names
_G["tostring"] = function(...)
local args = {...}
local arg = o_unpack(args)
if arg == _G["tostring"] then
return tostring_name
end
if arg == _G["loadstring"] then
return loadstring_name
end
if arg == _G["load"] then
return load_name
end
local ret = { o_tostring(o_unpack(args)) }
local value = o_unpack(ret)
return value
end
-- Hook loadstring
_G["loadstring"] = function(...)
local args = {...}
o_print("loadstring called")
local str = ""
for k, v in o_pairs(args) do
str = str .. o_tostring(v) .. " "
end
o_writefile("hook_loadstring"..o_tostring(files_loadstring)..".lua", str)
o_print("file written to hook_loadstring"..o_tostring(files_loadstring)..".lua")
files_loadstring = files_loadstring +1
local ret = { o_loadstring(o_unpack(args)) }
str = ""
for k, v in o_pairs(ret) do
str = str .. o_tostring(v) .. " "
end
return o_unpack(ret)
end
-- Hook load
_G["load"] = function(...)
local args = {...}
o_print("load called")
local str = ""
for k, v in o_pairs(args) do
str = str .. o_tostring(v) .. " "
end
o_writefile("hook_load"..o_tostring(files_load)..".lua", str)
o_print("file written to hook_load"..o_tostring(files_load)..".lua")
files_load = files_load +1
local ret = { o_load(o_unpack(args)) }
str = ""
for k, v in o_pairs(ret) do
str = str .. o_tostring(v) .. " "
end
return o_unpack(ret)
end
-- bellow is the loadstring function with a lua and all it's content is getting hooked and writen in a file
loadstring("local a = 1;")()`
I tried using tostring(loadstring) to compare the function name to check if it's real or fake but attacker can just hook tostring as well and give original function name so my anti hook won't work at all. Also I can't do writefile = nil or print = nil so attacker can't print or write the file since he saved a copy of these functions on top of the file so his code will work always. How can I prevent my loadstring from getting hooked like this. Please help.
I just want my content inside loadstring not to be stolen.
loadstring being hooked implies that the attacker's code runs before your code and in the same environment. This implies that all functions of the global environment may be hooked - from loadstring over tostring and including the debug library. Thus, the only thing you may rely on (and even that is uncertain, depending on which software is interpreting your Lua) are "hard-wired" (e.g. syntactical) Lua language features. You can take a look at the complete syntax of Lua. Notice that all these are basic constructs that won't help you at all; everything advanced in Lua uses function calls and the global environment, which may be hooked.
Whatever loads these scripts would need to be patched to either (1) load everything in a separate, clean environment (2) protect the global environment or at least a few selected functions, but even then the "loader" could be tampered with to remove these "protections".
In conclusion, you can't reliably prevent or detect loadstring being hooked. If you are providing someone with code for them to run, that code inevitably has to run at some point, and at that point they will be able to "steal" it. The "best" you can do is obfuscate your code so that there is little benefit from stealing it.
Bottom line: As long as your software runs "on-premise" (on their machines) rather than "as a service" (on your machines), they will always be able to steal and analyze your code; all you can do is make it harder e.g. through obfuscation or checks (which may be circumvented however).
local file = 'data.txt'
local lines = lines_from(file)
global data = {} -- this line is giving the error "lua: day8.lua:20: '=' expected near 'data'"
for key, value in pairs(lines) do
local row = {}
for i=1, #value do
local char = value:sub(i,i)
row[i] = char
end
data[key] = row
end
As you can see from the code above, my code is throwing an error on the line where the variable data is initialised. This code was working earlier when I tested it, then I added more code below what is visible and it broke this line somehow.
I don't think its the code below that broke this line as otherwise why would it be showing there?
This is also my first ever code with lua so I have no experience with this language.
What could be wrong in this code that could cause this error
Global variables don't need to be declared explicitly like local ones do. The interpreter is erroring because you are prefixing global to your variable, which isn't a recognized keyword
Try the following, without the global:
data = {}
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...)
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))
i try to write dissector on lua for wireshark. i need to parse header field version = 4 bytes (0x00000000)
my code:
do
local asc_sccp =Proto("asc_sccp", "ASC Skinny Client Control Protocol")
local f =asc_sccp.fields
f.length = ProtoField.bytes("asc_sccp.length", "length")
f.version =ProtoField.uint8("asc_sccp.version", "version", base.HEX, 0xC)
function asc_sccp.init()
end
function asc_sccp.dissector(buffer,pinfo,tree)
local subtree = tree:add (asc_sccp, buffer())
local offset = 0
pinfo.cols.protocol = asc_sccp.name
local length = buffer (offset, 4)
subtree:add (f.length, length)
subtree:append_text ("Data length: " .. length)
offset = offset + 4
local version = buffer (offset, 4)
subtree:add (f.version, version)
subtree:append_text (" Version: " .. version)
end
local tcp_table = DissectorTable.get("tcp.port")
tcp_table:add(2000, asc_sccp)
end
Why i am getting error 'attempt to index global 'base' (a nil value)' ?
Could you please help, i looked through a lot of dissector example but i can't find solution
This may be happening because init.lua isn't installed. This can happen in Redhat-based distributions (Fedora, Centos, RHEL etc.) if the development packages aren't installed. See answer here: https://stackoverflow.com/a/40489742/409638
In this line of code:
f.version =ProtoField.uint8("asc_sccp.version", "version", base.HEX, 0xC)
you are accessing the variable 'base'. Specifically, you are indexing it by telling Lua it is a table containing the key "HEX" and trying to retrieve the value at that key. Unless you define the variable 'base' somewhere to be a table (or userdata) and add a value at the key "HEX", lua will complain that you are attempting to index a global variable called 'base', when it is actually nil (i.e. non-existent).