mirror of https://github.com/OISF/suricata
detect: xor transform
Ticket: 3285 The xor transform applies xor decoding to a buffer, with a key specified as an option in hexadecimal. Arbitrary key sizes are accepted.pull/6809/head
parent
1d4fe38ccb
commit
0cfdec1266
@ -0,0 +1,144 @@
|
||||
/* Copyright (C) 2021 Open Information Security Foundation
|
||||
*
|
||||
* You can copy, redistribute or modify this Program under the terms of
|
||||
* the GNU General Public License version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \author Philippe Antoine <contact@catenacyber.fr>
|
||||
*
|
||||
* Implements the xor transform keyword with option support
|
||||
*/
|
||||
|
||||
#include "suricata-common.h"
|
||||
#include "detect.h"
|
||||
#include "detect-engine.h"
|
||||
#include "detect-parse.h"
|
||||
#include "detect-transform-xor.h"
|
||||
|
||||
typedef struct DetectTransformXorData {
|
||||
uint8_t *key;
|
||||
// limit the key length
|
||||
uint8_t length;
|
||||
} DetectTransformXorData;
|
||||
|
||||
static int DetectTransformXorSetup(DetectEngineCtx *, Signature *, const char *);
|
||||
static void DetectTransformXorFree(DetectEngineCtx *, void *);
|
||||
static void DetectTransformXor(InspectionBuffer *buffer, void *options);
|
||||
#ifdef UNITTESTS
|
||||
void DetectTransformXorRegisterTests(void);
|
||||
#endif
|
||||
|
||||
void DetectTransformXorRegister(void)
|
||||
{
|
||||
sigmatch_table[DETECT_TRANSFORM_XOR].name = "xor";
|
||||
sigmatch_table[DETECT_TRANSFORM_XOR].desc = "modify buffer via XOR decoding before inspection";
|
||||
sigmatch_table[DETECT_TRANSFORM_XOR].url = "/rules/transforms.html#xor";
|
||||
sigmatch_table[DETECT_TRANSFORM_XOR].Transform = DetectTransformXor;
|
||||
sigmatch_table[DETECT_TRANSFORM_XOR].Free = DetectTransformXorFree;
|
||||
sigmatch_table[DETECT_TRANSFORM_XOR].Setup = DetectTransformXorSetup;
|
||||
#ifdef UNITTESTS
|
||||
sigmatch_table[DETECT_TRANSFORM_XOR].RegisterTests = DetectTransformXorRegisterTests;
|
||||
#endif
|
||||
sigmatch_table[DETECT_TRANSFORM_XOR].flags |= SIGMATCH_QUOTES_MANDATORY;
|
||||
}
|
||||
|
||||
static void DetectTransformXorFree(DetectEngineCtx *de_ctx, void *ptr)
|
||||
{
|
||||
if (ptr != NULL) {
|
||||
DetectTransformXorData *pxd = (DetectTransformXorData *)ptr;
|
||||
SCFree(pxd->key);
|
||||
SCFree(pxd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* \brief Apply the xor keyword to the last pattern match
|
||||
* \param det_ctx detection engine ctx
|
||||
* \param s signature
|
||||
* \param optstr options string
|
||||
* \retval 0 ok
|
||||
* \retval -1 failure
|
||||
*/
|
||||
static int DetectTransformXorSetup(DetectEngineCtx *de_ctx, Signature *s, const char *optstr)
|
||||
{
|
||||
SCEnter();
|
||||
|
||||
// Create pxd from optstr
|
||||
DetectTransformXorData *pxd = SCCalloc(1, sizeof(*pxd));
|
||||
if (pxd == NULL) {
|
||||
SCLogError(SC_ERR_MEM_ALLOC, "memory allocation failed");
|
||||
SCReturnInt(-1);
|
||||
}
|
||||
|
||||
size_t keylen = strlen(optstr);
|
||||
if (keylen % 2 == 1) {
|
||||
SCLogError(SC_ERR_INVALID_SIGNATURE, "XOR transform key's length must be an even number");
|
||||
DetectTransformXorFree(de_ctx, pxd);
|
||||
SCReturnInt(-1);
|
||||
}
|
||||
if (keylen / 2 > UINT8_MAX) {
|
||||
SCLogError(SC_ERR_INVALID_SIGNATURE, "Key length too big for XOR transform");
|
||||
DetectTransformXorFree(de_ctx, pxd);
|
||||
SCReturnInt(-1);
|
||||
}
|
||||
pxd->length = keylen / 2;
|
||||
pxd->key = SCMalloc(keylen / 2);
|
||||
if (pxd->key == NULL) {
|
||||
SCLogError(SC_ERR_MEM_ALLOC, "memory allocation failed");
|
||||
DetectTransformXorFree(de_ctx, pxd);
|
||||
SCReturnInt(-1);
|
||||
}
|
||||
for (size_t i = 0; i < keylen / 2; i++) {
|
||||
if ((isxdigit(optstr[2 * i])) && (isxdigit(optstr[2 * i + 1]))) {
|
||||
pxd->key[i] = (optstr[2 * i] >= 'A' ? ((optstr[2 * i] & 0xdf) - 'A') + 10
|
||||
: (optstr[2 * i] - '0'))
|
||||
<< 4;
|
||||
pxd->key[i] |= (optstr[2 * i + 1] >= 'A' ? ((optstr[2 * i + 1] & 0xdf) - 'A') + 10
|
||||
: (optstr[2 * i + 1] - '0'));
|
||||
} else {
|
||||
SCLogError(SC_ERR_INVALID_SIGNATURE,
|
||||
"XOR transform key must be hexadecimal characters only");
|
||||
DetectTransformXorFree(de_ctx, pxd);
|
||||
SCReturnInt(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int r = DetectSignatureAddTransform(s, DETECT_TRANSFORM_XOR, pxd);
|
||||
if (r != 0) {
|
||||
DetectTransformXorFree(de_ctx, pxd);
|
||||
}
|
||||
|
||||
SCReturnInt(r);
|
||||
}
|
||||
|
||||
static void DetectTransformXor(InspectionBuffer *buffer, void *options)
|
||||
{
|
||||
const uint8_t *input = buffer->inspect;
|
||||
const uint32_t input_len = buffer->inspect_len;
|
||||
DetectTransformXorData *pxd = options;
|
||||
uint8_t output[input_len];
|
||||
|
||||
for (uint32_t i = 0; i < input_len; i++) {
|
||||
output[i] = input[i] ^ pxd->key[i % pxd->length];
|
||||
}
|
||||
InspectionBufferCopy(buffer, output, input_len);
|
||||
}
|
||||
|
||||
#ifdef UNITTESTS
|
||||
#include "tests/detect-transform-xor.c"
|
||||
#endif
|
@ -0,0 +1,30 @@
|
||||
/* Copyright (C) 2021 Open Information Security Foundation
|
||||
*
|
||||
* You can copy, redistribute or modify this Program under the terms of
|
||||
* the GNU General Public License version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \author Philippe Antoine <contact@catenacyber.fr>
|
||||
*/
|
||||
|
||||
#ifndef __DETECT_TRANSFORM_XOR_H__
|
||||
#define __DETECT_TRANSFORM_XOR_H__
|
||||
|
||||
/* prototypes */
|
||||
void DetectTransformXorRegister(void);
|
||||
|
||||
#endif /* __DETECT_TRANSFORM_XOR_H__ */
|
@ -0,0 +1,67 @@
|
||||
/* Copyright (C) 2021 Open Information Security Foundation
|
||||
*
|
||||
* You can copy, redistribute or modify this Program under the terms of
|
||||
* the GNU General Public License version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "../suricata-common.h"
|
||||
|
||||
#include "../detect-engine.h"
|
||||
|
||||
#include "../detect-transform-xor.h"
|
||||
|
||||
#include "../util-unittest.h"
|
||||
|
||||
/**
|
||||
* \test signature with an invalid xor value.
|
||||
*/
|
||||
|
||||
static int DetectTransformXorParseTest01(void)
|
||||
{
|
||||
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
||||
FAIL_IF_NULL(de_ctx);
|
||||
|
||||
Signature *sig = DetectEngineAppendSig(de_ctx, "alert tcp any any <> any 1 xor:\"nohexa\";");
|
||||
FAIL_IF_NOT_NULL(sig);
|
||||
|
||||
DetectEngineCtxFree(de_ctx);
|
||||
PASS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \test signature with a valid xor value.
|
||||
*/
|
||||
|
||||
static int DetectTransformXorParseTest02(void)
|
||||
{
|
||||
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
||||
FAIL_IF_NULL(de_ctx);
|
||||
|
||||
Signature *sig = DetectEngineAppendSig(de_ctx,
|
||||
"alert http any any -> any any (msg:\"HTTP with xor\"; http.request_line; "
|
||||
"xor:\"0a0DC8ff\"; content:\"/z4d4kWk.jpg\"; sid:1;)");
|
||||
FAIL_IF_NULL(sig);
|
||||
|
||||
DetectEngineCtxFree(de_ctx);
|
||||
PASS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief this function registers unit tests for DetectTransformXor
|
||||
*/
|
||||
void DetectTransformXorRegisterTests(void)
|
||||
{
|
||||
UtRegisterTest("DetectTransformXorParseTest01", DetectTransformXorParseTest01);
|
||||
UtRegisterTest("DetectTransformXorParseTest02", DetectTransformXorParseTest02);
|
||||
}
|
Loading…
Reference in New Issue