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
* 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;

@ -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);

Loading…
Cancel
Save