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