diff --git a/scripts/policy/protocols/modbus/track-memmap.bro b/scripts/policy/protocols/modbus/track-memmap.bro index cc02ce9e6a..fc02d9b274 100644 --- a/scripts/policy/protocols/modbus/track-memmap.bro +++ b/scripts/policy/protocols/modbus/track-memmap.bro @@ -60,7 +60,7 @@ event modbus_read_holding_registers_request(c: connection, headers: ModbusHeader c$modbus$track_address = start_address+1; } -event modbus_read_holding_registers_response(c: connection, headers: ModbusHeaders, byte_count: count, registers: ModbusRegisters) +event modbus_read_holding_registers_response(c: connection, headers: ModbusHeaders, registers: ModbusRegisters) { local slave = c$id$resp_h; diff --git a/src/event.bif b/src/event.bif index cc8acb1849..b965c26ae9 100644 --- a/src/event.bif +++ b/src/event.bif @@ -6623,10 +6623,8 @@ event modbus_read_holding_registers_request%(c: connection, headers: ModbusHeade ## ## headers: The headers for the modbus function. ## -## byte_count: The number of bytes in the message that comprise register values. -## ## registers: The register values returned from the device. -event modbus_read_holding_registers_response%(c: connection, headers: ModbusHeaders, byte_count: count, registers: ModbusRegisters%); +event modbus_read_holding_registers_response%(c: connection, headers: ModbusHeaders, registers: ModbusRegisters%); ## Generated for a Modbus read input registers request. ## @@ -6645,10 +6643,8 @@ event modbus_read_input_registers_request%(c: connection, headers: ModbusHeaders ## ## headers: The headers for the modbus function. ## -## byte_count: The number of bytes in the message that comprise register values. -## ## registers: The register values returned from the device. -event modbus_read_input_registers_response%(c: connection, headers: ModbusHeaders, byte_count: count, registers: ModbusRegisters%); +event modbus_read_input_registers_response%(c: connection, headers: ModbusHeaders, registers: ModbusRegisters%); ## Generated for a Modbus write single coil request. ## @@ -6724,10 +6720,8 @@ event modbus_write_multiple_coils_response%(c: connection, headers: ModbusHeader ## ## start_address: The memory address of the first register to be written. ## -## byte_count: The number of bytes in the message that comprise register values. -## ## registers: The values to be written to the registers. -event modbus_write_multiple_registers_request%(c: connection, headers: ModbusHeaders, start_address: count, byte_count: count, registers: ModbusRegisters%); +event modbus_write_multiple_registers_request%(c: connection, headers: ModbusHeaders, start_address: count, registers: ModbusRegisters%); ## Generated for a Modbus write multiple registers response. ## @@ -6818,10 +6812,8 @@ event modbus_mask_write_register_response%(c: connection, headers: ModbusHeaders ## ## write_start_address: The memory address of the first register to be written. ## -## write_byte_count: Number of bytes in message that comprise register values. -## ## write_registers: The values to be written to the registers. -event modbus_read_write_multiple_registers_request%(c: connection, headers: ModbusHeaders, read_start_address: count, read_quantity: count, write_start_address: count, write_byte_count: count, write_registers: ModbusRegisters%); +event modbus_read_write_multiple_registers_request%(c: connection, headers: ModbusHeaders, read_start_address: count, read_quantity: count, write_start_address: count, write_registers: ModbusRegisters%); ## Generated for a Modbus read/write multiple registers response. ## @@ -6829,10 +6821,8 @@ event modbus_read_write_multiple_registers_request%(c: connection, headers: Modb ## ## headers: The headers for the modbus function. ## -## byte_count: The number of bytes in the message that comprise register values. -## ## written_registers: The register values read from the registers specified in the request. -event modbus_read_write_multiple_registers_response%(c: connection, headers: ModbusHeaders, byte_count: count, written_registers: ModbusRegisters%); +event modbus_read_write_multiple_registers_response%(c: connection, headers: ModbusHeaders, written_registers: ModbusRegisters%); ## Generated for a Modbus read FIFO queue request. ## @@ -6849,10 +6839,8 @@ event modbus_read_fifo_queue_request%(c: connection, headers: ModbusHeaders, sta ## ## headers: The headers for the modbus function. ## -## byte_count: The number of bytes in the message that comprise register values. -## ## fifos: The register values read from the FIFO queue on the device. -event modbus_read_fifo_queue_response%(c: connection, headers: ModbusHeaders, byte_count: count, fifos: ModbusRegisters%); +event modbus_read_fifo_queue_response%(c: connection, headers: ModbusHeaders, fifos: ModbusRegisters%); ## Raised for informational messages reported via Bro's reporter framework. Such ## messages may be generated internally by the event engine and also by other diff --git a/src/modbus-analyzer.pac b/src/modbus-analyzer.pac index 155da9647f..b03df9d188 100644 --- a/src/modbus-analyzer.pac +++ b/src/modbus-analyzer.pac @@ -135,8 +135,16 @@ refine flow ModbusTCP_Flow += { # RESPONSE FC=3 function deliver_ReadHoldingRegistersResponse(header: ModbusTCP_TransportHeader, message: ReadHoldingRegistersResponse): bool %{ + if ( ${message.byte_count} % 2 != 0 ) + { + connection()->bro_analyzer()->ProtocolViolation( + fmt("invalid value for modbus read holding register response byte count %d", ${message.byte_count})); + return false; + } + if ( ::modbus_read_holding_registers_response ) { + VectorVal* t = new VectorVal(BifType::Vector::ModbusRegisters); for ( unsigned int i=0; i < ${message.registers}->size(); ++i ) { @@ -147,7 +155,6 @@ refine flow ModbusTCP_Flow += { BifEvent::generate_modbus_read_holding_registers_response(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), HeaderToBro(header), - ${message.byte_count}, t); } @@ -172,6 +179,13 @@ refine flow ModbusTCP_Flow += { # RESPONSE FC=4 function deliver_ReadInputRegistersResponse(header: ModbusTCP_TransportHeader, message: ReadInputRegistersResponse): bool %{ + if ( ${message.byte_count} % 2 != 0 ) + { + connection()->bro_analyzer()->ProtocolViolation( + fmt("invalid value for modbus read input register response byte count %d", ${message.byte_count})); + return false; + } + if ( ::modbus_read_input_registers_response ) { VectorVal* t = new VectorVal(BifType::Vector::ModbusRegisters); @@ -184,7 +198,6 @@ refine flow ModbusTCP_Flow += { BifEvent::generate_modbus_read_input_registers_response(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), HeaderToBro(header), - ${message.byte_count}, t); } @@ -309,6 +322,13 @@ refine flow ModbusTCP_Flow += { # REQUEST FC=16 function deliver_WriteMultipleRegistersRequest(header: ModbusTCP_TransportHeader, message: WriteMultipleRegistersRequest): bool %{ + if ( ${message.byte_count} % 2 != 0 ) + { + connection()->bro_analyzer()->ProtocolViolation( + fmt("invalid value for modbus write multiple registers request byte count %d", ${message.byte_count})); + return false; + } + if ( ::modbus_write_multiple_registers_request ) { VectorVal * t = new VectorVal(BifType::Vector::ModbusRegisters); @@ -321,7 +341,7 @@ refine flow ModbusTCP_Flow += { BifEvent::generate_modbus_write_multiple_registers_request(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), HeaderToBro(header), - ${message.start_address}, ${message.byte_count}, t); + ${message.start_address}, t); } return true; @@ -486,6 +506,13 @@ refine flow ModbusTCP_Flow += { # REQUEST FC=23 function deliver_ReadWriteMultipleRegistersRequest(header: ModbusTCP_TransportHeader, message: ReadWriteMultipleRegistersRequest): bool %{ + if ( ${message.write_byte_count} % 2 != 0 ) + { + connection()->bro_analyzer()->ProtocolViolation( + fmt("invalid value for modbus read write multiple registers request write byte count %d", ${message.write_byte_count})); + return false; + } + if ( ::modbus_read_write_multiple_registers_request ) { VectorVal* t = new VectorVal(BifType::Vector::ModbusRegisters); @@ -501,7 +528,6 @@ refine flow ModbusTCP_Flow += { ${message.read_start_address}, ${message.read_quantity}, ${message.write_start_address}, - ${message.write_byte_count}, t); } @@ -511,6 +537,13 @@ refine flow ModbusTCP_Flow += { # RESPONSE FC=23 function deliver_ReadWriteMultipleRegistersResponse(header: ModbusTCP_TransportHeader, message: ReadWriteMultipleRegistersResponse): bool %{ + if ( ${message.byte_count} % 2 != 0 ) + { + connection()->bro_analyzer()->ProtocolViolation( + fmt("invalid value for modbus read write multiple registers response byte count %d", ${message.byte_count})); + return false; + } + if ( ::modbus_read_write_multiple_registers_response ) { VectorVal* t = new VectorVal(BifType::Vector::ModbusRegisters); @@ -523,7 +556,6 @@ refine flow ModbusTCP_Flow += { BifEvent::generate_modbus_read_write_multiple_registers_response(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), HeaderToBro(header), - ${message.byte_count}, t); } @@ -548,6 +580,13 @@ refine flow ModbusTCP_Flow += { # RESPONSE FC=24 function deliver_ReadFIFOQueueResponse(header: ModbusTCP_TransportHeader, message: ReadFIFOQueueResponse): bool %{ + if ( ${message.byte_count} % 2 != 0 ) + { + connection()->bro_analyzer()->ProtocolViolation( + fmt("invalid value for modbus read FIFO queue response byte count %d", ${message.byte_count})); + return false; + } + if ( ::modbus_read_fifo_queue_response ) { VectorVal* t = new VectorVal(new VectorType(base_type(TYPE_COUNT))); @@ -560,7 +599,6 @@ refine flow ModbusTCP_Flow += { BifEvent::generate_modbus_read_fifo_queue_response(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), HeaderToBro(header), - ${message.byte_count}, t); } diff --git a/testing/btest/Baseline/scripts.base.protocols.modbus.register_parsing/output b/testing/btest/Baseline/scripts.base.protocols.modbus.register_parsing/output index 353f85d2ef..5bb5f1be7c 100644 --- a/testing/btest/Baseline/scripts.base.protocols.modbus.register_parsing/output +++ b/testing/btest/Baseline/scripts.base.protocols.modbus.register_parsing/output @@ -1,5 +1,4 @@ modbus_read_input_registers_request, [orig_h=10.1.1.234, orig_p=51411/tcp, resp_h=10.10.5.104, resp_p=502/tcp], [tid=1119, pid=0, uid=255, function_code=4], 900, 147 -modbus_read_input_registers_response, [orig_h=10.1.1.234, orig_p=51411/tcp, resp_h=10.10.5.104, resp_p=502/tcp], [tid=2606, pid=0, uid=255, function_code=4], [0, 0, 0, 0, 0, 0, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690], 100, 200 -modbus_read_input_registers_response, [orig_h=10.1.1.234, orig_p=51411/tcp, resp_h=10.10.5.104, resp_p=502/tcp], [tid=6714, pid=0, uid=255, function_code=4], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3840, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 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], 64, 129 +modbus_read_input_registers_response, [orig_h=10.1.1.234, orig_p=51411/tcp, resp_h=10.10.5.104, resp_p=502/tcp], [tid=2606, pid=0, uid=255, function_code=4], [0, 0, 0, 0, 0, 0, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690], 100 modbus_read_input_registers_request, [orig_h=10.1.1.234, orig_p=51411/tcp, resp_h=10.10.5.104, resp_p=502/tcp], [tid=12993, pid=0, uid=255, function_code=4], 400, 100 -modbus_read_input_registers_response, [orig_h=10.1.1.234, orig_p=51411/tcp, resp_h=10.10.5.104, resp_p=502/tcp], [tid=17667, pid=0, uid=255, function_code=4], [49, 18012, 51, 42, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 49, 50, 51, 54324, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 69, 63, 64, 65, 66, 67, 68, 49, 189, 51, 52, 53, 54, 4151, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 136, 49, 50, 51, 212, 53, 54, 170, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690], 100, 200 +modbus_read_input_registers_response, [orig_h=10.1.1.234, orig_p=51411/tcp, resp_h=10.10.5.104, resp_p=502/tcp], [tid=17667, pid=0, uid=255, function_code=4], [49, 18012, 51, 42, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 49, 50, 51, 54324, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 69, 63, 64, 65, 66, 67, 68, 49, 189, 51, 52, 53, 54, 4151, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 136, 49, 50, 51, 212, 53, 54, 170, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690, 43690], 100 diff --git a/testing/btest/scripts/base/protocols/modbus/events.bro b/testing/btest/scripts/base/protocols/modbus/events.bro index 6c47dc611a..f648a0adde 100644 --- a/testing/btest/scripts/base/protocols/modbus/events.bro +++ b/testing/btest/scripts/base/protocols/modbus/events.bro @@ -41,7 +41,7 @@ event modbus_read_holding_registers_request(c: connection, headers: ModbusHeader print "modbus_read_holding_registers_request", c, headers, start_address, quantity; } -event modbus_read_holding_registers_response(c: connection, headers: ModbusHeaders, byte_count: count, registers: ModbusRegisters) +event modbus_read_holding_registers_response(c: connection, headers: ModbusHeaders, registers: ModbusRegisters) { print "modbus_read_holding_registers_response", c, headers, registers; } @@ -51,7 +51,7 @@ event modbus_read_input_registers_request(c: connection, headers: ModbusHeaders, print "modbus_read_input_registers_request", c, headers, start_address, quantity; } -event modbus_read_input_registers_response(c: connection, headers: ModbusHeaders, byte_count: count, registers: ModbusRegisters) +event modbus_read_input_registers_response(c: connection, headers: ModbusHeaders, registers: ModbusRegisters) { print "modbus_read_input_registers_response", c, headers, registers; } @@ -86,7 +86,7 @@ event modbus_write_multiple_coils_response(c: connection, headers: ModbusHeaders print "modbus_write_multiple_coils_response", c, headers, start_address, quantity; } -event modbus_write_multiple_registers_request(c: connection, headers: ModbusHeaders, start_address: count, byte_count: count, registers: ModbusRegisters) +event modbus_write_multiple_registers_request(c: connection, headers: ModbusHeaders, start_address: count, registers: ModbusRegisters) { print "modbus_write_multiple_registers_request", c, headers, start_address, registers; } @@ -126,12 +126,12 @@ event modbus_mask_write_register_response(c: connection, headers: ModbusHeaders, print "modbus_mask_write_register_response", c, headers, address, and_mask, or_mask; } -event modbus_read_write_multiple_registers_request(c: connection, headers: ModbusHeaders, read_start_address: count, read_quantity: count, write_start_address: count, write_byte_count: count, write_registers: ModbusRegisters) +event modbus_read_write_multiple_registers_request(c: connection, headers: ModbusHeaders, read_start_address: count, read_quantity: count, write_start_address: count, write_registers: ModbusRegisters) { print "modbus_read_write_multiple_registers_request", c, headers, read_start_address, read_quantity, write_start_address, write_registers; } -event modbus_read_write_multiple_registers_response(c: connection, headers: ModbusHeaders, byte_count: count, written_registers: ModbusRegisters) +event modbus_read_write_multiple_registers_response(c: connection, headers: ModbusHeaders, written_registers: ModbusRegisters) { print "modbus_read_write_multiple_registers_response", c, headers, written_registers; } @@ -141,7 +141,7 @@ event modbus_read_fifo_queue_request(c: connection, headers: ModbusHeaders, star print "modbus_read_fifo_queue_request", c, headers, start_address; } -event modbus_read_fifo_queue_response(c: connection, headers: ModbusHeaders, byte_count: count, fifos: ModbusRegisters) +event modbus_read_fifo_queue_response(c: connection, headers: ModbusHeaders, fifos: ModbusRegisters) { print "modbus_read_fifo_queue_response", c, headers, fifos; } diff --git a/testing/btest/scripts/base/protocols/modbus/register_parsing.bro b/testing/btest/scripts/base/protocols/modbus/register_parsing.bro index 300dd75bfe..1641860228 100644 --- a/testing/btest/scripts/base/protocols/modbus/register_parsing.bro +++ b/testing/btest/scripts/base/protocols/modbus/register_parsing.bro @@ -6,15 +6,16 @@ # of register values, with the quantity being derived from a byte count value # that is also sent. If the byte count value is invalid (e.g. an odd value # might not be valid since registers must be 2-byte values), then the parser -# should not trigger any asserts, but the resulting event could indicate -# the strangeness (i.e. byte_count != 2*|registers|). +# should not trigger any asserts, but generate a protocol_violation (in this +# case TCP_ApplicationAnalyzer::ProtocolViolation asserts its behavior for +# incomplete connections). event modbus_read_input_registers_request(c: connection, headers: ModbusHeaders, start_address: count, quantity: count) { print "modbus_read_input_registers_request", c$id, headers, start_address, quantity; } -event modbus_read_input_registers_response(c: connection, headers: ModbusHeaders, byte_count: count, registers: ModbusRegisters) +event modbus_read_input_registers_response(c: connection, headers: ModbusHeaders, registers: ModbusRegisters) { - print "modbus_read_input_registers_response", c$id, headers, registers, |registers|, byte_count; + print "modbus_read_input_registers_response", c$id, headers, registers, |registers|; }