From 7084c68a020f019fba1bd727393b50933ae369e8 Mon Sep 17 00:00:00 2001 From: Anoop Saldanha Date: Tue, 6 Jul 2010 00:24:20 +0530 Subject: [PATCH] implement pcre relative matching in detect-engine-payload.c --- src/detect-engine-payload.c | 156 +++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 150 insertions(+), 6 deletions(-) diff --git a/src/detect-engine-payload.c b/src/detect-engine-payload.c index ce1c0dc..8ee54b0 100644 --- a/src/detect-engine-payload.c +++ b/src/detect-engine-payload.c @@ -39,6 +39,8 @@ #include "util-spm-bm.h" #include "util-debug.h" #include "util-print.h" +#include "pkt-var.h" +#include "flow-var.h" #include "util-unittest.h" #include "util-unittest-helper.h" @@ -74,7 +76,9 @@ static int DoInspectPacketPayload(DetectEngineCtx *de_ctx, { SCEnter(); - if (sm == NULL) { + int punt_matching = 0; + + if (sm == NULL || payload_len == 0) { SCReturnInt(0); } @@ -222,6 +226,10 @@ static int DoInspectPacketPayload(DetectEngineCtx *de_ctx, SCReturnInt(1); } + if (punt_matching == 1) { + SCReturnInt(0); + } + /* set the previous match offset to the start of this match + 1 */ prev_offset = (match_offset - (cd->content_len - 1)); SCLogDebug("trying to see if there is another match after prev_offset %"PRIu32, prev_offset); @@ -229,6 +237,7 @@ static int DoInspectPacketPayload(DetectEngineCtx *de_ctx, } while(1); } + case DETECT_ISDATAAT: { SCLogDebug("inspecting isdataat"); @@ -252,17 +261,124 @@ static int DoInspectPacketPayload(DetectEngineCtx *de_ctx, } } } + case DETECT_PCRE: { SCLogDebug("inspecting pcre"); - int r = DetectPcrePayloadMatch(det_ctx, s, sm, p, f, payload, payload_len); - if (r == 1) { - goto match; - } + DetectPcreData *pd = (DetectPcreData *)sm->ctx; + + /* search for our pattern, checking the matches recursively. + * if we match we look for the next SigMatch as well */ + uint32_t offset = 0; + uint32_t prev_offset = 0; /**< used in recursive searching */ + uint32_t prev_payload_offset = det_ctx->payload_offset; + +#define MAX_SUBSTRINGS 30 + int ov[MAX_SUBSTRINGS]; + uint8_t *ptr = NULL; + uint16_t len = 0; + int ret = 0; + + do { + if (s->flags & SIG_FLAG_RECURSIVE || + pd->flags & DETECT_PCRE_RELATIVE) { + offset = prev_payload_offset; + } else { + offset = 0; + } + + if (prev_offset != 0) { + offset = prev_offset; + } + + ptr = payload + offset; + len = payload_len - offset; + + /* run the actual pcre detection */ + ret = pcre_exec(pd->re, pd->sd, (char *)ptr, len, 0, 0, ov, + MAX_SUBSTRINGS); + SCLogDebug("ret %d (negating %s)", + ret, pd->negate ? "set" : "not set"); + + if (ret == PCRE_ERROR_NOMATCH) { + if (pd->negate == 1) { + /* regex didn't match with negate option means we + * consider it a match */ + SCReturnInt(1); + } else { + /* we have no matches here. if we don't get a pcre match + * here, it's pointless carrying our further matches */ + punt_matching = 1; + SCReturnInt(0); + } + } else if (ret >= 0) { + if (pd->negate == 1) { + punt_matching = 1; + /* regex matched but we're negated, so not + * considering it a match */ + SCReturnInt(0); + } else { + /* regex matched and we're not negated, + * considering it a match */ + + /* see if we need to do substring capturing. */ + if (ret > 1 && pd->capidx != 0) { + const char *str_ptr; + ret = pcre_get_substring((char *)ptr, ov, + MAX_SUBSTRINGS, 1, &str_ptr); + if (ret) { + if (pd->flags & DETECT_PCRE_CAPTURE_PKT) { + /* any more indentation, and we'll + * reach the moon */ + if (p != NULL) { + PktVarAdd(p, pd->capname, + (uint8_t *)str_ptr, ret); + } + } else if (pd->flags & DETECT_PCRE_CAPTURE_FLOW) { + if (f != NULL) { + /* flow will be locked be FlowVarAddStr */ + FlowVarAddStr(f, pd->capidx, + (uint8_t *)str_ptr, ret); + } + } + } /* if (ret) */ + } /* if (ret > 1 && pd->capidx != 0) */ + + /* update offset for pcre RELATIVE */ + det_ctx->payload_offset = (ptr + ov[1]) - payload; + + if ( !(pd->flags & DETECT_PCRE_RELATIVE_NEXT)) { + SCLogDebug("no relative match coming up, so this " + "is a match"); + goto match; + } - SCReturnInt(0); + /* see if the next payload keywords match. If not, we will + * search for another occurence of this pcre and see + * if the others match, until we run out of matches */ + int r = DoInspectPacketPayload(de_ctx, det_ctx, s, + sm->next, p, f, + payload, payload_len); + if (r == 1) { + SCReturnInt(1); + } + + if (punt_matching == 1) { + SCReturnInt(0); + } + + /* set the previous match offset to the start of this match + 1 */ + prev_offset = (ptr + ov[0] + 1) - payload; + } + } else { + SCLogDebug("pcre had matching error"); + punt_matching = 1; + SCReturnInt(0); + } + } while (1); } + case DETECT_BYTETEST: { if (DetectBytetestDoMatch(det_ctx,s,sm,payload,payload_len) != 1) { @@ -271,6 +387,7 @@ static int DoInspectPacketPayload(DetectEngineCtx *de_ctx, goto match; } + case DETECT_BYTEJUMP: { if (DetectBytejumpDoMatch(det_ctx,s,sm,payload,payload_len) != 1) { @@ -279,6 +396,7 @@ static int DoInspectPacketPayload(DetectEngineCtx *de_ctx, goto match; } + /* we should never get here, but bail out just in case */ default: { @@ -538,6 +656,31 @@ end: return result; } +/** + * \test Test pcre recursive matching. + */ +static int PayloadTestSig08(void) +{ + uint8_t *buf = (uint8_t *)"this is a super duper nova in super nova now"; + uint16_t buflen = strlen((char *)buf); + Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP); + int result = 0; + + char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; " + "pcre:/super/; content:nova; within:7; sid:1;)"; + + if (UTHPacketMatchSigMpm(p, sig, MPM_B2G) == 0) { + result = 0; + goto end; + } + + result = 1; +end: + if (p != NULL) + UTHFreePacket(p); + return result; +} + #endif /* UNITTESTS */ void PayloadRegisterTests(void) { @@ -549,5 +692,6 @@ void PayloadRegisterTests(void) { UtRegisterTest("PayloadTestSig05", PayloadTestSig05, 1); UtRegisterTest("PayloadTestSig06", PayloadTestSig06, 1); UtRegisterTest("PayloadTestSig07", PayloadTestSig07, 1); + UtRegisterTest("PayloadTestSig08", PayloadTestSig08, 1); #endif /* UNITTESTS */ } -- 1.7.1