2022-01-16 18:55:52 +00:00
|
|
|
|
[#wsluarm]
|
2014-11-02 21:20:08 +00:00
|
|
|
|
|
|
|
|
|
// Attributes
|
2023-02-11 00:11:20 +00:00
|
|
|
|
:build_dir: ..
|
2014-11-02 21:20:08 +00:00
|
|
|
|
|
|
|
|
|
== Lua Support in Wireshark
|
|
|
|
|
|
2022-01-16 18:55:52 +00:00
|
|
|
|
[#wsluarm_intro]
|
2014-11-02 21:20:08 +00:00
|
|
|
|
|
|
|
|
|
=== Introduction
|
|
|
|
|
|
2019-05-16 02:21:30 +00:00
|
|
|
|
Lua is a powerful light-weight programming language designed for extending
|
|
|
|
|
applications. Wireshark contains an embedded Lua 5.2 interpreter which
|
|
|
|
|
can be used to write dissectors, taps, and capture file readers
|
2014-11-02 21:20:08 +00:00
|
|
|
|
and writers.
|
|
|
|
|
|
2019-05-16 02:21:30 +00:00
|
|
|
|
Wireshark’s Lua interpreter starts by loading a file named `init.lua` from
|
2019-06-14 23:03:17 +00:00
|
|
|
|
Wireshark's link:{wireshark-users-guide-url}ChAppFilesConfigurationSection.html[_global configuration directory_].
|
2019-05-16 02:21:30 +00:00
|
|
|
|
The _global configuration directory_'s `init.lua` controls whether or not Lua
|
|
|
|
|
scripts are enabled via the
|
|
|
|
|
_$$enable_lua$$_ variable. Lua scripts are enabled by
|
|
|
|
|
default. To disable Lua scripts, set the _$$enable_lua$$_ variable to _false_.
|
|
|
|
|
Wireshark 2.6 and earlier enabled or disabled Lua scripts using
|
|
|
|
|
the variable _$$disable_lua$$_ (deprecated). If both _$$enable_lua$$_ and
|
|
|
|
|
_$$disable_lua$$_ are present, _$$disable_lua$$_ is ignored.
|
|
|
|
|
|
|
|
|
|
If Lua is enabled, Wireshark will try to load a file named `init.lua`
|
|
|
|
|
from the user’s
|
2019-06-14 23:03:17 +00:00
|
|
|
|
link:{wireshark-users-guide-url}ChAppFilesConfigurationSection.html[_personal configuration directory_]
|
2019-05-16 02:21:30 +00:00
|
|
|
|
and all files ending with _.lua_ in the global and the personal
|
2019-06-14 23:03:17 +00:00
|
|
|
|
link:{wireshark-users-guide-url}ChPluginFolders.html[_plugins directory_].
|
2019-05-16 02:21:30 +00:00
|
|
|
|
|
|
|
|
|
The command line option _$$-X lua_script:$$++file.lua++_ can also be used to load
|
|
|
|
|
specific Lua scripts.
|
|
|
|
|
|
|
|
|
|
The Lua code is executed after all protocol dissectors are
|
2014-11-02 21:20:08 +00:00
|
|
|
|
initialized and before reading any file.
|
|
|
|
|
|
2018-12-28 11:49:33 +00:00
|
|
|
|
Wireshark for Windows uses a modified Lua runtime
|
2019-05-16 02:21:30 +00:00
|
|
|
|
(link:https://github.com/Lekensteyn/lua-unicode[lua-unicode]) to
|
2018-12-28 11:49:33 +00:00
|
|
|
|
support Unicode (UTF-8) filesystem paths. This brings consistency with other
|
|
|
|
|
platforms (for example, Linux and macOS).
|
|
|
|
|
|
2022-01-16 18:55:52 +00:00
|
|
|
|
[#wslua_menu_example]
|
2019-05-16 02:21:30 +00:00
|
|
|
|
|
|
|
|
|
=== Example: Creating a Menu with Lua
|
|
|
|
|
|
|
|
|
|
The code below adds a menu "Lua Dialog Test" under the Tools menu.
|
|
|
|
|
When selected, it opens a dialog prompting the user for input
|
|
|
|
|
and then opens a text window with the output.
|
|
|
|
|
|
|
|
|
|
[source,lua]
|
|
|
|
|
----
|
|
|
|
|
|
2019-07-02 21:18:52 +00:00
|
|
|
|
-- Define the menu entry's callback
|
2019-05-16 02:21:30 +00:00
|
|
|
|
local function dialog_menu()
|
|
|
|
|
local function dialog_func(person,eyes,hair)
|
|
|
|
|
local window = TextWindow.new("Person Info");
|
|
|
|
|
local message = string.format("Person %s with %s eyes and %s hair.", person, eyes, hair);
|
|
|
|
|
window:set(message);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
new_dialog("Dialog Test",dialog_func,"A Person","Eyes","Hair")
|
|
|
|
|
end
|
|
|
|
|
|
2019-07-02 21:18:52 +00:00
|
|
|
|
-- Create the menu entry
|
2019-05-16 02:21:30 +00:00
|
|
|
|
register_menu("Lua Dialog Test",dialog_menu,MENU_TOOLS_UNSORTED)
|
2019-07-02 21:18:52 +00:00
|
|
|
|
|
|
|
|
|
-- Notify the user that the menu was created
|
|
|
|
|
if gui_enabled() then
|
|
|
|
|
local splash = TextWindow.new("Hello!");
|
|
|
|
|
splash:set("Wireshark has been enhanced with a useless feature.\n")
|
|
|
|
|
splash:append("Go to 'Tools->Lua Dialog Test' and check it out!")
|
|
|
|
|
end
|
|
|
|
|
|
2019-05-16 02:21:30 +00:00
|
|
|
|
----
|
|
|
|
|
|
2022-01-16 18:55:52 +00:00
|
|
|
|
[#wslua_dissector_example]
|
2014-11-02 21:20:08 +00:00
|
|
|
|
|
2019-05-16 02:21:30 +00:00
|
|
|
|
=== Example: Dissector written in Lua
|
2014-11-02 21:20:08 +00:00
|
|
|
|
|
|
|
|
|
[source,lua]
|
|
|
|
|
----
|
2016-10-17 00:08:44 +00:00
|
|
|
|
local p_multi = Proto("multi", "MultiProto");
|
2014-11-02 21:20:08 +00:00
|
|
|
|
|
|
|
|
|
local vs_protos = {
|
|
|
|
|
[2] = "mtp2",
|
|
|
|
|
[3] = "mtp3",
|
|
|
|
|
[4] = "alcap",
|
|
|
|
|
[5] = "h248",
|
|
|
|
|
[6] = "ranap",
|
|
|
|
|
[7] = "rnsap",
|
|
|
|
|
[8] = "nbap"
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-17 00:08:44 +00:00
|
|
|
|
local f_proto = ProtoField.uint8("multi.protocol", "Protocol", base.DEC, vs_protos)
|
|
|
|
|
local f_dir = ProtoField.uint8("multi.direction", "Direction", base.DEC, { [1] = "incoming", [0] = "outgoing"})
|
|
|
|
|
local f_text = ProtoField.string("multi.text", "Text")
|
2014-11-02 21:20:08 +00:00
|
|
|
|
|
|
|
|
|
p_multi.fields = { f_proto, f_dir, f_text }
|
|
|
|
|
|
|
|
|
|
local data_dis = Dissector.get("data")
|
|
|
|
|
|
|
|
|
|
local protos = {
|
|
|
|
|
[2] = Dissector.get("mtp2"),
|
|
|
|
|
[3] = Dissector.get("mtp3"),
|
|
|
|
|
[4] = Dissector.get("alcap"),
|
|
|
|
|
[5] = Dissector.get("h248"),
|
|
|
|
|
[6] = Dissector.get("ranap"),
|
|
|
|
|
[7] = Dissector.get("rnsap"),
|
|
|
|
|
[8] = Dissector.get("nbap"),
|
|
|
|
|
[9] = Dissector.get("rrc"),
|
|
|
|
|
[10] = DissectorTable.get("sctp.ppi"):get_dissector(3), -- m3ua
|
|
|
|
|
[11] = DissectorTable.get("ip.proto"):get_dissector(132), -- sctp
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-17 00:08:44 +00:00
|
|
|
|
function p_multi.dissector(buf, pkt, tree)
|
2014-11-02 21:20:08 +00:00
|
|
|
|
|
2016-10-17 00:08:44 +00:00
|
|
|
|
local subtree = tree:add(p_multi, buf(0,2))
|
|
|
|
|
subtree:add(f_proto, buf(0,1))
|
|
|
|
|
subtree:add(f_dir, buf(1,1))
|
2014-11-02 21:20:08 +00:00
|
|
|
|
|
|
|
|
|
local proto_id = buf(0,1):uint()
|
|
|
|
|
|
|
|
|
|
local dissector = protos[proto_id]
|
|
|
|
|
|
|
|
|
|
if dissector ~= nil then
|
2016-10-17 00:08:44 +00:00
|
|
|
|
-- Dissector was found, invoke subdissector with a new Tvb,
|
|
|
|
|
-- created from the current buffer (skipping first two bytes).
|
|
|
|
|
dissector:call(buf(2):tvb(), pkt, tree)
|
2014-11-02 21:20:08 +00:00
|
|
|
|
elseif proto_id < 2 then
|
2016-10-17 00:08:44 +00:00
|
|
|
|
subtree:add(f_text, buf(2))
|
|
|
|
|
-- pkt.cols.info:set(buf(2, buf:len() - 3):string())
|
2014-11-02 21:20:08 +00:00
|
|
|
|
else
|
2016-10-17 00:08:44 +00:00
|
|
|
|
-- fallback dissector that just shows the raw data.
|
|
|
|
|
data_dis:call(buf(2):tvb(), pkt, tree)
|
2014-11-02 21:20:08 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local wtap_encap_table = DissectorTable.get("wtap_encap")
|
|
|
|
|
local udp_encap_table = DissectorTable.get("udp.port")
|
|
|
|
|
|
2016-10-17 00:08:44 +00:00
|
|
|
|
wtap_encap_table:add(wtap.USER15, p_multi)
|
|
|
|
|
wtap_encap_table:add(wtap.USER12, p_multi)
|
|
|
|
|
udp_encap_table:add(7555, p_multi)
|
2014-11-02 21:20:08 +00:00
|
|
|
|
----
|
|
|
|
|
|
2022-01-16 18:55:52 +00:00
|
|
|
|
[#wslua_tap_example]
|
2014-11-02 21:20:08 +00:00
|
|
|
|
|
2019-05-16 02:21:30 +00:00
|
|
|
|
=== Example: Listener written in Lua
|
2014-11-02 21:20:08 +00:00
|
|
|
|
|
|
|
|
|
[source,lua]
|
|
|
|
|
----
|
|
|
|
|
-- This program will register a menu that will open a window with a count of occurrences
|
|
|
|
|
-- of every address in the capture
|
|
|
|
|
|
|
|
|
|
local function menuable_tap()
|
|
|
|
|
-- Declare the window we will use
|
|
|
|
|
local tw = TextWindow.new("Address Counter")
|
|
|
|
|
|
|
|
|
|
-- This will contain a hash of counters of appearances of a certain address
|
|
|
|
|
local ips = {}
|
|
|
|
|
|
|
|
|
|
-- this is our tap
|
|
|
|
|
local tap = Listener.new();
|
|
|
|
|
|
2018-03-23 17:05:13 +00:00
|
|
|
|
local function remove()
|
2014-11-02 21:20:08 +00:00
|
|
|
|
-- this way we remove the listener that otherwise will remain running indefinitely
|
|
|
|
|
tap:remove();
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- we tell the window to call the remove() function when closed
|
|
|
|
|
tw:set_atclose(remove)
|
|
|
|
|
|
|
|
|
|
-- this function will be called once for each packet
|
|
|
|
|
function tap.packet(pinfo,tvb)
|
|
|
|
|
local src = ips[tostring(pinfo.src)] or 0
|
|
|
|
|
local dst = ips[tostring(pinfo.dst)] or 0
|
|
|
|
|
|
|
|
|
|
ips[tostring(pinfo.src)] = src + 1
|
|
|
|
|
ips[tostring(pinfo.dst)] = dst + 1
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- this function will be called once every few seconds to update our window
|
|
|
|
|
function tap.draw(t)
|
|
|
|
|
tw:clear()
|
|
|
|
|
for ip,num in pairs(ips) do
|
|
|
|
|
tw:append(ip .. "\t" .. num .. "\n");
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- this function will be called whenever a reset is needed
|
|
|
|
|
-- e.g. when reloading the capture file
|
|
|
|
|
function tap.reset()
|
|
|
|
|
tw:clear()
|
|
|
|
|
ips = {}
|
|
|
|
|
end
|
2018-03-23 17:05:13 +00:00
|
|
|
|
|
|
|
|
|
-- Ensure that all existing packets are processed.
|
|
|
|
|
retap_packets()
|
2014-11-02 21:20:08 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- using this function we register our function
|
|
|
|
|
-- to be called when the user selects the Tools->Test->Packets menu
|
|
|
|
|
register_menu("Test/Packets", menuable_tap, MENU_TOOLS_UNSORTED)
|
|
|
|
|
----
|
|
|
|
|
|
2022-01-16 18:55:52 +00:00
|
|
|
|
[#wsluarm_modules]
|
2014-11-02 21:20:08 +00:00
|
|
|
|
|
2018-02-04 23:15:02 +00:00
|
|
|
|
== Wireshark’s Lua API Reference Manual
|
2014-11-02 21:20:08 +00:00
|
|
|
|
|
|
|
|
|
This Part of the User Guide describes the Wireshark specific functions in the embedded Lua.
|
|
|
|
|
|
2016-10-17 00:08:44 +00:00
|
|
|
|
Classes group certain functionality, the following notational conventions are
|
|
|
|
|
used:
|
|
|
|
|
|
2018-02-04 19:39:56 +00:00
|
|
|
|
* _Class.function()_ represents a class method (named _function_) on class
|
|
|
|
|
_Class_, taking no arguments.
|
2016-10-17 00:08:44 +00:00
|
|
|
|
|
2018-02-04 19:39:56 +00:00
|
|
|
|
* _Class.function(a)_ represents a class method taking one argument.
|
2016-10-17 00:08:44 +00:00
|
|
|
|
|
2018-02-04 19:39:56 +00:00
|
|
|
|
* _Class.function(...)_ represents a class method taking a variable number of
|
2016-10-17 00:08:44 +00:00
|
|
|
|
arguments.
|
|
|
|
|
|
2018-02-04 19:39:56 +00:00
|
|
|
|
* _class:method()_ represents an instance method (named _method_) on an instance
|
|
|
|
|
of class _Class_, taking no arguments. Note the lowercase notation in the
|
2016-10-17 00:08:44 +00:00
|
|
|
|
documentation to clarify an instance.
|
|
|
|
|
|
2018-02-04 19:39:56 +00:00
|
|
|
|
* _class.prop_ represents a property _prop_ on the instance of class _Class_.
|
2016-10-17 00:08:44 +00:00
|
|
|
|
|
|
|
|
|
Trying to access a non-existing property, function or method currently gives an
|
|
|
|
|
error, but do not rely on it as the behavior may change in the future.
|
|
|
|
|
|
|
|
|
|
|
2022-03-28 16:31:39 +00:00
|
|
|
|
include::{build_dir}/wsluarm_src/wslua_utility.adoc[]
|
2019-02-14 23:23:05 +00:00
|
|
|
|
include::{build_dir}/wsluarm_src/wslua_gui.adoc[]
|
|
|
|
|
include::{build_dir}/wsluarm_src/wslua_proto.adoc[]
|
2022-03-28 16:31:39 +00:00
|
|
|
|
include::{build_dir}/wsluarm_src/wslua_field.adoc[]
|
|
|
|
|
include::{build_dir}/wsluarm_src/wslua_pinfo.adoc[]
|
2019-02-14 23:23:05 +00:00
|
|
|
|
include::{build_dir}/wsluarm_src/wslua_tvb.adoc[]
|
2022-03-28 16:31:39 +00:00
|
|
|
|
include::{build_dir}/wsluarm_src/wslua_tree.adoc[]
|
|
|
|
|
include::{build_dir}/wsluarm_src/wslua_listener.adoc[]
|
|
|
|
|
include::{build_dir}/wsluarm_src/wslua_dumper.adoc[]
|
|
|
|
|
include::{build_dir}/wsluarm_src/wslua_wtap.adoc[]
|
2019-02-14 23:23:05 +00:00
|
|
|
|
include::{build_dir}/wsluarm_src/wslua_file.adoc[]
|
|
|
|
|
include::{build_dir}/wsluarm_src/wslua_dir.adoc[]
|
|
|
|
|
include::{build_dir}/wsluarm_src/wslua_int64.adoc[]
|
|
|
|
|
include::{build_dir}/wsluarm_src/wslua_struct.adoc[]
|
2022-05-22 23:30:37 +00:00
|
|
|
|
|
|
|
|
|
[#lua_module_PCRE2]
|
|
|
|
|
|
|
|
|
|
=== PCRE2 Regular Expressions
|
|
|
|
|
|
|
|
|
|
Lua has its own native _pattern_ syntax in the string library, but sometimes a
|
|
|
|
|
real regex engine is more useful. Wireshark comes with Perl Compatible Regular
|
|
|
|
|
Expressions version 2 (PCRE2). This engine is exposed into Wireshark’s Lua engine through the
|
|
|
|
|
well-known Lrexlib library. The module is loaded in the global environment using
|
|
|
|
|
the "rex_pcre2" table. The manual is available at https://rrthomas.github.io/lrexlib/manual.html.
|