From bdf119ade35e940c5f27d27197ed6bb9eb5d5ad6 Mon Sep 17 00:00:00 2001 From: Pablo Rincon Date: Tue, 15 Sep 2009 19:26:30 +0200 Subject: [PATCH] Adding window and isdataat keyword and some unittests --- INSTALL | 19 ++ src/Makefile.am | 2 + src/detect-content.c | 29 +++ src/detect-content.h | 2 + src/detect-isdataat.c | 561 ++++++++++++++++++++++++++++++++++++++++++ src/detect-isdataat.h | 19 ++ src/detect-window.c | 499 +++++++++++++++++++++++++++++++++++++ src/detect-window.h | 16 ++ src/detect.c | 267 ++++++++++++++++++++ src/detect.h | 4 + 10 files changed, 1418 insertions(+) create mode 100755 src/detect-isdataat.c create mode 100755 src/detect-isdataat.h create mode 100644 src/detect-window.c create mode 100644 src/detect-window.h diff --git a/INSTALL b/INSTALL index 02a4a0740a..767979229b 100644 --- a/INSTALL +++ b/INSTALL @@ -1,3 +1,22 @@ + + +For Debian/Ubuntu Users +======================= +After getting the git copy, you will need to get some depends. This +should be enought to get a binary: + + cd your_local_git_branch + sudo apt-get -y install libpcre3 libpcre3-dbg libpcre3-dev build-essential autoconf automake libtool libpcap-dev libnet1-dev libyaml-0-1 libyaml-dev + bash autojunk.sh + ./configure --enable-unittests + sudo mkdir /var/log/eidps/ + cd src + make + ./eidps + +***************** + + Basic Installation ================== diff --git a/src/Makefile.am b/src/Makefile.am index 6f4ecd3cae..fda45245ff 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -28,6 +28,8 @@ pkt-var.c pkt-var.h \ host.c host.h \ detect.c detect.h \ detect-engine.c detect-engine.h \ +detect-isdataat.c detect-isdataat.h \ +detect-window.c detect-window.h \ detect-engine-address.c detect-engine-address.h \ detect-engine-address-ipv4.c detect-engine-address-ipv4.h \ detect-engine-address-ipv6.c detect-engine-address-ipv6.h \ diff --git a/src/detect-content.c b/src/detect-content.c index dade4eb3a2..d0ef0a252a 100644 --- a/src/detect-content.c +++ b/src/detect-content.c @@ -240,6 +240,28 @@ DoDetectContent(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signat } } } + + /* If it has matched, check if it's set a "isdataat" option and process it */ + if( match == 1 && co->flags & DETECT_CONTENT_ISDATAAT_RELATIVE ) + { + /* if the rest of the payload (from the last match) is less than + the "isdataat" there is no data where the rule expected + so match=0 + */ + + #ifdef DEBUG + printf("detect-content: isdataat: payload_len: %u, used %u, rest %u, isdataat? %u\n", p->payload_len, (m->offset + co->content_len),p->payload_len - (m->offset + co->content_len), co->isdataat ); + #endif + if( ! (p->payload_len - (m->offset + co->content_len) >= co->isdataat) ) + match=0; + if(match) + { + #ifdef DEBUG + printf("detect-content: MATCHED\n"); + #endif + } + } + return match; } @@ -458,6 +480,8 @@ void DetectContentFree(void *ptr) { free(cd); } +#ifdef UNITTESTS /* UNITTESTS */ + /** * \test DetectCotentParseTest01 this is a test to make sure we can deal with escaped colons */ @@ -639,10 +663,13 @@ int DetectContentParseTest08 (void) { } +#endif /* UNITTESTS */ + /** * \brief this function registers unit tests for DetectFlow */ void DetectContentRegisterTests(void) { + #ifdef UNITTESTS /* UNITTESTS */ UtRegisterTest("DetectContentParseTest01", DetectContentParseTest01, 1); UtRegisterTest("DetectContentParseTest02", DetectContentParseTest02, 1); UtRegisterTest("DetectContentParseTest03", DetectContentParseTest03, 1); @@ -651,5 +678,7 @@ void DetectContentRegisterTests(void) { UtRegisterTest("DetectContentParseTest06", DetectContentParseTest06, 1); UtRegisterTest("DetectContentParseTest07", DetectContentParseTest07, 1); UtRegisterTest("DetectContentParseTest08", DetectContentParseTest08, 1); + + #endif /* UNITTESTS */ } diff --git a/src/detect-content.h b/src/detect-content.h index d0e69b5e69..28ff6ffceb 100644 --- a/src/detect-content.h +++ b/src/detect-content.h @@ -7,6 +7,7 @@ #define DETECT_CONTENT_DISTANCE_NEXT 0x08 #define DETECT_CONTENT_WITHIN_NEXT 0x10 +#define DETECT_CONTENT_ISDATAAT_RELATIVE 0x16 #define DETECT_CONTENT_RAWBYTES 0x20 @@ -17,6 +18,7 @@ typedef struct DetectContentData_ { uint16_t depth; uint16_t offset; + uint32_t isdataat; int32_t distance; int32_t within; uint8_t flags; diff --git a/src/detect-isdataat.c b/src/detect-isdataat.c new file mode 100755 index 0000000000..4f596dceba --- /dev/null +++ b/src/detect-isdataat.c @@ -0,0 +1,561 @@ +/** + * \file + * \author Pablo Rincon + * + * ISDATAAT part of the detection engine. + */ + +#include + +#include "eidps-common.h" +#include "debug.h" +#include "decode.h" +#include "detect.h" + +#include "util-unittest.h" + +#include "detect-isdataat.h" +#include "detect-content.h" + +#include "flow.h" +#include "flow-var.h" + + +/** + * \brief Regex for parsing our isdataat options + */ +#define PARSE_REGEX "^\\s*([0-9]{1,10})\\s*(,\\s*relative)?\\s*(,\\s*rawbytes\\s*)?\\s*$" + +static pcre *parse_regex; +static pcre_extra *parse_regex_study; + +int DetectIsdataatMatch (ThreadVars *, DetectEngineThreadCtx *, Packet *, Signature *, SigMatch *); +int DetectIsdataatSetup (DetectEngineCtx *, Signature *, SigMatch *, char *); +void DetectIsdataatRegisterTests(void); +void DetectIsdataatFree(void *); + +/** + * \brief Registration function for isdataat: keyword + */ +void DetectIsdataatRegister (void) { + sigmatch_table[DETECT_ISDATAAT].name = "isdataat"; + sigmatch_table[DETECT_ISDATAAT].Match = DetectIsdataatMatch; + sigmatch_table[DETECT_ISDATAAT].Setup = DetectIsdataatSetup; + sigmatch_table[DETECT_ISDATAAT].Free = DetectIsdataatFree; + sigmatch_table[DETECT_ISDATAAT].RegisterTests = DetectIsdataatRegisterTests; + + const char *eb; + int eo; + int opts = 0; + + parse_regex = pcre_compile(PARSE_REGEX, opts, &eb, &eo, NULL); + if(parse_regex == NULL) + { + printf("pcre compile of \"%s\" failed at offset %" PRId32 ": %s\n", PARSE_REGEX, eo, eb); + goto error; + } + + parse_regex_study = pcre_study(parse_regex, 0, &eb); + if(eb != NULL) + { + printf("pcre study failed: %s\n", eb); + goto error; + } + return; + +error: + /* XXX */ + return; +} + +/** + * \brief This function is used to match isdataat on a packet + * \todo We need to add support for rawbytes + * + * \param t pointer to thread vars + * \param det_ctx pointer to the pattern matcher thread + * \param p pointer to the current packet + * \param m pointer to the sigmatch that we will cast into DetectIsdataatData + * + * \retval 0 no match + * \retval 1 match + */ +int DetectIsdataatMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) +{ + DetectIsdataatData *idad = (DetectIsdataatData *)m->ctx; + int ret=0; + + #ifdef DEBUG + printf("detect-isdataat: payload len : %u , dataat? %u ; relative? %u ...\n", p->payload_len,idad->dataat,idad->flags &ISDATAAT_RELATIVE); + #endif + + if(idad->flags & ISDATAAT_RELATIVE) + { + /* Relative to the last matched content, is not performed here */ + #ifdef DEBUG + printf("detect-isdataat: Nothing now, this is checked in detect-content.c!\n"); + #endif + } + else if( !(idad->flags & ISDATAAT_RELATIVE) && p->payload_len >= idad->dataat) { + ret=1; /* its not relative and we have more data in the packet than the offset of isdataat */ + #ifdef DEBUG + printf("detect-isdataat: matched with payload len : %u , dataat? %u ; relative? %u ...\n", p->payload_len,idad->dataat,idad->flags &ISDATAAT_RELATIVE); + #endif + } + + return ret; +} + +/** + * \brief This function is used to parse isdataat options passed via isdataat: keyword + * + * \param isdataatstr Pointer to the user provided isdataat options + * + * \retval idad pointer to DetectIsdataatData on success + * \retval NULL on failure + */ +DetectIsdataatData *DetectIsdataatParse (char *isdataatstr) +{ + DetectIsdataatData *idad = NULL; + char *args[3] = {NULL,NULL,NULL}; +#define MAX_SUBSTRINGS 30 + int ret = 0, res = 0; + int ov[MAX_SUBSTRINGS]; + int i=0; + + ret = pcre_exec(parse_regex, parse_regex_study, isdataatstr, strlen(isdataatstr), 0, 0, ov, MAX_SUBSTRINGS); + if (ret < 1 || ret > 4) { + goto error; + } + + if (ret > 1) { + const char *str_ptr; + res = pcre_get_substring((char *)isdataatstr, ov, MAX_SUBSTRINGS, 1, &str_ptr); + if (res < 0) { + printf("DetectIsdataatParse: pcre_get_substring failed\n"); + goto error; + } + args[0] = (char *)str_ptr; + + + if (ret > 2) { + res = pcre_get_substring((char *)isdataatstr, ov, MAX_SUBSTRINGS, 2, &str_ptr); + if (res < 0) { + printf("DetectIsdataatParse: pcre_get_substring failed\n"); + goto error; + } + args[1] = (char *)str_ptr; + } + if (ret > 3) { + res = pcre_get_substring((char *)isdataatstr, ov, MAX_SUBSTRINGS, 3, &str_ptr); + if (res < 0) { + printf("DetectIsdataatParse: pcre_get_substring failed\n"); + goto error; + } + args[2] = (char *)str_ptr; + } + + idad = malloc(sizeof(DetectIsdataatData)); + if (idad == NULL) { + printf("DetectIsdataatParse malloc failed\n"); + goto error; + } + + idad->flags = 0; + idad->dataat= 0; + + if(args[0] != NULL) + idad->dataat=atoi(args[0]); + + if(idad->dataat < ISDATAAT_MIN || idad->dataat > ISDATAAT_MAX) { + printf("detect-isdataat: DetectIsdataatParse: isdataat out of range\n"); + free(idad); + idad=NULL; + goto error; + } + + if(args[1] !=NULL) + { + idad->flags |= ISDATAAT_RELATIVE; + + if(args[2] !=NULL) + idad->flags |= ISDATAAT_RAWBYTES; + } + + for (i = 0; i < (ret -1); i++){ + if (args[i] != NULL) free(args[i]); + } + + return idad; + + } + +error: + + for (i = 0; i < (ret -1); i++){ + if (args[i] != NULL) free(args[i]); + } + + if (idad != NULL) DetectIsdataatFree(idad); + return NULL; + +} + +/** + * \brief this function is used to add the parsed isdataatdata into the current signature + * + * \param de_ctx pointer to the Detection Engine Context + * \param s pointer to the Current Signature + * \param m pointer to the Current SigMatch + * \param isdataatstr pointer to the user provided isdataat options + * + * \retval 0 on Success + * \retval -1 on Failure + */ +int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char *isdataatstr) +{ + DetectIsdataatData *idad = NULL; + SigMatch *sm = NULL; + SigMatch *search_sm_content = NULL; + DetectContentData *cd = NULL; + + + idad = DetectIsdataatParse(isdataatstr); + if (idad == NULL) goto error; + + if(idad->flags & ISDATAAT_RELATIVE) + { + /// Set it in the last parsed contet because it is relative to that content match + #ifdef DEBUG + printf("detect-isdataat: Set it in the last parsed contet because it is relative to that content match\n"); + #endif + + if( m == NULL ) + { + printf("detect-isdataat: No previous content, the flag 'relative' cant be used without content\n"); + goto error; + } + else + { + search_sm_content=m; + /// Searching last content + uint8_t found=0; + while(search_sm_content != NULL && !found) + { + if(search_sm_content->type== DETECT_CONTENT) //Found content + found=1; + else + search_sm_content=search_sm_content->prev; + } + + if(search_sm_content != NULL) + { + /* Found */ + cd=(DetectContentData*)search_sm_content->ctx; + if(cd != NULL) + { + cd->flags |= DETECT_CONTENT_ISDATAAT_RELATIVE; + cd->isdataat=idad->dataat; + } + else + { + printf("detect-isdataat: No content data found in a SigMatch of DETECT_CONTENT type\n"); + goto error; + } + } + else + { + printf("detect-isdataat: No previous content, the flag 'relative' cant be used without content\n"); + goto error; + } + + } + } + else + { + #ifdef DEBUG + printf("detect-isdataat: Set it as a normal SigMatch\n"); + #endif + /// else Set it as a normal SigMatch + sm = SigMatchAlloc(); + if (sm == NULL) + goto error; + + sm->type = DETECT_ISDATAAT; + sm->ctx = (void *)idad; + + SigMatchAppend(s,m,sm); + } + + return 0; + +error: + if (idad != NULL) DetectIsdataatFree(idad); + if (sm != NULL) free(sm); + return -1; + +} + +/** + * \brief this function will free memory associated with DetectIsdataatData + * + * \param idad pointer to DetectIsdataatData + */ +void DetectIsdataatFree(void *ptr) { + DetectIsdataatData *idad = (DetectIsdataatData *)ptr; + free(idad); +} + + +#ifdef UNITTESTS + +/** + * \test DetectIsdataatTestParse01 is a test to make sure that we return a correct IsdataatData structure + * when given valid isdataat opt + */ +int DetectIsdataatTestParse01 (void) { + int result = 0; + DetectIsdataatData *idad = NULL; + idad = DetectIsdataatParse("30 "); + if (idad != NULL) { + DetectIsdataatFree(idad); + result = 1; + } + + return result; +} + +/** + * \test DetectIsdataatTestParse02 is a test to make sure that we return a correct IsdataatData structure + * when given valid isdataat opt + */ +int DetectIsdataatTestParse02 (void) { + int result = 0; + DetectIsdataatData *idad = NULL; + idad = DetectIsdataatParse("30 , relative"); + if (idad != NULL && idad->flags & ISDATAAT_RELATIVE && !(idad->flags & ISDATAAT_RAWBYTES)) { + DetectIsdataatFree(idad); + result = 1; + } + + return result; +} + +/** + * \test DetectIsdataatTestParse03 is a test to make sure that we return a correct IsdataatData structure + * when given valid isdataat opt + */ +int DetectIsdataatTestParse03 (void) { + int result = 0; + DetectIsdataatData *idad = NULL; + idad = DetectIsdataatParse("30,relative, rawbytes "); + if (idad != NULL && idad->flags & ISDATAAT_RELATIVE && idad->flags & ISDATAAT_RAWBYTES) { + DetectIsdataatFree(idad); + result = 1; + } + + return result; +} + +/** + * \test DetectIsdataatTestPacket01 is a test to check if the packet has data at 50 bytes offset non relative + * + */ + +int DetectIsdataatTestPacket01 (void) { + int result = 0; + DetectIsdataatData *idad = NULL; + + /// Parse Isdataat Data: if packet data len is greater or equal than 50 byte it should match + /// The packet has 190 bytes of data so it must match + idad = DetectIsdataatParse("50"); + if (idad == NULL) + { + printf("DetectIsdataatTestPacket01: expected a DetectIsdataatData pointer (got NULL)\n"); + return 0; + } + /* Buid and decode the packet */ + uint8_t raw_eth [] = { + 0x00,0x25,0x00,0x9e,0xfa,0xfe,0x00,0x02,0xcf,0x74,0xfe,0xe1,0x08,0x00,0x45,0x00 + ,0x01,0xcc,0xcb,0x91,0x00,0x00,0x34,0x06,0xdf,0xa8,0xd1,0x55,0xe3,0x67,0xc0,0xa8 + ,0x64,0x8c,0x00,0x50,0xc0,0xb7,0xd1,0x11,0xed,0x63,0x81,0xa9,0x9a,0x05,0x80,0x18 + ,0x00,0x75,0x0a,0xdd,0x00,0x00,0x01,0x01,0x08,0x0a,0x09,0x8a,0x06,0xd0,0x12,0x21 + ,0x2a,0x3b,0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x33,0x30,0x32,0x20,0x46 + ,0x6f,0x75,0x6e,0x64,0x0d,0x0a,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x3a,0x20 + ,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c + ,0x65,0x2e,0x65,0x73,0x2f,0x0d,0x0a,0x43,0x61,0x63,0x68,0x65,0x2d,0x43,0x6f,0x6e + ,0x74,0x72,0x6f,0x6c,0x3a,0x20,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x0d,0x0a,0x43 + ,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78 + ,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d + ,0x55,0x54,0x46,0x2d,0x38,0x0d,0x0a,0x44,0x61,0x74,0x65,0x3a,0x20,0x4d,0x6f,0x6e + ,0x2c,0x20,0x31,0x34,0x20,0x53,0x65,0x70,0x20,0x32,0x30,0x30,0x39,0x20,0x30,0x38 + ,0x3a,0x34,0x38,0x3a,0x33,0x31,0x20,0x47,0x4d,0x54,0x0d,0x0a,0x53,0x65,0x72,0x76 + ,0x65,0x72,0x3a,0x20,0x67,0x77,0x73,0x0d,0x0a,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74 + ,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x32,0x31,0x38,0x0d,0x0a,0x0d,0x0a + ,0x3c,0x48,0x54,0x4d,0x4c,0x3e,0x3c,0x48,0x45,0x41,0x44,0x3e,0x3c,0x6d,0x65,0x74 + ,0x61,0x20,0x68,0x74,0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x63,0x6f + ,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74 + ,0x65,0x6e,0x74,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x63 + ,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x22,0x3e,0x0a,0x3c + ,0x54,0x49,0x54,0x4c,0x45,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76,0x65,0x64,0x3c + ,0x2f,0x54,0x49,0x54,0x4c,0x45,0x3e,0x3c,0x2f,0x48,0x45,0x41,0x44,0x3e,0x3c,0x42 + ,0x4f,0x44,0x59,0x3e,0x0a,0x3c,0x48,0x31,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76 + ,0x65,0x64,0x3c,0x2f,0x48,0x31,0x3e,0x0a,0x54,0x68,0x65,0x20,0x64,0x6f,0x63,0x75 + ,0x6d,0x65,0x6e,0x74,0x20,0x68,0x61,0x73,0x20,0x6d,0x6f,0x76,0x65,0x64,0x0a,0x3c + ,0x41,0x20,0x48,0x52,0x45,0x46,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77 + ,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x65,0x73,0x2f,0x22,0x3e,0x68 + ,0x65,0x72,0x65,0x3c,0x2f,0x41,0x3e,0x2e,0x0d,0x0a,0x3c,0x2f,0x42,0x4f,0x44,0x59 + ,0x3e,0x3c,0x2f,0x48,0x54,0x4d,0x4c,0x3e,0x0d,0x0a }; + + Packet q; + ThreadVars tv; + DecodeThreadVars dtv; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&q, 0, sizeof(Packet)); + memset(&dtv, 0, sizeof(DecodeThreadVars)); + + FlowInitConfig(FLOW_QUIET); + DecodeEthernet(&tv, &dtv, &q, raw_eth, sizeof(raw_eth), NULL); + FlowShutdown(); + + Packet *p=&q; + + if (!(PKT_IS_TCP(p))) { + printf("detect-window: TestPacket01: Packet is not TCP\n"); + return 0; + } + + + /* We dont need DetectEngineThreadCtx inside DetectIsdataatMatch, its just to pass it to + the function, since this is a test for this option + Also a Signature is not really needed + */ + + DetectEngineThreadCtx *det_ctx=NULL; + Signature *s=NULL; + + /* The data of DetectIsdataatData is retrieved inside DetectIsdataatMatch + from a SigMatch struct, so creating a temporal SigMatch + */ + SigMatch m; + m.ctx=idad; + + /* Now that we have what we need, just try to Match! */ + result=DetectIsdataatMatch (&tv, det_ctx, p, s, &m); + + return result; +} + + +/** + * \test DetectIsdataatTestPacket02 is a test to check if the packet match 6000 bytes offset non relative (it wont) + * + */ + +int DetectIsdataatTestPacket02 (void) { + int result = 0; + DetectIsdataatData *idad = NULL; + + /// Parse Isdataat Data: if packet data len is greater or equal than 6000 byte it should match + /// The packet has 190 bytes of data so it must not match + idad = DetectIsdataatParse("6000"); + if (idad == NULL) + { + printf("DetectIsdataatTestPacket01: expected a DetectIsdataatData pointer (got NULL)\n"); + return 0; + } + /* Buid and decode the packet */ + uint8_t raw_eth [] = { + 0x00,0x25,0x00,0x9e,0xfa,0xfe,0x00,0x02,0xcf,0x74,0xfe,0xe1,0x08,0x00,0x45,0x00 + ,0x01,0xcc,0xcb,0x91,0x00,0x00,0x34,0x06,0xdf,0xa8,0xd1,0x55,0xe3,0x67,0xc0,0xa8 + ,0x64,0x8c,0x00,0x50,0xc0,0xb7,0xd1,0x11,0xed,0x63,0x81,0xa9,0x9a,0x05,0x80,0x18 + ,0x00,0x75,0x0a,0xdd,0x00,0x00,0x01,0x01,0x08,0x0a,0x09,0x8a,0x06,0xd0,0x12,0x21 + ,0x2a,0x3b,0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x33,0x30,0x32,0x20,0x46 + ,0x6f,0x75,0x6e,0x64,0x0d,0x0a,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x3a,0x20 + ,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c + ,0x65,0x2e,0x65,0x73,0x2f,0x0d,0x0a,0x43,0x61,0x63,0x68,0x65,0x2d,0x43,0x6f,0x6e + ,0x74,0x72,0x6f,0x6c,0x3a,0x20,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x0d,0x0a,0x43 + ,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78 + ,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d + ,0x55,0x54,0x46,0x2d,0x38,0x0d,0x0a,0x44,0x61,0x74,0x65,0x3a,0x20,0x4d,0x6f,0x6e + ,0x2c,0x20,0x31,0x34,0x20,0x53,0x65,0x70,0x20,0x32,0x30,0x30,0x39,0x20,0x30,0x38 + ,0x3a,0x34,0x38,0x3a,0x33,0x31,0x20,0x47,0x4d,0x54,0x0d,0x0a,0x53,0x65,0x72,0x76 + ,0x65,0x72,0x3a,0x20,0x67,0x77,0x73,0x0d,0x0a,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74 + ,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x32,0x31,0x38,0x0d,0x0a,0x0d,0x0a + ,0x3c,0x48,0x54,0x4d,0x4c,0x3e,0x3c,0x48,0x45,0x41,0x44,0x3e,0x3c,0x6d,0x65,0x74 + ,0x61,0x20,0x68,0x74,0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x63,0x6f + ,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74 + ,0x65,0x6e,0x74,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x63 + ,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x22,0x3e,0x0a,0x3c + ,0x54,0x49,0x54,0x4c,0x45,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76,0x65,0x64,0x3c + ,0x2f,0x54,0x49,0x54,0x4c,0x45,0x3e,0x3c,0x2f,0x48,0x45,0x41,0x44,0x3e,0x3c,0x42 + ,0x4f,0x44,0x59,0x3e,0x0a,0x3c,0x48,0x31,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76 + ,0x65,0x64,0x3c,0x2f,0x48,0x31,0x3e,0x0a,0x54,0x68,0x65,0x20,0x64,0x6f,0x63,0x75 + ,0x6d,0x65,0x6e,0x74,0x20,0x68,0x61,0x73,0x20,0x6d,0x6f,0x76,0x65,0x64,0x0a,0x3c + ,0x41,0x20,0x48,0x52,0x45,0x46,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77 + ,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x65,0x73,0x2f,0x22,0x3e,0x68 + ,0x65,0x72,0x65,0x3c,0x2f,0x41,0x3e,0x2e,0x0d,0x0a,0x3c,0x2f,0x42,0x4f,0x44,0x59 + ,0x3e,0x3c,0x2f,0x48,0x54,0x4d,0x4c,0x3e,0x0d,0x0a }; + + Packet q; + ThreadVars tv; + DecodeThreadVars dtv; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&q, 0, sizeof(Packet)); + memset(&dtv, 0, sizeof(DecodeThreadVars)); + + FlowInitConfig(FLOW_QUIET); + DecodeEthernet(&tv, &dtv, &q, raw_eth, sizeof(raw_eth), NULL); + FlowShutdown(); + + Packet *p=&q; + + if (!(PKT_IS_TCP(p))) { + printf("detect-window: TestPacket02: Packet is not TCP\n"); + return 0; + } + + + /* We dont need DetectEngineThreadCtx inside DetectIsdataatMatch, its just to pass it to + the function, since this is a test for this option + Also a Signature is not really needed + */ + + DetectEngineThreadCtx *det_ctx=NULL; + Signature *s=NULL; + + /* The data of DetectIsdataatData is retrieved inside DetectIsdataatMatch + from a SigMatch struct, so creating a temporal SigMatch + */ + + SigMatch m; + + m.ctx=idad; + + /* Now that we have what we need, just try to Match! */ + result=DetectIsdataatMatch (&tv, det_ctx, p, s, &m); + + /* Invert it, we dont want this packet to match */ + result=!result; + if(result==0) + printf("detect-isdataat: It has matched with isdataat 6000, expecting not to match\n"); + + return result; +} + +#endif + +/** + * \brief this function registers unit tests for DetectIsdataat + */ +void DetectIsdataatRegisterTests(void) { + #ifdef UNITTESTS + UtRegisterTest("DetectIsdataatTestParse01", DetectIsdataatTestParse01, 1); + UtRegisterTest("DetectIsdataatTestParse02", DetectIsdataatTestParse02, 1); + UtRegisterTest("DetectIsdataatTestParse03", DetectIsdataatTestParse03, 1); + UtRegisterTest("DetectIsdataatTestPacket01", DetectIsdataatTestPacket01, 1); + UtRegisterTest("DetectIsdataatTestPacket02", DetectIsdataatTestPacket02, 1); + #endif +} diff --git a/src/detect-isdataat.h b/src/detect-isdataat.h new file mode 100755 index 0000000000..07f81336c5 --- /dev/null +++ b/src/detect-isdataat.h @@ -0,0 +1,19 @@ +#ifndef __DETECT_ISDATAAT_H__ +#define __DETECT_ISDATAAT_H__ + +#define ISDATAAT_RELATIVE 0x01 +#define ISDATAAT_RAWBYTES 0x02 + +#define ISDATAAT_MIN 0 +#define ISDATAAT_MAX 65535 + +typedef struct DetectIsdataatData_ { + uint32_t dataat; /* data offset to match */ + uint8_t flags; /* isdataat options*/ +} DetectIsdataatData; + +/* prototypes */ +void DetectIsdataatRegister (void); + +#endif /* __DETECT_ISDATAAT_H__ */ + diff --git a/src/detect-window.c b/src/detect-window.c new file mode 100644 index 0000000000..c13ae7cf7b --- /dev/null +++ b/src/detect-window.c @@ -0,0 +1,499 @@ +/** + * \file + * \author Pablo Rincon Crespo + * + * WINDOW tcp window option, part of the detection engine. + */ + +#include + +#include "eidps-common.h" +#include "debug.h" +#include "decode.h" +#include "detect.h" + +#include "detect-window.h" +#include "flow.h" +#include "flow-var.h" + +#include "util-unittest.h" + +/** + * \brief Regex for parsing our window option + */ +#define PARSE_REGEX "^\\s*([!])?\\s*([0-9]{1,9}+)\\s*$" + +static pcre *parse_regex; +static pcre_extra *parse_regex_study; + +int DetectWindowMatch (ThreadVars *, DetectEngineThreadCtx *, Packet *, Signature *, SigMatch *); +int DetectWindowSetup (DetectEngineCtx *, Signature *, SigMatch *, char *); +void DetectWindowRegisterTests(void); +void DetectWindowFree(void *); + +/** + * \brief Registration function for window: keyword + */ +void DetectWindowRegister (void) { + sigmatch_table[DETECT_WINDOW].name = "window"; + sigmatch_table[DETECT_WINDOW].Match = DetectWindowMatch; + sigmatch_table[DETECT_WINDOW].Setup = DetectWindowSetup; + sigmatch_table[DETECT_WINDOW].Free = DetectWindowFree; + sigmatch_table[DETECT_WINDOW].RegisterTests = DetectWindowRegisterTests; + + const char *eb; + int eo; + int opts = 0; + + #ifdef WINDOW_DEBUG + printf("detect-window: Registering window rule option\n"); + #endif + + parse_regex = pcre_compile(PARSE_REGEX, opts, &eb, &eo, NULL); + if(parse_regex == NULL) + { + printf("pcre compile of \"%s\" failed at offset %" PRId32 ": %s\n", PARSE_REGEX, eo, eb); + goto error; + } + + parse_regex_study = pcre_study(parse_regex, 0, &eb); + if(eb != NULL) + { + printf("pcre study failed: %s\n", eb); + goto error; + } + return; + +error: + /* XXX */ + return; +} + +/** + * \brief This function is used to match the window size on a packet + * + * \param t pointer to thread vars + * \param det_ctx pointer to the pattern matcher thread + * \param p pointer to the current packet + * \param m pointer to the sigmatch that we will cast into DetectWindowData + * + * \retval 0 no match + * \retval 1 match + */ +int DetectWindowMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) +{ + int ret=0; + DetectWindowData *wd = (DetectWindowData *)m->ctx; + + if(wd != NULL) + { + + /** + * To match a packet with a widow size rule, we need a TCP packet, + * and we must look if the size is negated or not + */ + if (!(PKT_IS_TCP(p))) { + return 0; + } + + if((!wd->negated && wd->size==TCP_GET_WINDOW(p)) || (wd->negated && wd->size!=TCP_GET_WINDOW(p))) + { + #ifdef WINDOW_DEBUG + printf("detect-window: packet is TCP Proto and matched with packet window size %d and rule option size %d negated: %d!!!\n", TCP_GET_WINDOW(p), wd->size, wd->negated); + #endif + ret=1; + } + } + + return ret; +} + +/** + * \brief This function is used to parse window options passed via window: keyword + * + * \param windowstr Pointer to the user provided window options (negation! and size) + * + * \retval wd pointer to DetectWindowData on success + * \retval NULL on failure + */ +DetectWindowData *DetectWindowParse (char *windowstr) +{ + DetectWindowData *wd = NULL; + char *args[3] = {NULL,NULL,NULL}; /* PR: Why PCRE MAX_SUBSTRING must be multiple of 3? */ + #define MAX_SUBSTRINGS 30 + + int ret = 0, res = 0; + int ov[MAX_SUBSTRINGS]; + + + ret = pcre_exec(parse_regex, parse_regex_study, windowstr, strlen(windowstr), 0, 0, ov, MAX_SUBSTRINGS); + + if (ret < 1 || ret > 3) { + goto error; + } + + wd = malloc(sizeof(DetectWindowData)); + if (wd == NULL) { + printf("DetectWindowParse malloc failed\n"); + goto error; + } + + + if (ret > 1) { + const char *str_ptr; + res = pcre_get_substring((char *)windowstr, ov, MAX_SUBSTRINGS, 1, &str_ptr); + if (res < 0) { + printf("DetectWindowParse: pcre_get_substring failed\n"); + goto error; + } + args[0] = (char *)str_ptr; + /// Detect if it's negated + if(args[0][0]=='!') + wd->negated=1; + else + wd->negated=0; + + #ifdef WINDOW_DEBUG + if(wd->negated) + printf("detect-window: Negation: %s\n", windowstr); + #endif + + if (ret > 2) { + res = pcre_get_substring((char *)windowstr, ov, MAX_SUBSTRINGS, 2, &str_ptr); + if (res < 0) { + printf("DetectWindowParse: pcre_get_substring failed\n"); + goto error; + } + wd->size = atoi((char *)str_ptr); + + /// Get the window size if it's a valid value (in packets, we should alert if this doesn't happend from decode) + + if(wd->sizesize>MAX_WINDOW_VALUE) //If greater than 1GB window + { + goto error; + } + + #ifdef WINDOW_DEBUG + printf("detect-window: window size-> %u\n", wd->size); + #endif + } + } + + int i=0; + for (i = 0; i < (ret -1); i++){ + if (args[i] != NULL) free(args[i]); + } + return wd; + +error: + for (i = 0; i < (ret -1); i++){ + if (args[i] != NULL) free(args[i]); + } + if (wd != NULL) DetectWindowFree(wd); + return NULL; + +} + +/** + * \brief this function is used to add the parsed window sizedata into the current signature + * + * \param de_ctx pointer to the Detection Engine Context + * \param s pointer to the Current Signature + * \param m pointer to the Current SigMatch + * \param windowstr pointer to the user provided window options + * + * \retval 0 on Success + * \retval -1 on Failure + */ +int DetectWindowSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char *windowstr) +{ + DetectWindowData *wd = NULL; + SigMatch *sm = NULL; + + wd = DetectWindowParse(windowstr); + if (wd == NULL) 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_WINDOW; + sm->ctx = (void *)wd; + + SigMatchAppend(s,m,sm); + + return 0; + +error: + if (wd != NULL) DetectWindowFree(wd); + if (sm != NULL) free(sm); + return -1; + +} + +/** + * \brief this function will free memory associated with DetectWindowData + * + * \param wd pointer to DetectWindowData + */ +void DetectWindowFree(void *ptr) { + DetectWindowData *wd = (DetectWindowData *)ptr; + free(wd); +} + +#ifdef UNITTESTS /* UNITTESTS */ + +/** + * \test DetectWindowTestParse01 is a test to make sure that we set the size correctly + * when given valid window opt + */ +int DetectWindowTestParse01 (void) { + int result = 0; + DetectWindowData *wd = NULL; + wd = DetectWindowParse("35402"); + if (wd != NULL &&wd->size==35402) { + DetectWindowFree(wd); + result = 1; + } + + return result; +} + +/** + * \test DetectWindowTestParse02 is a test for setting the window opt negated + */ +int DetectWindowTestParse02 (void) { + int result = 0; + DetectWindowData *wd = NULL; + wd = DetectWindowParse("!35402"); + if (wd != NULL) { + if (wd->negated == 1 && wd->size==35402) { + result = 1; + } else { + printf("expected wd->negated=1 and wd->size=35402\n"); + } + DetectWindowFree(wd); + } + + return result; +} + +/** + * \test DetectWindowTestParse03 is a test to check for an empty value + */ +int DetectWindowTestParse03 (void) { + int result = 0; + DetectWindowData *wd = NULL; + wd = DetectWindowParse(""); + if (wd == NULL) { + result = 1; + } else { + printf("expected a NULL pointer (It was an empty string)\n"); + } + DetectWindowFree(wd); + + return result; +} + +/** + * \test DetectWindowTestParse03 is a test to check for a big value + */ +int DetectWindowTestParse04 (void) { + int result = 0; + DetectWindowData *wd = NULL; + wd = DetectWindowParse("1235402"); + if (wd != NULL) { + printf("expected a NULL pointer (It was exceeding the MAX window size)\n"); + DetectWindowFree(wd); + }else + result=1; + + return result; +} + + +/** + * \test DetectWindowTestPacket01 is a test to check window with constructed packets, expecting to match a negated size + * Parse Window Data: if th_win is not 55455 it should Match! + * The packet is less than 55455 so it must match + */ + +int DetectWindowTestPacket01 (void) { + int result = 0; + DetectWindowData *wd = NULL; + + + wd = DetectWindowParse("!55455"); + if (wd == NULL) + { + printf("DetectWindowTestPacket01: expected a DetectWindowData pointer (got NULL)\n"); + return 0; + } + /* Buid and decode the packet */ + uint8_t raw_eth [] = { + 0x00,0x25,0x00,0x9e,0xfa,0xfe,0x00,0x02,0xcf,0x74,0xfe,0xe1,0x08,0x00,0x45,0x00 + ,0x01,0xcc,0xcb,0x91,0x00,0x00,0x34,0x06,0xdf,0xa8,0xd1,0x55,0xe3,0x67,0xc0,0xa8 + ,0x64,0x8c,0x00,0x50,0xc0,0xb7,0xd1,0x11,0xed,0x63,0x81,0xa9,0x9a,0x05,0x80,0x18 + ,0x00,0x75,0x0a,0xdd,0x00,0x00,0x01,0x01,0x08,0x0a,0x09,0x8a,0x06,0xd0,0x12,0x21 + ,0x2a,0x3b,0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x33,0x30,0x32,0x20,0x46 + ,0x6f,0x75,0x6e,0x64,0x0d,0x0a,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x3a,0x20 + ,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c + ,0x65,0x2e,0x65,0x73,0x2f,0x0d,0x0a,0x43,0x61,0x63,0x68,0x65,0x2d,0x43,0x6f,0x6e + ,0x74,0x72,0x6f,0x6c,0x3a,0x20,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x0d,0x0a,0x43 + ,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78 + ,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d + ,0x55,0x54,0x46,0x2d,0x38,0x0d,0x0a,0x44,0x61,0x74,0x65,0x3a,0x20,0x4d,0x6f,0x6e + ,0x2c,0x20,0x31,0x34,0x20,0x53,0x65,0x70,0x20,0x32,0x30,0x30,0x39,0x20,0x30,0x38 + ,0x3a,0x34,0x38,0x3a,0x33,0x31,0x20,0x47,0x4d,0x54,0x0d,0x0a,0x53,0x65,0x72,0x76 + ,0x65,0x72,0x3a,0x20,0x67,0x77,0x73,0x0d,0x0a,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74 + ,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x32,0x31,0x38,0x0d,0x0a,0x0d,0x0a + ,0x3c,0x48,0x54,0x4d,0x4c,0x3e,0x3c,0x48,0x45,0x41,0x44,0x3e,0x3c,0x6d,0x65,0x74 + ,0x61,0x20,0x68,0x74,0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x63,0x6f + ,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74 + ,0x65,0x6e,0x74,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x63 + ,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x22,0x3e,0x0a,0x3c + ,0x54,0x49,0x54,0x4c,0x45,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76,0x65,0x64,0x3c + ,0x2f,0x54,0x49,0x54,0x4c,0x45,0x3e,0x3c,0x2f,0x48,0x45,0x41,0x44,0x3e,0x3c,0x42 + ,0x4f,0x44,0x59,0x3e,0x0a,0x3c,0x48,0x31,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76 + ,0x65,0x64,0x3c,0x2f,0x48,0x31,0x3e,0x0a,0x54,0x68,0x65,0x20,0x64,0x6f,0x63,0x75 + ,0x6d,0x65,0x6e,0x74,0x20,0x68,0x61,0x73,0x20,0x6d,0x6f,0x76,0x65,0x64,0x0a,0x3c + ,0x41,0x20,0x48,0x52,0x45,0x46,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77 + ,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x65,0x73,0x2f,0x22,0x3e,0x68 + ,0x65,0x72,0x65,0x3c,0x2f,0x41,0x3e,0x2e,0x0d,0x0a,0x3c,0x2f,0x42,0x4f,0x44,0x59 + ,0x3e,0x3c,0x2f,0x48,0x54,0x4d,0x4c,0x3e,0x0d,0x0a }; + + Packet q; + ThreadVars tv; + DecodeThreadVars dtv; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&q, 0, sizeof(Packet)); + memset(&dtv, 0, sizeof(DecodeThreadVars)); + + FlowInitConfig(FLOW_QUIET); + DecodeEthernet(&tv, &dtv, &q, raw_eth, sizeof(raw_eth), NULL); + FlowShutdown(); + + Packet *p=&q; + + if (!(PKT_IS_TCP(p))) { + printf("detect-window: TestPacket01: Packet is not TCP\n"); + return 0; + } + + + /* We dont need DetectEngineThreadCtx inside DetectWindowMatch, its just to pass it to + the function, since this is a test for this option + Also a Signature is not really needed + */ + + DetectEngineThreadCtx *det_ctx=NULL; + Signature *s=NULL; + + SigMatch m; + m.ctx=wd; + + /* Now that we have what we need, just try to Match! */ + result=DetectWindowMatch (&tv, det_ctx, p, s, &m); + + return result; +} + + +/** + * \test DetectWindowTestPacket02 is a test to check window with constructed packets, expecting to match a size + * Parse Window Data: if th_win is 190 it should Match! + * The packet tcp window is 190 so it must match + */ + +int DetectWindowTestPacket02 (void) { + int result = 0; + DetectWindowData *wd = NULL; + + wd = DetectWindowParse("117"); + if (wd == NULL) + { + printf("DetectWindowTestPacket02: expected a DetectWindowData pointer (got NULL)\n"); + return 0; + } + + uint8_t raw_eth [] = { + 0x00,0x25,0x00,0x9e,0xfa,0xfe,0x00,0x02,0xcf,0x74,0xfe,0xe1,0x08,0x00,0x45,0x00 + ,0x01,0xcc,0xcb,0x91,0x00,0x00,0x34,0x06,0xdf,0xa8,0xd1,0x55,0xe3,0x67,0xc0,0xa8 + ,0x64,0x8c,0x00,0x50,0xc0,0xb7,0xd1,0x11,0xed,0x63,0x81,0xa9,0x9a,0x05,0x80,0x18 + ,0x00,0x75,0x0a,0xdd,0x00,0x00,0x01,0x01,0x08,0x0a,0x09,0x8a,0x06,0xd0,0x12,0x21 + ,0x2a,0x3b,0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x33,0x30,0x32,0x20,0x46 + ,0x6f,0x75,0x6e,0x64,0x0d,0x0a,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x3a,0x20 + ,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c + ,0x65,0x2e,0x65,0x73,0x2f,0x0d,0x0a,0x43,0x61,0x63,0x68,0x65,0x2d,0x43,0x6f,0x6e + ,0x74,0x72,0x6f,0x6c,0x3a,0x20,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x0d,0x0a,0x43 + ,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78 + ,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d + ,0x55,0x54,0x46,0x2d,0x38,0x0d,0x0a,0x44,0x61,0x74,0x65,0x3a,0x20,0x4d,0x6f,0x6e + ,0x2c,0x20,0x31,0x34,0x20,0x53,0x65,0x70,0x20,0x32,0x30,0x30,0x39,0x20,0x30,0x38 + ,0x3a,0x34,0x38,0x3a,0x33,0x31,0x20,0x47,0x4d,0x54,0x0d,0x0a,0x53,0x65,0x72,0x76 + ,0x65,0x72,0x3a,0x20,0x67,0x77,0x73,0x0d,0x0a,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74 + ,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x32,0x31,0x38,0x0d,0x0a,0x0d,0x0a + ,0x3c,0x48,0x54,0x4d,0x4c,0x3e,0x3c,0x48,0x45,0x41,0x44,0x3e,0x3c,0x6d,0x65,0x74 + ,0x61,0x20,0x68,0x74,0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x63,0x6f + ,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74 + ,0x65,0x6e,0x74,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x63 + ,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x22,0x3e,0x0a,0x3c + ,0x54,0x49,0x54,0x4c,0x45,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76,0x65,0x64,0x3c + ,0x2f,0x54,0x49,0x54,0x4c,0x45,0x3e,0x3c,0x2f,0x48,0x45,0x41,0x44,0x3e,0x3c,0x42 + ,0x4f,0x44,0x59,0x3e,0x0a,0x3c,0x48,0x31,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76 + ,0x65,0x64,0x3c,0x2f,0x48,0x31,0x3e,0x0a,0x54,0x68,0x65,0x20,0x64,0x6f,0x63,0x75 + ,0x6d,0x65,0x6e,0x74,0x20,0x68,0x61,0x73,0x20,0x6d,0x6f,0x76,0x65,0x64,0x0a,0x3c + ,0x41,0x20,0x48,0x52,0x45,0x46,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77 + ,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x65,0x73,0x2f,0x22,0x3e,0x68 + ,0x65,0x72,0x65,0x3c,0x2f,0x41,0x3e,0x2e,0x0d,0x0a,0x3c,0x2f,0x42,0x4f,0x44,0x59 + ,0x3e,0x3c,0x2f,0x48,0x54,0x4d,0x4c,0x3e,0x0d,0x0a }; + + Packet q; + ThreadVars tv; + DecodeThreadVars dtv; + + memset(&tv, 0, sizeof(ThreadVars)); + memset(&q, 0, sizeof(Packet)); + memset(&dtv, 0, sizeof(DecodeThreadVars)); + + FlowInitConfig(FLOW_QUIET); + DecodeEthernet(&tv, &dtv, &q, raw_eth, sizeof(raw_eth), NULL); + FlowShutdown(); + + Packet *p=&q; + + if (!(PKT_IS_TCP(p))) { + printf("DetectWindowTestPacket02: TestPacket01: Packet is not TCP\n"); + return 0; + } + + + DetectEngineThreadCtx *det_ctx=NULL; + Signature *s=NULL; + SigMatch m; + m.ctx=wd; + + /* Now that we have what we need, just try to Match! */ + result=DetectWindowMatch (&tv, det_ctx, p, s, &m); + + return result; +} + +#endif /* UNITTESTS */ + +/** + * \brief this function registers unit tests for DetectWindow + */ +void DetectWindowRegisterTests(void) { + #ifdef UNITTESTS /* UNITTESTS */ + UtRegisterTest("DetectWindowTestParse01", DetectWindowTestParse01, 1); + UtRegisterTest("DetectWindowTestParse02", DetectWindowTestParse02, 1); + UtRegisterTest("DetectWindowTestParse03", DetectWindowTestParse03, 1); + UtRegisterTest("DetectWindowTestParse04", DetectWindowTestParse04, 1); + UtRegisterTest("DetectWindowTestPacket01" , DetectWindowTestPacket01 , 1); + UtRegisterTest("DetectWindowTestPacket02" , DetectWindowTestPacket02 , 1); + #endif /* UNITTESTS */ +} diff --git a/src/detect-window.h b/src/detect-window.h new file mode 100644 index 0000000000..53c29835f7 --- /dev/null +++ b/src/detect-window.h @@ -0,0 +1,16 @@ +#ifndef __DETECT_WINDOW_H__ +#define __DETECT_WINDOW_H__ + +#define MIN_WINDOW_VALUE 0 +#define MAX_WINDOW_VALUE 65535 + +typedef struct DetectWindowData_ { + uint8_t negated; /** negated? 1=True : 0=False */ + uint32_t size; /** window size to match */ +} DetectWindowData; + +/* prototypes */ +void DetectWindowRegister (void); + +#endif /* __DETECT_WINDOW_H__ */ + diff --git a/src/detect.c b/src/detect.c index 8d65f2ca02..f1f102be49 100644 --- a/src/detect.c +++ b/src/detect.c @@ -40,6 +40,8 @@ #include "detect-msg.h" #include "detect-rev.h" #include "detect-flow.h" +#include "detect-window.h" +#include "detect-isdataat.h" #include "detect-dsize.h" #include "detect-flowvar.h" #include "detect-pktvar.h" @@ -568,6 +570,10 @@ static int SignatureIsIPOnly(DetectEngineCtx *de_ctx, Signature *s) { return 0; } else if (sm->type == DETECT_FLOW) { return 0; + } else if (sm->type == DETECT_WINDOW) { + return 0; + } else if (sm->type == DETECT_ISDATAAT) { + return 0; } else if (sm->type == DETECT_PKTVAR) { return 0; } else if (sm->type == DETECT_FLOWVAR) { @@ -2497,6 +2503,8 @@ void SigTableSetup(void) { DetectDistanceRegister(); DetectOffsetRegister(); DetectFlowRegister(); + DetectWindowRegister(); + DetectIsdataatRegister(); DetectDsizeRegister(); DetectFlowvarRegister(); DetectPktvarRegister(); @@ -5916,6 +5924,253 @@ static int SigTest39Wm (void) { } + +/** + * \test SigTestContentAndIsdataatKeywords01 is a test to check window with constructed packets, + * \brief expecting to match a size + */ + +int SigTestContentAndIsdataatKeywords01Real (int mpm_type) { + int result = 0; + + // Buid and decode the packet + + uint8_t raw_eth [] = { + 0x00,0x25,0x00,0x9e,0xfa,0xfe,0x00,0x02,0xcf,0x74,0xfe,0xe1,0x08,0x00,0x45,0x00 + ,0x01,0xcc,0xcb,0x91,0x00,0x00,0x34,0x06,0xdf,0xa8,0xd1,0x55,0xe3,0x67,0xc0,0xa8 + ,0x64,0x8c,0x00,0x50,0xc0,0xb7,0xd1,0x11,0xed,0x63,0x81,0xa9,0x9a,0x05,0x80,0x18 + ,0x00,0x75,0x0a,0xdd,0x00,0x00,0x01,0x01,0x08,0x0a,0x09,0x8a,0x06,0xd0,0x12,0x21 + ,0x2a,0x3b,0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x33,0x30,0x32,0x20,0x46 + ,0x6f,0x75,0x6e,0x64,0x0d,0x0a,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x3a,0x20 + ,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c + ,0x65,0x2e,0x65,0x73,0x2f,0x0d,0x0a,0x43,0x61,0x63,0x68,0x65,0x2d,0x43,0x6f,0x6e + ,0x74,0x72,0x6f,0x6c,0x3a,0x20,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x0d,0x0a,0x43 + ,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78 + ,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d + ,0x55,0x54,0x46,0x2d,0x38,0x0d,0x0a,0x44,0x61,0x74,0x65,0x3a,0x20,0x4d,0x6f,0x6e + ,0x2c,0x20,0x31,0x34,0x20,0x53,0x65,0x70,0x20,0x32,0x30,0x30,0x39,0x20,0x30,0x38 + ,0x3a,0x34,0x38,0x3a,0x33,0x31,0x20,0x47,0x4d,0x54,0x0d,0x0a,0x53,0x65,0x72,0x76 + ,0x65,0x72,0x3a,0x20,0x67,0x77,0x73,0x0d,0x0a,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74 + ,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x32,0x31,0x38,0x0d,0x0a,0x0d,0x0a + ,0x3c,0x48,0x54,0x4d,0x4c,0x3e,0x3c,0x48,0x45,0x41,0x44,0x3e,0x3c,0x6d,0x65,0x74 + ,0x61,0x20,0x68,0x74,0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x63,0x6f + ,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74 + ,0x65,0x6e,0x74,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x63 + ,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x22,0x3e,0x0a,0x3c + ,0x54,0x49,0x54,0x4c,0x45,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76,0x65,0x64,0x3c + ,0x2f,0x54,0x49,0x54,0x4c,0x45,0x3e,0x3c,0x2f,0x48,0x45,0x41,0x44,0x3e,0x3c,0x42 + ,0x4f,0x44,0x59,0x3e,0x0a,0x3c,0x48,0x31,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76 + ,0x65,0x64,0x3c,0x2f,0x48,0x31,0x3e,0x0a,0x54,0x68,0x65,0x20,0x64,0x6f,0x63,0x75 + ,0x6d,0x65,0x6e,0x74,0x20,0x68,0x61,0x73,0x20,0x6d,0x6f,0x76,0x65,0x64,0x0a,0x3c + ,0x41,0x20,0x48,0x52,0x45,0x46,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77 + ,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x65,0x73,0x2f,0x22,0x3e,0x68 + ,0x65,0x72,0x65,0x3c,0x2f,0x41,0x3e,0x2e,0x0d,0x0a,0x3c,0x2f,0x42,0x4f,0x44,0x59 + ,0x3e,0x3c,0x2f,0x48,0x54,0x4d,0x4c,0x3e,0x0d,0x0a }; + + Packet p; + DecodeThreadVars dtv; + + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + + memset(&p, 0, sizeof(Packet)); + memset(&dtv, 0, sizeof(DecodeThreadVars)); + memset(&th_v, 0, sizeof(th_v)); + + FlowInitConfig(FLOW_QUIET); + DecodeEthernet(&th_v, &dtv, &p, raw_eth, sizeof(raw_eth), NULL); + + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTestContentAndIsdataatKeywords01 \"; content:\"HTTP\"; isdataat:404, relative; sid:101;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, mpm_type); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + if (PacketAlertCheck(&p, 101) == 0) { + result = 0; + goto end; + } else { + result=1; + } + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); + FlowShutdown(); + + return result; + +end: + if(de_ctx) + { + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + } + + if(det_ctx) + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + + PatternMatchDestroy(mpm_ctx); + + if(de_ctx) + DetectEngineCtxFree(de_ctx); + + FlowShutdown(); + + return result; +} + + +/** + * \test SigTestContentAndIsdataatKeywords02 is a test to check window with constructed packets, + * \brief not expecting to match a size + */ + +int SigTestContentAndIsdataatKeywords02Real (int mpm_type) { + int result = 0; + + // Buid and decode the packet + + uint8_t raw_eth [] = { + 0x00,0x25,0x00,0x9e,0xfa,0xfe,0x00,0x02,0xcf,0x74,0xfe,0xe1,0x08,0x00,0x45,0x00 + ,0x01,0xcc,0xcb,0x91,0x00,0x00,0x34,0x06,0xdf,0xa8,0xd1,0x55,0xe3,0x67,0xc0,0xa8 + ,0x64,0x8c,0x00,0x50,0xc0,0xb7,0xd1,0x11,0xed,0x63,0x81,0xa9,0x9a,0x05,0x80,0x18 + ,0x00,0x75,0x0a,0xdd,0x00,0x00,0x01,0x01,0x08,0x0a,0x09,0x8a,0x06,0xd0,0x12,0x21 + ,0x2a,0x3b,0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x31,0x20,0x33,0x30,0x32,0x20,0x46 + ,0x6f,0x75,0x6e,0x64,0x0d,0x0a,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x3a,0x20 + ,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c + ,0x65,0x2e,0x65,0x73,0x2f,0x0d,0x0a,0x43,0x61,0x63,0x68,0x65,0x2d,0x43,0x6f,0x6e + ,0x74,0x72,0x6f,0x6c,0x3a,0x20,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x0d,0x0a,0x43 + ,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65,0x78 + ,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73,0x65,0x74,0x3d + ,0x55,0x54,0x46,0x2d,0x38,0x0d,0x0a,0x44,0x61,0x74,0x65,0x3a,0x20,0x4d,0x6f,0x6e + ,0x2c,0x20,0x31,0x34,0x20,0x53,0x65,0x70,0x20,0x32,0x30,0x30,0x39,0x20,0x30,0x38 + ,0x3a,0x34,0x38,0x3a,0x33,0x31,0x20,0x47,0x4d,0x54,0x0d,0x0a,0x53,0x65,0x72,0x76 + ,0x65,0x72,0x3a,0x20,0x67,0x77,0x73,0x0d,0x0a,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74 + ,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20,0x32,0x31,0x38,0x0d,0x0a,0x0d,0x0a + ,0x3c,0x48,0x54,0x4d,0x4c,0x3e,0x3c,0x48,0x45,0x41,0x44,0x3e,0x3c,0x6d,0x65,0x74 + ,0x61,0x20,0x68,0x74,0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x63,0x6f + ,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74 + ,0x65,0x6e,0x74,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x63 + ,0x68,0x61,0x72,0x73,0x65,0x74,0x3d,0x75,0x74,0x66,0x2d,0x38,0x22,0x3e,0x0a,0x3c + ,0x54,0x49,0x54,0x4c,0x45,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76,0x65,0x64,0x3c + ,0x2f,0x54,0x49,0x54,0x4c,0x45,0x3e,0x3c,0x2f,0x48,0x45,0x41,0x44,0x3e,0x3c,0x42 + ,0x4f,0x44,0x59,0x3e,0x0a,0x3c,0x48,0x31,0x3e,0x33,0x30,0x32,0x20,0x4d,0x6f,0x76 + ,0x65,0x64,0x3c,0x2f,0x48,0x31,0x3e,0x0a,0x54,0x68,0x65,0x20,0x64,0x6f,0x63,0x75 + ,0x6d,0x65,0x6e,0x74,0x20,0x68,0x61,0x73,0x20,0x6d,0x6f,0x76,0x65,0x64,0x0a,0x3c + ,0x41,0x20,0x48,0x52,0x45,0x46,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77 + ,0x77,0x77,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x65,0x73,0x2f,0x22,0x3e,0x68 + ,0x65,0x72,0x65,0x3c,0x2f,0x41,0x3e,0x2e,0x0d,0x0a,0x3c,0x2f,0x42,0x4f,0x44,0x59 + ,0x3e,0x3c,0x2f,0x48,0x54,0x4d,0x4c,0x3e,0x0d,0x0a }; + + Packet p; + DecodeThreadVars dtv; + + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + + memset(&p, 0, sizeof(Packet)); + memset(&dtv, 0, sizeof(DecodeThreadVars)); + memset(&th_v, 0, sizeof(th_v)); + + FlowInitConfig(FLOW_QUIET); + DecodeEthernet(&th_v, &dtv, &p, raw_eth, sizeof(raw_eth), NULL); + + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"SigTestContentAndIsdataatKeywords01 \"; content:\"HTTP\"; isdataat:500, relative; sid:101;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + + SigGroupBuild(de_ctx); + PatternMatchPrepare(mpm_ctx, mpm_type); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + if (PacketAlertCheck(&p, 101) == 0) { + result = 1; + goto end; + } else { + result=0; + } + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + PatternMatchDestroy(mpm_ctx); + DetectEngineCtxFree(de_ctx); + FlowShutdown(); + + return result; + +end: + if(de_ctx) + { + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + } + + if(det_ctx) + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + + PatternMatchDestroy(mpm_ctx); + + if(de_ctx) + DetectEngineCtxFree(de_ctx); + + FlowShutdown(); + + return result; +} + + +// Wrapper functions to pass the mpm_type +static int SigTestContentAndIsdataatKeywords01B2g (void) { + return SigTestContentAndIsdataatKeywords01Real(MPM_B2G); +} +static int SigTestContentAndIsdataatKeywords01B3g (void) { + return SigTestContentAndIsdataatKeywords01Real(MPM_B3G); +} +static int SigTestContentAndIsdataatKeywords01Wm (void) { + return SigTestContentAndIsdataatKeywords01Real(MPM_WUMANBER); +} + +static int SigTestContentAndIsdataatKeywords02B2g (void) { + return SigTestContentAndIsdataatKeywords02Real(MPM_B2G); +} +static int SigTestContentAndIsdataatKeywords02B3g (void) { + return SigTestContentAndIsdataatKeywords02Real(MPM_B3G); +} +static int SigTestContentAndIsdataatKeywords02Wm (void) { + return SigTestContentAndIsdataatKeywords02Real(MPM_WUMANBER); +} + + #endif /* UNITTESTS */ void SigRegisterTests(void) { @@ -6037,6 +6292,18 @@ void SigRegisterTests(void) { UtRegisterTest("SigTest35NegativeICMPV4Keyword", SigTest35NegativeICMPV4Keyword, 1); + /* The following tests check content options with isdataat options + relative to that content match + */ + + UtRegisterTest("SigTestContentAndIsdataatKeywords01B2g", SigTestContentAndIsdataatKeywords01B2g, 1); + UtRegisterTest("SigTestContentAndIsdataatKeywords01B3g", SigTestContentAndIsdataatKeywords01B3g, 1); + UtRegisterTest("SigTestContentAndIsdataatKeywords01Wm" , SigTestContentAndIsdataatKeywords01Wm, 1); + + UtRegisterTest("SigTestContentAndIsdataatKeywords02B2g", SigTestContentAndIsdataatKeywords02B2g, 1); + UtRegisterTest("SigTestContentAndIsdataatKeywords02B3g", SigTestContentAndIsdataatKeywords02B3g, 1); + UtRegisterTest("SigTestContentAndIsdataatKeywords02Wm" , SigTestContentAndIsdataatKeywords02Wm, 1); + /* We need to enable these tests, as soon as we add the ICMPv6 protocol support in our rules engine */ //UtRegisterTest("SigTest36ICMPV6Keyword", SigTest36ICMPV6Keyword, 1); diff --git a/src/detect.h b/src/detect.h index b11fe70704..60de626a51 100644 --- a/src/detect.h +++ b/src/detect.h @@ -374,6 +374,8 @@ typedef struct SigGroupHead_ { /** sigmatch is compatible with a decode event only rule */ #define SIGMATCH_DEONLY_COMPAT 0x04 +/** Remember to add the options in SignatureIsIPOnly() at detect.c otherwise it wont be part of a signature group */ + enum { DETECT_SID, DETECT_PRIORITY, @@ -396,6 +398,8 @@ enum { DETECT_BYTETEST, DETECT_BYTEJUMP, DETECT_FLOW, + DETECT_WINDOW, + DETECT_ISDATAAT, DETECT_DSIZE, DETECT_FLOWVAR, DETECT_PKTVAR,