Merge branch 'modbus-fc-fixes' of https://github.com/zambo99/zeek

* 'modbus-fc-fixes' of https://github.com/zambo99/zeek:
  Fix issues with Modbus message logging
This commit is contained in:
Arne Welzel 2024-10-30 14:36:57 +01:00
commit fd0181c2cb
8 changed files with 319 additions and 205 deletions

View file

@ -23,6 +23,7 @@ export {
[0x17] = "READ_WRITE_MULTIPLE_REGISTERS",
[0x18] = "READ_FIFO_QUEUE",
[0x2B] = "ENCAP_INTERFACE_TRANSPORT",
[0x5B] = "OBJECT_MESSAGING", # See https://modbus.org/docs/Object_Messaging_Protocol_ExtensionsVers1.1.doc
# Machine/vendor/network specific functions
[0x09] = "PROGRAM_484",
@ -32,25 +33,11 @@ export {
[0x12] = "PROGRAM_884_U84",
[0x13] = "RESET_COMM_LINK_884_U84",
[0x28] = "PROGRAM_CONCEPT",
[0x29] = "MULTIPLE_FUNCTION_CODES", # See https://patents.google.com/patent/US20040054829A1/en
[0x5A] = "PROGRAM_UNITY", # See https://lirasenlared.blogspot.com/2017/08/the-unity-umas-protocol-part-i.html
[0x7D] = "FIRMWARE_REPLACEMENT",
[0x7E] = "PROGRAM_584_984_2",
[0x7F] = "REPORT_LOCAL_ADDRESS",
# Exceptions
[0x81] = "READ_COILS_EXCEPTION",
[0x82] = "READ_DISCRETE_INPUTS_EXCEPTION",
[0x83] = "READ_HOLDING_REGISTERS_EXCEPTION",
[0x84] = "READ_INPUT_REGISTERS_EXCEPTION",
[0x85] = "WRITE_SINGLE_COIL_EXCEPTION",
[0x86] = "WRITE_SINGLE_REGISTER_EXCEPTION",
[0x87] = "READ_EXCEPTION_STATUS_EXCEPTION",
[0x8F] = "WRITE_MULTIPLE_COILS_EXCEPTION",
[0x90] = "WRITE_MULTIPLE_REGISTERS_EXCEPTION",
[0x94] = "READ_FILE_RECORD_EXCEPTION",
[0x95] = "WRITE_FILE_RECORD_EXCEPTION",
[0x96] = "MASK_WRITE_REGISTER_EXCEPTION",
[0x97] = "READ_WRITE_MULTIPLE_REGISTERS_EXCEPTION",
[0x98] = "READ_FIFO_QUEUE_EXCEPTION",
} &default=function(i: count):string { return fmt("unknown-%d", i); } &redef;
const exception_codes = {

View file

@ -45,6 +45,25 @@ event zeek_init() &priority=5
Log::create_stream(Modbus::LOG, [$columns=Info, $ev=log_modbus, $path="modbus", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_MODBUS, ports);
}
function build_func(func: count): string
{
local masked = func & ~0x80;
# If the function code is in function_codes, use it. Also,
# if the masked value isn't in function_codes, use function_codes
# &default functionality.
if ( func in function_codes || masked !in function_codes )
return function_codes[func];
local s = function_codes[masked];
# Suffix exceptions with _EXCEPTION.
if ( func & 0x80 == 0x80 )
s += "_EXCEPTION";
return s;
}
event modbus_message(c: connection, headers: ModbusHeaders, is_orig: bool) &priority=5
{
@ -56,7 +75,7 @@ event modbus_message(c: connection, headers: ModbusHeaders, is_orig: bool) &prio
c$modbus$ts = network_time();
c$modbus$tid = headers$tid;
c$modbus$unit = headers$uid;
c$modbus$func = function_codes[headers$function_code];
c$modbus$func = build_func(headers$function_code);
## If this message is from the TCP originator, it is a request. Otherwise,
## it is a response.
c$modbus$pdu_type = is_orig ? "REQ" : "RESP";
@ -65,7 +84,7 @@ event modbus_message(c: connection, headers: ModbusHeaders, is_orig: bool) &prio
event modbus_message(c: connection, headers: ModbusHeaders, is_orig: bool) &priority=-5
{
# Don't log now if this is an exception (log in the exception event handler)
if ( headers$function_code <= 0x81 || headers$function_code >= 0x98 )
if ( headers$function_code < 0x80 )
Log::write(LOG, c$modbus);
}