From 981ca859cb686a84ea3aea7deabb13b351c83ee0 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Sat, 7 Nov 2009 14:23:15 +0100 Subject: [PATCH] Fixes for distance and within content modifiers. --- src/detect-content.c | 85 ++++++++++++++++--------- src/detect.c | 147 +++++++++++++++++++++++++++++-------------- 2 files changed, 158 insertions(+), 74 deletions(-) diff --git a/src/detect-content.c b/src/detect-content.c index d5cb31de36..46d380797d 100644 --- a/src/detect-content.c +++ b/src/detect-content.c @@ -89,54 +89,83 @@ TestOffsetDepth(MpmMatch *m, DetectContentData *co, uint16_t pktoff) { * that turn out to fail being followed by full matches later in the * packet. This adds some runtime complexity however. * + * WITHIN + * The within check, if enabled, works as follows. The check is done + * against the current match "m". This is the pattern that we check + * the next against. So we will figure out if the next pattern exists + * within X bytes of "m". + * + * To do this, we take the next pattern (nsm) and loop through all + * matches of it. We then for each of the matches "nm" below, see if + * it is in the within limit. + * + * The within limit is checked as follows. It's checked against the + * current match "m". "m->offset" indicates the start of that match. + * So we need to consider m->offset + co->content_len. This will give + * us the end of the match "m". The next match then needs to occur + * before that point + the lenght of the pattern we're checking, + * nco->content_len. + * * \param t thread vars * \param det_ctx thread local data of the detection engine ctx * \param m match we are inspecting - * \param nsm sigmatch to work with + * \param nm current sigmatch to work with + * \param nsm next sigmatch to work with * \param pktoff packet offset */ static inline int -TestWithinDistanceOffsetDepth(ThreadVars *t, DetectEngineThreadCtx *det_ctx, MpmMatch *m, SigMatch *nsm, uint16_t pktoff) +TestWithinDistanceOffsetDepth(ThreadVars *t, DetectEngineThreadCtx *det_ctx, MpmMatch *m, SigMatch *sm, SigMatch *nsm, uint16_t pktoff) { if (nsm == NULL) return 1; - DetectContentData *co = (DetectContentData *)nsm->ctx; - MpmMatch *nm = det_ctx->mtc.match[co->id].top; + /** content match of current pattern */ + DetectContentData *co = (DetectContentData *)sm->ctx; + /** content match of next pattern */ + DetectContentData *nco = (DetectContentData *)nsm->ctx; + /** list of matches of the next pattern */ + MpmMatch *nm = det_ctx->mtc.match[nco->id].top; + /* recursively check if we have a next pattern that matches */ for (; nm; nm = nm->next) { SCLogDebug("nm->offset %" PRIu32 ", m->offset %" PRIu32 ", pktoff %" PRIu32 "", nm->offset, m->offset, pktoff); + SCLogDebug("nm->offset + nco->content_len = %"PRIu32" + %"PRIu32" = %"PRIu32"", + nm->offset, nco->content_len, nm->offset + nco->content_len); + SCLogDebug("within (0 if disabled) = %"PRIu32" (nco->within %"PRIu32" + co->content_len %"PRIu32")", + nco->flags & DETECT_CONTENT_WITHIN ? (nco->within + co->content_len) : 0, nco->within, co->content_len); if (nm->offset >= pktoff) { - if ((!(co->flags & DETECT_CONTENT_WITHIN) || (co->within > 0 && - (nm->offset > m->offset) && - ((nm->offset - m->offset) <= co->within)))) + if ((!(nco->flags & DETECT_CONTENT_WITHIN) || + (nco->within > 0 && (nm->offset > m->offset) && + (((nm->offset + nco->content_len) - m->offset) <= (nco->within + co->content_len))))) { - SCLogDebug("MATCH: %" PRIu32 " <= WITHIN(%" PRIu32 "), " - "nm->offset %" PRIu32 ", m->offset %" PRIu32 "", - nm->offset - m->offset, - co->within, nm->offset, m->offset); - - if (!(co->flags & DETECT_CONTENT_DISTANCE) || - ((nm->offset > m->offset) && - ((nm->offset - m->offset) >= co->distance))) + SCLogDebug("MATCH: %" PRIu32 " <= WITHIN(%" PRIu32 ")", + (nm->offset + nco->content_len) - m->offset, + nco->within + co->content_len); + + if (!(nco->flags & DETECT_CONTENT_DISTANCE) || + ((nm->offset >= (m->offset + co->content_len)) && + ((nm->offset - (m->offset + co->content_len)) >= nco->distance))) { - SCLogDebug("MATCH: %" PRIu32 " >= DISTANCE(%" PRIu32 "), " - "nm->offset %" PRIu32 ", m->offset %" PRIu32 "", - nm->offset - m->offset, co->distance, nm->offset, m->offset); - if (TestOffsetDepth(nm, co, pktoff) == 1) { - return TestWithinDistanceOffsetDepth(t, det_ctx, nm, nsm->next, pktoff); + SCLogDebug("MATCH: %" PRIu32 " >= DISTANCE(%" PRIu32 ")", + nm->offset - (m->offset + co->content_len), nco->distance); + + if (TestOffsetDepth(nm, nco, pktoff) == 1) { + return TestWithinDistanceOffsetDepth(t, det_ctx, nm, nsm, nsm->next, pktoff); } } else { - SCLogDebug("NO MATCH: %" PRIu32 " >= DISTANCE(%" PRIu32 "), " - "nm->offset %" PRIu32 ", m->offset %" PRIu32 "", - nm->offset - m->offset, co->distance, nm->offset, m->offset); + SCLogDebug("NO MATCH: %" PRIu32 " < DISTANCE(%" PRIu32 ")", + nm->offset - (m->offset + co->content_len), nco->distance); } } else { - SCLogDebug("NO MATCH: %" PRIu32 " > WITHIN(%" PRIu32 "), " - "nm->offset %" PRIu32 ", m->offset %" PRIu32 "", - nm->offset - m->offset, - co->within, nm->offset, m->offset); + if (nm->offset <= m->offset) { + SCLogDebug("NO MATCH: nm->offset before or on m->offset: %"PRIu32" <= %"PRIu32"", + nm->offset, m->offset); + } else { + SCLogDebug("NO MATCH: %" PRIu32 " > WITHIN(%" PRIu32 ")", + (nm->offset + nco->content_len) - m->offset, + (nco->within + co->content_len)); + } } } } @@ -175,7 +204,7 @@ DoDetectContent(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signat if (TestOffsetDepth(m, co, det_ctx->pkt_off) == 1) { SCLogDebug("TestOffsetDepth returned 1, for co->id %"PRIu32"", co->id); - ret = TestWithinDistanceOffsetDepth(t, det_ctx, m, sm->next, det_ctx->pkt_off); + ret = TestWithinDistanceOffsetDepth(t, det_ctx, m, sm, sm->next, det_ctx->pkt_off); if (ret == 1) { SCLogDebug("TestWithinDistanceOffsetDepth returned 1"); det_ctx->pkt_ptr = p->payload + m->offset; diff --git a/src/detect.c b/src/detect.c index 4ed9072cec..4ee2fecfbc 100644 --- a/src/detect.c +++ b/src/detect.c @@ -460,6 +460,9 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh det_ctx->pkt_ptr = NULL; det_ctx->pkt_off = 0; + /* new signature, so reset indicator of checking distance and within */ + det_ctx->de_checking_distancewithin = 0; + if (s->flags & SIG_FLAG_RECURSIVE) { uint8_t rmatch = 0; det_ctx->pkt_cnt = 0; @@ -2881,12 +2884,12 @@ static int SigTest03Wm (void) { static int SigTest04Real (int mpm_type) { uint8_t *buf = (uint8_t *) - "GET /one/ HTTP/1.1\r\n" - "Host: one.example.org\r\n" - "\r\n\r\n" - "GET /two/ HTTP/1.1\r\n" - "Host: two.example.org\r\n" - "\r\n\r\n"; + "GET /one/ HTTP/1.1\r\n" /* 20*/ + "Host: one.example.org\r\n" /* 23, post "Host:" 18 */ + "\r\n\r\n" /* 4 */ + "GET /two/ HTTP/1.1\r\n" /* 20 */ + "Host: two.example.org\r\n" /* 23 */ + "\r\n\r\n"; /* 4 */ uint16_t buflen = strlen((char *)buf); Packet p; @@ -2910,7 +2913,7 @@ static int SigTest04Real (int mpm_type) { de_ctx->mpm_matcher = mpm_type; de_ctx->flags |= DE_QUIET; - de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP TEST\"; content:\"Host:\"; offset:20; depth:25; content:\"Host:\"; distance:47; within:52; sid:1;)"); + de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"HTTP TEST\"; content:\"Host:\"; offset:20; depth:25; content:\"Host:\"; distance:42; within:47; sid:1;)"); if (de_ctx->sig_list == NULL) { result = 0; goto end; @@ -7583,11 +7586,77 @@ static int SigTestContent04Wm (void) { return SigTestContent04Real(MPM_WUMANBER); } +static int SigTestContent05Real (int mpm_type) { + uint8_t *buf = (uint8_t *)"01234567890123456789012345678901abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + uint16_t buflen = strlen((char *)buf); + Packet p; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 0; + + memset(&th_v, 0, sizeof(th_v)); + memset(&p, 0, sizeof(p)); + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = buf; + p.payload_len = buflen; + p.proto = IPPROTO_TCP; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->mpm_matcher = mpm_type; + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"Test 32\"; content:\"01234567890123456789012345678901\"; content:\"abcdefghijklmnopqrstuvwxyzABCDEF\"; distance:0; within:31; sid:1;)"); + if (de_ctx->sig_list == NULL) { + goto end; + } + de_ctx->sig_list->next = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"Test 32\"; content:\"01234567890123456789012345678901\"; content:\"abcdefghijklmnopqrstuvwxyzABCDEF\"; distance:1; within:33; sid:2;)"); + if (de_ctx->sig_list->next == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + + if (PacketAlertCheck(&p, 1)) { + printf("sig 1 matched but shouldn't: "); + goto end; + } + + if (PacketAlertCheck(&p, 2)) { + printf("sig 2 matched but shouldn't: "); + goto end; + } + + result = 1; +end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} +static int SigTestContent05B2g (void) { + return SigTestContent05Real(MPM_B2G); +} +static int SigTestContent05B3g (void) { + return SigTestContent05Real(MPM_B3G); +} +static int SigTestContent05Wm (void) { + return SigTestContent05Real(MPM_WUMANBER); +} + static int SigTestWithinReal01 (int mpm_type) { DecodeThreadVars dtv; ThreadVars th_v; int result = 0; - int alertcnt = 0; uint8_t rawpkt1[] = { 0x00,0x04,0x76,0xd3,0xd8,0x6a,0x00,0x24, @@ -7706,11 +7775,9 @@ static int SigTestWithinReal01 (int mpm_type) { memset(&p1, 0, sizeof(Packet)); DecodeEthernet(&th_v, &dtv, &p1, rawpkt1, sizeof(rawpkt1), NULL); SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); - if (PacketAlertCheck(&p1, 556)) { - //printf("match of sid on packet 1\n"); - alertcnt++; - }else{ - SCLogInfo("failed to match on packet 1"); + if (!(PacketAlertCheck(&p1, 556))) { + printf("failed to match on packet 1: "); + goto end; } /* packet 2 */ @@ -7718,11 +7785,9 @@ static int SigTestWithinReal01 (int mpm_type) { memset(&p2, 0, sizeof(Packet)); DecodeEthernet(&th_v, &dtv, &p2, rawpkt2, sizeof(rawpkt2), NULL); SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); - if (PacketAlertCheck(&p2, 556)) { - //printf("match of sid on packet 2\n"); - alertcnt++; - }else{ - SCLogInfo("failed to match on packet 2"); + if (!(PacketAlertCheck(&p2, 556))) { + printf("failed to match on packet 2: "); + goto end; } /* packet 3 */ @@ -7730,11 +7795,9 @@ static int SigTestWithinReal01 (int mpm_type) { memset(&p3, 0, sizeof(Packet)); DecodeEthernet(&th_v, &dtv, &p3, rawpkt3, sizeof(rawpkt3), NULL); SigMatchSignatures(&th_v, de_ctx, det_ctx, &p3); - if (PacketAlertCheck(&p3, 556)){ - //printf("match of sid on packet 3\n"); - alertcnt++; - }else{ - SCLogInfo("failed to match on packet 3"); + if (!(PacketAlertCheck(&p3, 556))) { + printf("failed to match on packet 3: "); + goto end; } /* packet 4 */ @@ -7742,11 +7805,9 @@ static int SigTestWithinReal01 (int mpm_type) { memset(&p4, 0, sizeof(Packet)); DecodeEthernet(&th_v, &dtv, &p4, rawpkt4, sizeof(rawpkt4), NULL); SigMatchSignatures(&th_v, de_ctx, det_ctx, &p4); - if (PacketAlertCheck(&p4, 556)){ - //printf("match of sid on packet 4\n"); - alertcnt++; - }else{ - SCLogInfo("failed to match on packet 4"); + if (!(PacketAlertCheck(&p4, 556))) { + printf("failed to match on packet 4: "); + goto end; } /* packet 5 */ @@ -7760,35 +7821,25 @@ static int SigTestWithinReal01 (int mpm_type) { p5.payload_len = p5buflen; p5.proto = IPPROTO_TCP; SigMatchSignatures(&th_v, de_ctx, det_ctx, &p5); - if (PacketAlertCheck(&p5, 556)){ - //printf("match of sid on packet 5\n"); - alertcnt++; - }else{ - SCLogInfo("failed to match on packet 5"); - } - - /* do all five packets alert ? */ - if(alertcnt == 5){ - result = 1; - }else{ - SCLogInfo("expected 5 alerts got %i",alertcnt); + if (!(PacketAlertCheck(&p5, 556))) { + printf("failed to match on packet 5: "); + goto end; } + result = 1; end: - if(de_ctx) - { + if (de_ctx != NULL) { SigGroupCleanup(de_ctx); SigCleanSignatures(de_ctx); } - if(det_ctx) + if (det_ctx != NULL) DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); - if(de_ctx) - DetectEngineCtxFree(de_ctx); + if (de_ctx != NULL) + DetectEngineCtxFree(de_ctx); FlowShutdown(); - return result; } @@ -7985,6 +8036,10 @@ void SigRegisterTests(void) { UtRegisterTest("SigTestContent04B3g -- 32 byte pattern, x2 + distance/within", SigTestContent04B3g, 1); UtRegisterTest("SigTestContent04Wm -- 32 byte pattern, x2 + distance/within", SigTestContent04Wm, 1); + UtRegisterTest("SigTestContent05B2g -- distance/within", SigTestContent05B2g, 1); + UtRegisterTest("SigTestContent05B3g -- distance/within", SigTestContent05B3g, 1); + UtRegisterTest("SigTestContent05Wm -- distance/within", SigTestContent05Wm, 1); + UtRegisterTest("SigTestWithinReal01B2g", SigTestWithinReal01B2g, 1); UtRegisterTest("SigTestWithinReal01B3g", SigTestWithinReal01B3g, 1); UtRegisterTest("SigTestWithinReal01Wm", SigTestWithinReal01Wm, 1);