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
Philippe Antoine 4 years ago committed by Victor Julien
parent 1d4fe38ccb
commit 0cfdec1266

@ -120,3 +120,17 @@ url_decode
Decodes url-encoded data, ie replacing '+' with space and '%HH' with its value.
This does not decode unicode '%uZZZZ' encoding
xor
---
Takes the buffer, applies xor decoding.
.. note:: this transform requires a mandatory option which is the hexadecimal encoded xor key.
This example alerts if ``http.uri`` contains ``password=`` xored with 4-bytes key ``0d0ac8ff``
Example::
alert http any any -> any any (msg:"HTTP with xor"; http.uri; \
xor:"0d0ac8ff"; content:"password="; sid:1;)

@ -336,6 +336,7 @@ noinst_HEADERS = \
detect-transform-sha256.h \
detect-transform-strip-whitespace.h \
detect-transform-urldecode.h \
detect-transform-xor.h \
detect-ttl.h \
detect-udphdr.h \
detect-uricontent.h \
@ -920,6 +921,7 @@ libsuricata_c_a_SOURCES = \
detect-transform-sha256.c \
detect-transform-strip-whitespace.c \
detect-transform-urldecode.c \
detect-transform-xor.c \
detect-ttl.c \
detect-udphdr.c \
detect-uricontent.c \
@ -1191,6 +1193,7 @@ EXTRA_DIST = \
tests/detect-tcpmss.c \
tests/detect-template.c \
tests/detect-transform-pcrexform.c \
tests/detect-transform-xor.c \
tests/detect-ttl.c \
tests/source-pcap.c \
tests/app-layer-htp-file.c \

@ -231,6 +231,7 @@
#include "detect-transform-dotprefix.h"
#include "detect-transform-pcrexform.h"
#include "detect-transform-urldecode.h"
#include "detect-transform-xor.h"
#include "util-rule-vars.h"
@ -659,6 +660,7 @@ void SigTableSetup(void)
DetectTransformDotPrefixRegister();
DetectTransformPcrexformRegister();
DetectTransformUrlDecodeRegister();
DetectTransformXorRegister();
/* close keyword registration */
DetectBufferTypeCloseRegistration();

@ -300,6 +300,7 @@ enum DetectKeywordId {
DETECT_TRANSFORM_DOTPREFIX,
DETECT_TRANSFORM_PCREXFORM,
DETECT_TRANSFORM_URL_DECODE,
DETECT_TRANSFORM_XOR,
DETECT_AL_IKE_EXCH_TYPE,
DETECT_AL_IKE_SPI_INITIATOR,

@ -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…
Cancel
Save