Fixes for distance and within content modifiers.

remotes/origin/master-1.0.x
Victor Julien 16 years ago
parent 884b1034b4
commit 981ca859cb

@ -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 * that turn out to fail being followed by full matches later in the
* packet. This adds some runtime complexity however. * 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 t thread vars
* \param det_ctx thread local data of the detection engine ctx * \param det_ctx thread local data of the detection engine ctx
* \param m match we are inspecting * \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 * \param pktoff packet offset
*/ */
static inline int 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) if (nsm == NULL)
return 1; return 1;
DetectContentData *co = (DetectContentData *)nsm->ctx; /** content match of current pattern */
MpmMatch *nm = det_ctx->mtc.match[co->id].top; 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) { for (; nm; nm = nm->next) {
SCLogDebug("nm->offset %" PRIu32 ", m->offset %" PRIu32 ", pktoff %" PRIu32 "", nm->offset, m->offset, pktoff); 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 (nm->offset >= pktoff) {
if ((!(co->flags & DETECT_CONTENT_WITHIN) || (co->within > 0 && if ((!(nco->flags & DETECT_CONTENT_WITHIN) ||
(nm->offset > m->offset) && (nco->within > 0 && (nm->offset > m->offset) &&
((nm->offset - m->offset) <= co->within)))) (((nm->offset + nco->content_len) - m->offset) <= (nco->within + co->content_len)))))
{ {
SCLogDebug("MATCH: %" PRIu32 " <= WITHIN(%" PRIu32 "), " SCLogDebug("MATCH: %" PRIu32 " <= WITHIN(%" PRIu32 ")",
"nm->offset %" PRIu32 ", m->offset %" PRIu32 "", (nm->offset + nco->content_len) - m->offset,
nm->offset - m->offset, nco->within + co->content_len);
co->within, nm->offset, m->offset);
if (!(nco->flags & DETECT_CONTENT_DISTANCE) ||
if (!(co->flags & DETECT_CONTENT_DISTANCE) || ((nm->offset >= (m->offset + co->content_len)) &&
((nm->offset > m->offset) && ((nm->offset - (m->offset + co->content_len)) >= nco->distance)))
((nm->offset - m->offset) >= co->distance)))
{ {
SCLogDebug("MATCH: %" PRIu32 " >= DISTANCE(%" PRIu32 "), " SCLogDebug("MATCH: %" PRIu32 " >= DISTANCE(%" PRIu32 ")",
"nm->offset %" PRIu32 ", m->offset %" PRIu32 "", nm->offset - (m->offset + co->content_len), nco->distance);
nm->offset - m->offset, co->distance, nm->offset, m->offset);
if (TestOffsetDepth(nm, co, pktoff) == 1) { if (TestOffsetDepth(nm, nco, pktoff) == 1) {
return TestWithinDistanceOffsetDepth(t, det_ctx, nm, nsm->next, pktoff); return TestWithinDistanceOffsetDepth(t, det_ctx, nm, nsm, nsm->next, pktoff);
} }
} else { } else {
SCLogDebug("NO MATCH: %" PRIu32 " >= DISTANCE(%" PRIu32 "), " SCLogDebug("NO MATCH: %" PRIu32 " < DISTANCE(%" PRIu32 ")",
"nm->offset %" PRIu32 ", m->offset %" PRIu32 "", nm->offset - (m->offset + co->content_len), nco->distance);
nm->offset - m->offset, co->distance, nm->offset, m->offset);
} }
} else { } else {
SCLogDebug("NO MATCH: %" PRIu32 " > WITHIN(%" PRIu32 "), " if (nm->offset <= m->offset) {
"nm->offset %" PRIu32 ", m->offset %" PRIu32 "", SCLogDebug("NO MATCH: nm->offset before or on m->offset: %"PRIu32" <= %"PRIu32"",
nm->offset - m->offset, nm->offset, m->offset);
co->within, 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) { if (TestOffsetDepth(m, co, det_ctx->pkt_off) == 1) {
SCLogDebug("TestOffsetDepth returned 1, for co->id %"PRIu32"", co->id); 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) { if (ret == 1) {
SCLogDebug("TestWithinDistanceOffsetDepth returned 1"); SCLogDebug("TestWithinDistanceOffsetDepth returned 1");
det_ctx->pkt_ptr = p->payload + m->offset; det_ctx->pkt_ptr = p->payload + m->offset;

@ -460,6 +460,9 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
det_ctx->pkt_ptr = NULL; det_ctx->pkt_ptr = NULL;
det_ctx->pkt_off = 0; 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) { if (s->flags & SIG_FLAG_RECURSIVE) {
uint8_t rmatch = 0; uint8_t rmatch = 0;
det_ctx->pkt_cnt = 0; det_ctx->pkt_cnt = 0;
@ -2881,12 +2884,12 @@ static int SigTest03Wm (void) {
static int SigTest04Real (int mpm_type) { static int SigTest04Real (int mpm_type) {
uint8_t *buf = (uint8_t *) uint8_t *buf = (uint8_t *)
"GET /one/ HTTP/1.1\r\n" "GET /one/ HTTP/1.1\r\n" /* 20*/
"Host: one.example.org\r\n" "Host: one.example.org\r\n" /* 23, post "Host:" 18 */
"\r\n\r\n" "\r\n\r\n" /* 4 */
"GET /two/ HTTP/1.1\r\n" "GET /two/ HTTP/1.1\r\n" /* 20 */
"Host: two.example.org\r\n" "Host: two.example.org\r\n" /* 23 */
"\r\n\r\n"; "\r\n\r\n"; /* 4 */
uint16_t buflen = strlen((char *)buf); uint16_t buflen = strlen((char *)buf);
Packet p; Packet p;
@ -2910,7 +2913,7 @@ static int SigTest04Real (int mpm_type) {
de_ctx->mpm_matcher = mpm_type; de_ctx->mpm_matcher = mpm_type;
de_ctx->flags |= DE_QUIET; 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) { if (de_ctx->sig_list == NULL) {
result = 0; result = 0;
goto end; goto end;
@ -7583,11 +7586,77 @@ static int SigTestContent04Wm (void) {
return SigTestContent04Real(MPM_WUMANBER); 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) { static int SigTestWithinReal01 (int mpm_type) {
DecodeThreadVars dtv; DecodeThreadVars dtv;
ThreadVars th_v; ThreadVars th_v;
int result = 0; int result = 0;
int alertcnt = 0;
uint8_t rawpkt1[] = { uint8_t rawpkt1[] = {
0x00,0x04,0x76,0xd3,0xd8,0x6a,0x00,0x24, 0x00,0x04,0x76,0xd3,0xd8,0x6a,0x00,0x24,
@ -7706,11 +7775,9 @@ static int SigTestWithinReal01 (int mpm_type) {
memset(&p1, 0, sizeof(Packet)); memset(&p1, 0, sizeof(Packet));
DecodeEthernet(&th_v, &dtv, &p1, rawpkt1, sizeof(rawpkt1), NULL); DecodeEthernet(&th_v, &dtv, &p1, rawpkt1, sizeof(rawpkt1), NULL);
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1); SigMatchSignatures(&th_v, de_ctx, det_ctx, &p1);
if (PacketAlertCheck(&p1, 556)) { if (!(PacketAlertCheck(&p1, 556))) {
//printf("match of sid on packet 1\n"); printf("failed to match on packet 1: ");
alertcnt++; goto end;
}else{
SCLogInfo("failed to match on packet 1");
} }
/* packet 2 */ /* packet 2 */
@ -7718,11 +7785,9 @@ static int SigTestWithinReal01 (int mpm_type) {
memset(&p2, 0, sizeof(Packet)); memset(&p2, 0, sizeof(Packet));
DecodeEthernet(&th_v, &dtv, &p2, rawpkt2, sizeof(rawpkt2), NULL); DecodeEthernet(&th_v, &dtv, &p2, rawpkt2, sizeof(rawpkt2), NULL);
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2); SigMatchSignatures(&th_v, de_ctx, det_ctx, &p2);
if (PacketAlertCheck(&p2, 556)) { if (!(PacketAlertCheck(&p2, 556))) {
//printf("match of sid on packet 2\n"); printf("failed to match on packet 2: ");
alertcnt++; goto end;
}else{
SCLogInfo("failed to match on packet 2");
} }
/* packet 3 */ /* packet 3 */
@ -7730,11 +7795,9 @@ static int SigTestWithinReal01 (int mpm_type) {
memset(&p3, 0, sizeof(Packet)); memset(&p3, 0, sizeof(Packet));
DecodeEthernet(&th_v, &dtv, &p3, rawpkt3, sizeof(rawpkt3), NULL); DecodeEthernet(&th_v, &dtv, &p3, rawpkt3, sizeof(rawpkt3), NULL);
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p3); SigMatchSignatures(&th_v, de_ctx, det_ctx, &p3);
if (PacketAlertCheck(&p3, 556)){ if (!(PacketAlertCheck(&p3, 556))) {
//printf("match of sid on packet 3\n"); printf("failed to match on packet 3: ");
alertcnt++; goto end;
}else{
SCLogInfo("failed to match on packet 3");
} }
/* packet 4 */ /* packet 4 */
@ -7742,11 +7805,9 @@ static int SigTestWithinReal01 (int mpm_type) {
memset(&p4, 0, sizeof(Packet)); memset(&p4, 0, sizeof(Packet));
DecodeEthernet(&th_v, &dtv, &p4, rawpkt4, sizeof(rawpkt4), NULL); DecodeEthernet(&th_v, &dtv, &p4, rawpkt4, sizeof(rawpkt4), NULL);
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p4); SigMatchSignatures(&th_v, de_ctx, det_ctx, &p4);
if (PacketAlertCheck(&p4, 556)){ if (!(PacketAlertCheck(&p4, 556))) {
//printf("match of sid on packet 4\n"); printf("failed to match on packet 4: ");
alertcnt++; goto end;
}else{
SCLogInfo("failed to match on packet 4");
} }
/* packet 5 */ /* packet 5 */
@ -7760,35 +7821,25 @@ static int SigTestWithinReal01 (int mpm_type) {
p5.payload_len = p5buflen; p5.payload_len = p5buflen;
p5.proto = IPPROTO_TCP; p5.proto = IPPROTO_TCP;
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p5); SigMatchSignatures(&th_v, de_ctx, det_ctx, &p5);
if (PacketAlertCheck(&p5, 556)){ if (!(PacketAlertCheck(&p5, 556))) {
//printf("match of sid on packet 5\n"); printf("failed to match on packet 5: ");
alertcnt++; goto end;
}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);
} }
result = 1;
end: end:
if(de_ctx) if (de_ctx != NULL) {
{
SigGroupCleanup(de_ctx); SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx); SigCleanSignatures(de_ctx);
} }
if(det_ctx) if (det_ctx != NULL)
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
if(de_ctx) if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx); DetectEngineCtxFree(de_ctx);
FlowShutdown(); FlowShutdown();
return result; return result;
} }
@ -7985,6 +8036,10 @@ void SigRegisterTests(void) {
UtRegisterTest("SigTestContent04B3g -- 32 byte pattern, x2 + distance/within", SigTestContent04B3g, 1); UtRegisterTest("SigTestContent04B3g -- 32 byte pattern, x2 + distance/within", SigTestContent04B3g, 1);
UtRegisterTest("SigTestContent04Wm -- 32 byte pattern, x2 + distance/within", SigTestContent04Wm, 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("SigTestWithinReal01B2g", SigTestWithinReal01B2g, 1);
UtRegisterTest("SigTestWithinReal01B3g", SigTestWithinReal01B3g, 1); UtRegisterTest("SigTestWithinReal01B3g", SigTestWithinReal01B3g, 1);
UtRegisterTest("SigTestWithinReal01Wm", SigTestWithinReal01Wm, 1); UtRegisterTest("SigTestWithinReal01Wm", SigTestWithinReal01Wm, 1);

Loading…
Cancel
Save