diff options
Diffstat (limited to 'src/detect-modbus.c')
-rw-r--r-- | src/detect-modbus.c | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/detect-modbus.c b/src/detect-modbus.c new file mode 100644 index 0000000..b010500 --- /dev/null +++ b/src/detect-modbus.c @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2014 ANSSI + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * \author David DIALLO <diallo@et.esiea.fr> + * + * Implements the Modbus function and access keywords + * You can specify a: + * - concrete function like Modbus: + * function 8, subfunction 4 (diagnostic: Force Listen Only Mode) + * - data (in primary table) register access (r/w) like Modbus: + * access read coils, address 1000 (.i.e Read coils: at address 1000) + * - write data value at specific address Modbus: + * access write, address 1500<>2000, value >2000 (Write multiple coils/register: + * at address between 1500 and 2000 value greater than 2000) + */ + +#include "suricata-common.h" + +#include "detect.h" +#include "detect-parse.h" +#include "detect-engine.h" + +#include "detect-modbus.h" + +#include "util-debug.h" +#include "util-byte.h" + +#include "stream-tcp.h" +#include "rust.h" + +static int g_modbus_buffer_id = 0; + +/** \internal + * + * \brief this function will free memory associated with DetectModbus + * + * \param ptr pointer to DetectModbus + */ +static void DetectModbusFree(DetectEngineCtx *de_ctx, void *ptr) { + SCEnter(); + if (ptr != NULL) { + rs_modbus_free(ptr); + } + SCReturn; +} + +/** \internal + * + * \brief this function is used to add the parsed "id" option into the current signature + * + * \param de_ctx Pointer to the Detection Engine Context + * \param s Pointer to the Current Signature + * \param str Pointer to the user provided "id" option + * + * \retval 0 on Success or -1 on Failure + */ +static int DetectModbusSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str) +{ + SCEnter(); + DetectModbusRust *modbus = NULL; + SigMatch *sm = NULL; + + if (DetectSignatureSetAppProto(s, ALPROTO_MODBUS) != 0) + return -1; + + if ((modbus = rs_modbus_parse(str)) == NULL) { + SCLogError("invalid modbus option"); + goto error; + } + + /* Okay so far so good, lets get this into a SigMatch and put it in the Signature. */ + sm = SigMatchAlloc(); + if (sm == NULL) + goto error; + + sm->type = DETECT_AL_MODBUS; + sm->ctx = (void *) modbus; + + SigMatchAppendSMToList(s, sm, g_modbus_buffer_id); + + SCReturnInt(0); + +error: + if (modbus != NULL) + DetectModbusFree(de_ctx, modbus); + if (sm != NULL) + SCFree(sm); + SCReturnInt(-1); +} + +static int DetectModbusMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, void *state, + void *txv, const Signature *s, const SigMatchCtx *ctx) +{ + return rs_modbus_inspect(txv, (void *)ctx); +} + +/** + * \brief Registration function for Modbus keyword + */ +void DetectModbusRegister(void) +{ + sigmatch_table[DETECT_AL_MODBUS].name = "modbus"; + sigmatch_table[DETECT_AL_MODBUS].desc = "match on various properties of Modbus requests"; + sigmatch_table[DETECT_AL_MODBUS].url = "/rules/modbus-keyword.html#modbus-keyword"; + sigmatch_table[DETECT_AL_MODBUS].Match = NULL; + sigmatch_table[DETECT_AL_MODBUS].Setup = DetectModbusSetup; + sigmatch_table[DETECT_AL_MODBUS].Free = DetectModbusFree; + sigmatch_table[DETECT_AL_MODBUS].AppLayerTxMatch = DetectModbusMatch; + + DetectAppLayerInspectEngineRegister2( + "modbus", ALPROTO_MODBUS, SIG_FLAG_TOSERVER, 0, DetectEngineInspectGenericList, NULL); + + g_modbus_buffer_id = DetectBufferTypeGetByName("modbus"); +} |