diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index 0a596ccb48..4e96175fda 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -4441,6 +4441,34 @@ type ModbusHeaders: record { len: count; }; +type ModbusFileRecordRequest: record { + ref_type: count; + file_num: count; + record_num: count; + record_len: count; +}; + +type ModbusFileRecordRequests: vector of ModbusFileRecordRequest; + +type ModbusFileRecordResponse: record { + file_len: count; + ref_type: count; + record_data: string; +}; + +type ModbusFileRecordResponses: vector of ModbusFileRecordResponse; + +type ModbusFileReference: record { + ref_type: count; + file_num: count; + record_num: count; + record_len: count; + record_data: string; +}; + +type ModbusFileReferences: vector of ModbusFileReference; + + module SSL; export { type SignatureAndHashAlgorithm: record { diff --git a/scripts/base/protocols/modbus/main.zeek b/scripts/base/protocols/modbus/main.zeek index d2fbc281a8..f40e29f149 100644 --- a/scripts/base/protocols/modbus/main.zeek +++ b/scripts/base/protocols/modbus/main.zeek @@ -79,4 +79,3 @@ event modbus_exception(c: connection, headers: ModbusHeaders, code: count) &prio Log::write(LOG, c$modbus); delete c$modbus$exception; } - diff --git a/src/analyzer/protocol/modbus/events.bif b/src/analyzer/protocol/modbus/events.bif index 067e98bb58..ecd47379c5 100644 --- a/src/analyzer/protocol/modbus/events.bif +++ b/src/analyzer/protocol/modbus/events.bif @@ -191,9 +191,11 @@ event modbus_write_multiple_registers_response%(c: connection, headers: ModbusHe ## ## headers: The headers for the modbus function. ## -## .. note: This event is incomplete. The information from the data structure -## is not yet passed through to the event. -event modbus_read_file_record_request%(c: connection, headers: ModbusHeaders%); +## byte_count: The full byte count for all of the reference records that follow. +## +## refs: A vector of reference records. +event modbus_read_file_record_request%(c: connection, headers: ModbusHeaders, byte_count: count, refs: ModbusFileRecordRequests%); +event modbus_read_file_record_request%(c: connection, headers: ModbusHeaders%) &deprecated="Remove in v7.1. Use the version that takes a byte_count and vector of references"; ## Generated for a Modbus read file record response. ## @@ -201,9 +203,11 @@ event modbus_read_file_record_request%(c: connection, headers: ModbusHeaders%); ## ## headers: The headers for the modbus function. ## -## .. note: This event is incomplete. The information from the data structure -## is not yet passed through to the event. -event modbus_read_file_record_response%(c: connection, headers: ModbusHeaders%); +## byte_count: The full byte count for all of the reference records that follow. +## +## refs: A vector of reference records. +event modbus_read_file_record_response%(c: connection, headers: ModbusHeaders, byte_count: count, refs: ModbusFileRecordResponses%); +event modbus_read_file_record_response%(c: connection, headers: ModbusHeaders%) &deprecated="Remove in v7.1. Use the version that takes a byte_count and vector of references"; ## Generated for a Modbus write file record request. ## @@ -211,9 +215,11 @@ event modbus_read_file_record_response%(c: connection, headers: ModbusHeaders%); ## ## headers: The headers for the modbus function. ## -## .. note: This event is incomplete. The information from the data structure -## is not yet passed through to the event. -event modbus_write_file_record_request%(c: connection, headers: ModbusHeaders%); +## byte_count: The full byte count for all of the reference records that follow. +## +## refs: A vector of reference records. +event modbus_write_file_record_request%(c: connection, headers: ModbusHeaders, byte_count: count, refs: ModbusFileReferences%); +event modbus_write_file_record_request%(c: connection, headers: ModbusHeaders%) &deprecated="Remove in v7.1. Use the version that takes a byte_count and vector of references"; ## Generated for a Modbus write file record response. ## @@ -221,9 +227,11 @@ event modbus_write_file_record_request%(c: connection, headers: ModbusHeaders%); ## ## headers: The headers for the modbus function. ## -## .. note: This event is incomplete. The information from the data structure -## is not yet passed through to the event. -event modbus_write_file_record_response%(c: connection, headers: ModbusHeaders%); +## byte_count: The full byte count for all of the reference records that follow. +## +## refs: A vector of reference records. +event modbus_write_file_record_response%(c: connection, headers: ModbusHeaders, byte_count: count, refs: ModbusFileReferences%); +event modbus_write_file_record_response%(c: connection, headers: ModbusHeaders%) &deprecated="Remove in v7.1. Use the version that takes a byte_count and vector of references"; ## Generated for a Modbus mask write register request. ## diff --git a/src/analyzer/protocol/modbus/modbus-analyzer.pac b/src/analyzer/protocol/modbus/modbus-analyzer.pac index d4769ac252..fdacf86aa2 100644 --- a/src/analyzer/protocol/modbus/modbus-analyzer.pac +++ b/src/analyzer/protocol/modbus/modbus-analyzer.pac @@ -521,23 +521,23 @@ refine flow ModbusTCP_Flow += { %{ if ( ::modbus_read_file_record_request ) { - //TODO: this need to be a vector of some Reference Request record type - //auto t = create_vector_of_count(); - //for ( unsigned int i = 0; i < (${message.references}->size()); ++i ) - // { - // auto r = zeek::val_mgr->Count((${message.references[i].ref_type})); - // t->Assign(i, r); - // - // auto k = zeek::val_mgr->Count((${message.references[i].file_num})); - // t->Assign(i, k); - // - // auto l = zeek::val_mgr->Count((${message.references[i].record_num})); - // t->Assign(i, l); - // } + auto vect = zeek::make_intrusive(zeek::BifType::Vector::ModbusFileRecordRequests); + + for ( unsigned int i = 0; i < (${message.references}->size()); ++i ) + { + auto r = zeek::make_intrusive(zeek::BifType::Record::ModbusFileRecordRequest); + + r->Assign(0, zeek::val_mgr->Count(${message.references[i].ref_type})); + r->Assign(1, zeek::val_mgr->Count(${message.references[i].file_num})); + r->Assign(2, zeek::val_mgr->Count(${message.references[i].record_num})); + r->Assign(3, zeek::val_mgr->Count(${message.references[i].record_len})); + + vect->Append(r); + } zeek::BifEvent::enqueue_modbus_read_file_record_request(connection()->zeek_analyzer(), - connection()->zeek_analyzer()->Conn(), - HeaderToVal(header)); + connection()->zeek_analyzer()->Conn(), + HeaderToVal(header), ${message.byte_count}, vect); } return true; @@ -548,17 +548,22 @@ refine flow ModbusTCP_Flow += { %{ if ( ::modbus_read_file_record_response ) { - //auto t = create_vector_of_count(); - //for ( unsigned int i = 0; i < ${message.references}->size(); ++i ) - // { - // //TODO: work the reference type in here somewhere - // auto r = zeek::val_mgr->Count(${message.references[i].record_data})); - // t->Assign(i, r); - // } + auto vect = zeek::make_intrusive(zeek::BifType::Vector::ModbusFileRecordResponses); + + for ( unsigned int i = 0; i < (${message.references}->size()); ++i ) + { + auto r = zeek::make_intrusive(zeek::BifType::Record::ModbusFileRecordResponse); + + r->Assign(0, zeek::val_mgr->Count(${message.references[i].file_len})); + r->Assign(1, zeek::val_mgr->Count(${message.references[i].ref_type})); + r->Assign(2, to_stringval(${message.references[i].record_data})); + + vect->Append(r); + } zeek::BifEvent::enqueue_modbus_read_file_record_response(connection()->zeek_analyzer(), connection()->zeek_analyzer()->Conn(), - HeaderToVal(header)); + HeaderToVal(header), ${message.byte_count}, vect); } return true; @@ -569,60 +574,50 @@ refine flow ModbusTCP_Flow += { %{ if ( ::modbus_write_file_record_request ) { - //auto t = create_vector_of_count(); - //for ( unsigned int i = 0; i < (${message.references}->size()); ++i ) - // { - // auto r = zeek::val_mgr->Count((${message.references[i].ref_type})); - // t->Assign(i, r); - // - // auto k = zeek::val_mgr->Count((${message.references[i].file_num})); - // t->Assign(i, k); - // - // auto n = zeek::val_mgr->Count((${message.references[i].record_num})); - // t->Assign(i, n); - // - // for ( unsigned int j = 0; j < (${message.references[i].register_value}->size()); ++j ) - // { - // k = zeek::val_mgr->Count((${message.references[i].register_value[j]})); - // t->Assign(i, k); - // } - // } + auto vect = zeek::make_intrusive(zeek::BifType::Vector::ModbusFileReferences); + + for ( unsigned int i = 0; i < (${message.references}->size()); ++i ) + { + auto r = zeek::make_intrusive(zeek::BifType::Record::ModbusFileReference); + r->Assign(0, zeek::val_mgr->Count(${message.references[i].ref_type})); + r->Assign(1, zeek::val_mgr->Count(${message.references[i].file_num})); + r->Assign(2, zeek::val_mgr->Count(${message.references[i].record_num})); + r->Assign(3, zeek::val_mgr->Count(${message.references[i].record_length})); + r->Assign(4, to_stringval(${message.references[i].record_data})); + + vect->Append(r); + } zeek::BifEvent::enqueue_modbus_write_file_record_request(connection()->zeek_analyzer(), connection()->zeek_analyzer()->Conn(), - HeaderToVal(header)); + HeaderToVal(header), ${message.byte_count}, vect); } return true; %} - # RESPONSE FC=21 function deliver_WriteFileRecordResponse(header: ModbusTCP_TransportHeader, message: WriteFileRecordResponse): bool %{ if ( ::modbus_write_file_record_response ) { - //auto t = create_vector_of_count(); - //for ( unsigned int i = 0; i < (${messages.references}->size()); ++i ) - // { - // auto r = zeek::val_mgr->Count((${message.references[i].ref_type})); - // t->Assign(i, r); - // - // auto f = zeek::val_mgr->Count((${message.references[i].file_num})); - // t->Assign(i, f); - // - // auto rn = zeek::val_mgr->Count((${message.references[i].record_num})); - // t->Assign(i, rn); - // - // for ( unsigned int j = 0; j<(${message.references[i].register_value}->size()); ++j ) - // { - // auto k = zeek::val_mgr->Count((${message.references[i].register_value[j]})); - // t->Assign(i, k); - // } + auto vect = zeek::make_intrusive(zeek::BifType::Vector::ModbusFileReferences); + + for ( unsigned int i = 0; i < (${message.references}->size()); ++i ) + { + auto r = zeek::make_intrusive(zeek::BifType::Record::ModbusFileReference); + r->Assign(0, zeek::val_mgr->Count(${message.references[i].ref_type})); + r->Assign(1, zeek::val_mgr->Count(${message.references[i].file_num})); + r->Assign(2, zeek::val_mgr->Count(${message.references[i].record_num})); + r->Assign(3, zeek::val_mgr->Count(${message.references[i].record_length})); + r->Assign(4, to_stringval(${message.references[i].record_data})); + + vect->Append(r); + } zeek::BifEvent::enqueue_modbus_write_file_record_response(connection()->zeek_analyzer(), connection()->zeek_analyzer()->Conn(), - HeaderToVal(header)); + HeaderToVal(header), ${message.byte_count}, vect); } return true; diff --git a/src/analyzer/protocol/modbus/modbus-protocol.pac b/src/analyzer/protocol/modbus/modbus-protocol.pac index b807a683f6..ebd1805815 100644 --- a/src/analyzer/protocol/modbus/modbus-protocol.pac +++ b/src/analyzer/protocol/modbus/modbus-protocol.pac @@ -344,7 +344,7 @@ type ReadFileRecordRequest(header: ModbusTCP_TransportHeader) = record { type FileRecordResponse = record { file_len: uint8; # &check(file_len >= 0x07 && file_len <= 0xF5); ref_type: uint8; # &check(ref_type == 6); - record_data: uint16[file_len/2] &length=file_len; + record_data: bytestring &length=file_len; } &byteorder=bigendian; # RESPONSE FC=20 @@ -357,11 +357,11 @@ type ReadFileRecordResponse(header: ModbusTCP_TransportHeader) = record { # Support data structure for the two following message types. type ReferenceWithData = record { - ref_type: uint8; - file_num: uint16; - record_num: uint16; - word_count: uint16; - register_value: uint16[word_count]; + ref_type: uint8; + file_num: uint16; + record_num: uint16; + record_length: uint16; + record_data: bytestring &length=record_length*2; } &byteorder=bigendian; # REQUEST FC=21 diff --git a/src/types.bif b/src/types.bif index 543a92d4b6..9797e3e08c 100644 --- a/src/types.bif +++ b/src/types.bif @@ -176,6 +176,12 @@ module GLOBAL; type ModbusHeaders: record; type ModbusCoils: vector; type ModbusRegisters: vector; +type ModbusFileRecordRequest: record; +type ModbusFileRecordRequests: vector; +type ModbusFileRecordResponse: record; +type ModbusFileRecordResponses: vector; +type ModbusFileReference: record; +type ModbusFileReferences: vector; type PE::DOSHeader: record; type PE::FileHeader: record; diff --git a/testing/btest/Baseline/scripts.base.protocols.modbus.coil_parsing_big/coverage b/testing/btest/Baseline/scripts.base.protocols.modbus.coil_parsing_big/coverage index f8af25eb8c..c9dd1e6e71 100644 --- a/testing/btest/Baseline/scripts.base.protocols.modbus.coil_parsing_big/coverage +++ b/testing/btest/Baseline/scripts.base.protocols.modbus.coil_parsing_big/coverage @@ -1,2 +1,2 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. -5 of 32 events triggered by trace +5 of 36 events triggered by trace diff --git a/testing/btest/Baseline/scripts.base.protocols.modbus.coil_parsing_small/coverage b/testing/btest/Baseline/scripts.base.protocols.modbus.coil_parsing_small/coverage index f8af25eb8c..c9dd1e6e71 100644 --- a/testing/btest/Baseline/scripts.base.protocols.modbus.coil_parsing_small/coverage +++ b/testing/btest/Baseline/scripts.base.protocols.modbus.coil_parsing_small/coverage @@ -1,2 +1,2 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. -5 of 32 events triggered by trace +5 of 36 events triggered by trace diff --git a/testing/btest/Baseline/scripts.base.protocols.modbus.events/coverage b/testing/btest/Baseline/scripts.base.protocols.modbus.events/coverage index e7693345ad..eb747a6f71 100644 --- a/testing/btest/Baseline/scripts.base.protocols.modbus.events/coverage +++ b/testing/btest/Baseline/scripts.base.protocols.modbus.events/coverage @@ -1,2 +1,2 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. -22 of 32 events triggered by trace +22 of 36 events triggered by trace diff --git a/testing/btest/Baseline/scripts.base.protocols.modbus.events/output b/testing/btest/Baseline/scripts.base.protocols.modbus.events/output index 60c75b87da..074cb159e1 100644 --- a/testing/btest/Baseline/scripts.base.protocols.modbus.events/output +++ b/testing/btest/Baseline/scripts.base.protocols.modbus.events/output @@ -39973,7 +39973,7 @@ 1 modbus_read_coils_response, [orig_h=192.168.66.235, orig_p=2582/tcp, resp_h=166.161.16.230, resp_p=502/tcp], [tid=0, pid=0, uid=1, function_code=1, len=4], [T, F, T, F, T, F, F, F] 1 modbus_read_discrete_inputs_request, [orig_h=192.168.66.235, orig_p=2582/tcp, resp_h=166.161.16.230, resp_p=502/tcp], [tid=0, pid=0, uid=1, function_code=2, len=6], 0, 0 1 modbus_read_fifo_queue_request, [orig_h=192.168.66.235, orig_p=2582/tcp, resp_h=166.161.16.230, resp_p=502/tcp], [tid=0, pid=0, uid=1, function_code=24, len=6], 0 -1 modbus_read_file_record_request, [orig_h=192.168.66.235, orig_p=2582/tcp, resp_h=166.161.16.230, resp_p=502/tcp], [tid=0, pid=0, uid=1, function_code=20, len=6] +1 modbus_read_file_record_request, [orig_h=192.168.66.235, orig_p=2582/tcp, resp_h=166.161.16.230, resp_p=502/tcp], [tid=0, pid=0, uid=1, function_code=20, len=6], 0, [] 1 modbus_read_holding_registers_request, [orig_h=10.0.0.9, orig_p=3082/tcp, resp_h=10.0.0.3, resp_p=502/tcp], [tid=1, pid=0, uid=10, function_code=3, len=6], 5, 2 1 modbus_read_holding_registers_request, [orig_h=10.1.1.234, orig_p=51411/tcp, resp_h=10.10.5.85, resp_p=502/tcp], [tid=10000, pid=0, uid=255, function_code=3, len=6], 100, 100 1 modbus_read_holding_registers_request, [orig_h=10.1.1.234, orig_p=51411/tcp, resp_h=10.10.5.85, resp_p=502/tcp], [tid=10004, pid=0, uid=255, function_code=3, len=6], 500, 100 @@ -79402,7 +79402,7 @@ 1 modbus_read_input_registers_response, [orig_h=10.1.1.234, orig_p=51411/tcp, resp_h=10.10.5.85, resp_p=502/tcp], [tid=9997, pid=0, uid=255, function_code=4, len=203], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 1 modbus_read_input_registers_response, [orig_h=10.1.1.234, orig_p=51411/tcp, resp_h=10.10.5.85, resp_p=502/tcp], [tid=9998, pid=0, uid=255, function_code=4, len=203], [70, 80, 72, 9, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89] 1 modbus_read_input_registers_response, [orig_h=10.1.1.234, orig_p=51411/tcp, resp_h=10.10.5.85, resp_p=502/tcp], [tid=9999, pid=0, uid=255, function_code=4, len=203], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -1 modbus_write_file_record_request, [orig_h=192.168.66.235, orig_p=2582/tcp, resp_h=166.161.16.230, resp_p=502/tcp], [tid=0, pid=0, uid=1, function_code=21, len=6] +1 modbus_write_file_record_request, [orig_h=192.168.66.235, orig_p=2582/tcp, resp_h=166.161.16.230, resp_p=502/tcp], [tid=0, pid=0, uid=1, function_code=21, len=6], 0, [] 1 modbus_write_multiple_coils_request, [orig_h=192.168.66.235, orig_p=2582/tcp, resp_h=166.161.16.230, resp_p=502/tcp], [tid=0, pid=0, uid=1, function_code=15, len=7], 0, [] 1 modbus_write_multiple_registers_request, [orig_h=192.168.66.235, orig_p=2582/tcp, resp_h=166.161.16.230, resp_p=502/tcp], [tid=0, pid=0, uid=1, function_code=16, len=7], 0, [] 1 modbus_write_single_coil_request, [orig_h=10.0.0.9, orig_p=3082/tcp, resp_h=10.0.0.3, resp_p=502/tcp], [tid=1, pid=0, uid=10, function_code=5, len=6], 1, F diff --git a/testing/btest/scripts/base/protocols/modbus/events.zeek b/testing/btest/scripts/base/protocols/modbus/events.zeek index 1bb52fc6c7..4e412b6dfd 100644 --- a/testing/btest/scripts/base/protocols/modbus/events.zeek +++ b/testing/btest/scripts/base/protocols/modbus/events.zeek @@ -110,24 +110,24 @@ event modbus_write_multiple_registers_response(c: connection, headers: ModbusHea print "modbus_write_multiple_registers_response", c$id, headers, start_address, quantity; } -event modbus_read_file_record_request(c: connection, headers: ModbusHeaders) +event modbus_read_file_record_request(c: connection, headers: ModbusHeaders, byte_count: count, refs: ModbusFileRecordRequests) { - print "modbus_read_file_record_request", c$id, headers; + print "modbus_read_file_record_request", c$id, headers, byte_count, refs; } -event modbus_read_file_record_response(c: connection, headers: ModbusHeaders) +event modbus_read_file_record_response(c: connection, headers: ModbusHeaders, byte_count: count, refs: ModbusFileRecordResponses) { - print "modbus_read_file_record_response", c$id, headers; + print "modbus_read_file_record_response", c$id, headers, byte_count, refs; } -event modbus_write_file_record_request(c: connection, headers: ModbusHeaders) +event modbus_write_file_record_request(c: connection, headers: ModbusHeaders, byte_count: count, refs: ModbusFileReferences) { - print "modbus_write_file_record_request", c$id, headers; + print "modbus_write_file_record_request", c$id, headers, byte_count, refs; } -event modbus_write_file_record_response(c: connection, headers: ModbusHeaders) +event modbus_write_file_record_response(c: connection, headers: ModbusHeaders, byte_count: count, refs: ModbusFileReferences) { - print "modbus_write_file_record_response", c$id, headers; + print "modbus_write_file_record_response", c$id, headers, byte_count, refs; } event modbus_mask_write_register_request(c: connection, headers: ModbusHeaders, address: count, and_mask: count, or_mask: count)