suricata
detect-engine-payload.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2021 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
21 * \author Victor Julien <victor@inliniac.net>
22 *
23 * Performs payload matching functions
24 */
25
26#include "suricata-common.h"
27#include "suricata.h"
28#include "rust.h"
29
30#include "decode.h"
31
32#include "detect.h"
33#include "detect-engine.h"
34#include "detect-parse.h"
37#include "detect-engine-state.h"
39#include "detect-engine-build.h"
40
41#include "stream.h"
42#include "stream-tcp.h"
43
44#include "util-debug.h"
45#include "util-print.h"
46
47#include "util-unittest.h"
49#include "util-validate.h"
50#include "util-profiling.h"
51#include "util-mpm-ac.h"
52
57
58static int StreamMpmFunc(
59 void *cb_data, const uint8_t *data, const uint32_t data_len, const uint64_t _offset)
60{
61 struct StreamMpmData *smd = cb_data;
62 if (data_len >= smd->mpm_ctx->minlen) {
63#ifdef DEBUG
64 smd->det_ctx->stream_mpm_cnt++;
65 smd->det_ctx->stream_mpm_size += data_len;
66#endif
67 (void)mpm_table[smd->mpm_ctx->mpm_type].Search(
68 smd->mpm_ctx, &smd->det_ctx->mtc, &smd->det_ctx->pmq, data, data_len);
70 }
71 return 0;
72}
73
74static void PrefilterPktStream(DetectEngineThreadCtx *det_ctx,
75 Packet *p, const void *pectx)
76{
77 SCEnter();
78
79 const MpmCtx *mpm_ctx = (MpmCtx *)pectx;
80
81 /* for established packets inspect any stream we may have queued up */
83 SCLogDebug("PRE det_ctx->raw_stream_progress %"PRIu64,
85 struct StreamMpmData stream_mpm_data = { det_ctx, mpm_ctx };
87 StreamMpmFunc, &stream_mpm_data,
89 false /* mpm doesn't use min inspect depth */);
90 SCLogDebug("POST det_ctx->raw_stream_progress %"PRIu64,
92
93 /* packets that have not been added to the stream will be inspected as if they are stream
94 * chunks */
95 } else if ((p->flags & (PKT_NOPAYLOAD_INSPECTION | PKT_STREAM_ADD)) == 0) {
96 if (p->payload_len >= mpm_ctx->minlen) {
97#ifdef DEBUG
98 det_ctx->payload_mpm_cnt++;
99 det_ctx->payload_mpm_size += p->payload_len;
100#endif
102 &det_ctx->mtc, &det_ctx->pmq,
103 p->payload, p->payload_len);
105 }
106 }
107}
108
111{
113 PrefilterPktStream, mpm_ctx, NULL, "stream");
114}
115
116static void PrefilterPktPayload(DetectEngineThreadCtx *det_ctx,
117 Packet *p, const void *pectx)
118{
119 SCEnter();
120
121 const MpmCtx *mpm_ctx = (MpmCtx *)pectx;
122 if (p->payload_len < mpm_ctx->minlen)
123 SCReturn;
124
126 &det_ctx->mtc, &det_ctx->pmq,
127 p->payload, p->payload_len);
128
130}
131
134{
136 PrefilterPktPayload, mpm_ctx, NULL, "payload");
137}
138
139
140/**
141 * \brief Do the content inspection & validation for a signature
142 *
143 * \param de_ctx Detection engine context
144 * \param det_ctx Detection engine thread context
145 * \param s Signature to inspect
146 * \param f flow (for pcre flowvar storage)
147 * \param p Packet
148 *
149 * \retval 0 no match
150 * \retval 1 match
151 */
153 const Signature *s, Flow *f, Packet *p)
154{
155 SCEnter();
156
157 if (s->sm_arrays[DETECT_SM_LIST_PMATCH] == NULL) {
158 SCReturnInt(0);
159 }
160#ifdef DEBUG
161 det_ctx->payload_persig_cnt++;
162 det_ctx->payload_persig_size += p->payload_len;
163#endif
164 const bool match = DetectEngineContentInspection(de_ctx, det_ctx, s,
167 if (match) {
168 SCReturnInt(1);
169 }
170 SCReturnInt(0);
171}
172
173/**
174 * \brief Do the content inspection & validation for a sigmatch list
175 *
176 * \param de_ctx Detection engine context
177 * \param det_ctx Detection engine thread context
178 * \param s Signature to inspect
179 * \param smd array of matches to eval
180 * \param f flow (for pcre flowvar storage)
181 * \param p Packet
182 *
183 * \retval 0 no match
184 * \retval 1 match
185 */
186static uint8_t DetectEngineInspectStreamUDPPayload(DetectEngineCtx *de_ctx,
187 DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Flow *f,
188 Packet *p)
189{
190 SCEnter();
191
192 if (smd == NULL) {
193 SCReturnInt(0);
194 }
195#ifdef DEBUG
196 det_ctx->payload_persig_cnt++;
197 det_ctx->payload_persig_size += p->payload_len;
198#endif
199 const bool match =
202 if (match) {
203 SCReturnInt(1);
204 }
205 SCReturnInt(0);
206}
207
214
215static int StreamContentInspectFunc(
216 void *cb_data, const uint8_t *data, const uint32_t data_len, const uint64_t _offset)
217{
218 SCEnter();
219 struct StreamContentInspectData *smd = cb_data;
220#ifdef DEBUG
221 smd->det_ctx->stream_persig_cnt++;
222 smd->det_ctx->stream_persig_size += data_len;
223#endif
224
225 const bool match = DetectEngineContentInspection(smd->de_ctx, smd->det_ctx, smd->s,
226 smd->s->sm_arrays[DETECT_SM_LIST_PMATCH], NULL, smd->f, data, data_len, 0,
227 0, // TODO
229 if (match) {
230 SCReturnInt(1);
231 }
232
233 SCReturnInt(0);
234}
235
236/**
237 * \brief Do the content inspection & validation for a signature
238 * on the raw stream
239 *
240 * \param de_ctx Detection engine context
241 * \param det_ctx Detection engine thread context
242 * \param s Signature to inspect
243 * \param f flow (for pcre flowvar storage)
244 *
245 * \retval 0 no match
246 * \retval 1 match
247 */
250 Flow *f, Packet *p)
251{
252 SCEnter();
253 SCLogDebug("FLUSH? %s", (s->flags & SIG_FLAG_FLUSH)?"true":"false");
254 uint64_t unused;
255 struct StreamContentInspectData inspect_data = { de_ctx, det_ctx, s, f };
256 int r = StreamReassembleRaw(f->protoctx, p,
257 StreamContentInspectFunc, &inspect_data,
258 &unused, ((s->flags & SIG_FLAG_FLUSH) != 0));
259 return r;
260}
261
269
270static int StreamContentInspectEngineFunc(
271 void *cb_data, const uint8_t *data, const uint32_t data_len, const uint64_t _offset)
272{
273 SCEnter();
274 struct StreamContentInspectEngineData *smd = cb_data;
275#ifdef DEBUG
276 smd->det_ctx->stream_persig_cnt++;
277 smd->det_ctx->stream_persig_size += data_len;
278#endif
279
280 const bool match = DetectEngineContentInspection(smd->de_ctx, smd->det_ctx, smd->s, smd->smd,
281 NULL, smd->f, data, data_len, 0, 0, // TODO
283 if (match) {
284 SCReturnInt(1);
285 }
286
287 SCReturnInt(0);
288}
289
290/**
291 * \brief inspect engine for stateful rules
292 *
293 * Caches results as it may be called multiple times if we inspect
294 * multiple transactions in one packet.
295 *
296 * Returns "can't match" if depth is reached.
297 */
299 const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f,
300 uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
301{
302 Packet *p = det_ctx->p; /* TODO: get rid of this HACK */
303
304 /* in certain sigs, e.g. 'alert dns', which apply to both tcp and udp
305 * we can get called for UDP. Then we simply inspect the packet payload */
306 if (p->proto == IPPROTO_UDP) {
307 return DetectEngineInspectStreamUDPPayload(de_ctx, det_ctx, s, engine->smd, f, p);
308 /* for other non-TCP protocols we assume match */
309 } else if (p->proto != IPPROTO_TCP)
311
312 TcpSession *ssn = f->protoctx;
313 if (ssn == NULL)
315
316 SCLogDebug("pre-inspect det_ctx->raw_stream_progress %"PRIu64" FLUSH? %s",
318 (s->flags & SIG_FLAG_FLUSH)?"true":"false");
319 uint64_t unused;
320 struct StreamContentInspectEngineData inspect_data = { de_ctx, det_ctx, s, engine->smd, f };
321 int match = StreamReassembleRaw(f->protoctx, p,
322 StreamContentInspectEngineFunc, &inspect_data,
323 &unused, ((s->flags & SIG_FLAG_FLUSH) != 0));
324
325 bool is_last = false;
326 if (flags & STREAM_TOSERVER) {
327 TcpStream *stream = &ssn->client;
329 is_last = true;
330 } else {
331 TcpStream *stream = &ssn->server;
333 is_last = true;
334 }
335
336 SCLogDebug("%s ran stream for sid %u on packet %"PRIu64" and we %s",
337 is_last? "LAST:" : "normal:", s->id, p->pcap_cnt,
338 match ? "matched" : "didn't match");
339
340 if (match) {
342 } else {
343 if (is_last) {
344 //SCLogNotice("last, so DETECT_ENGINE_INSPECT_SIG_CANT_MATCH");
346 }
347 /* TODO maybe we can set 'CANT_MATCH' for EOF too? */
349 }
350}
351
352#ifdef UNITTESTS
353#include "detect-engine-alert.h"
354
355/** \test Not the first but the second occurrence of "abc" should be used
356 * for the 2nd match */
357static int PayloadTestSig01 (void)
358{
359 uint8_t *buf = (uint8_t *)
360 "abcabcd";
361 uint16_t buflen = strlen((char *)buf);
362 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
363
364 FAIL_IF_NULL(p);
365
366 char sig[] = "alert tcp any any -> any any (content:\"abc\"; content:\"d\"; distance:0; within:1; sid:1;)";
367
369
370 UTHFreePacket(p);
371
372 PASS;
373}
374
375/** \test Nocase matching */
376static int PayloadTestSig02 (void)
377{
378 uint8_t *buf = (uint8_t *)
379 "abcaBcd";
380 uint16_t buflen = strlen((char *)buf);
381 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
382
383 FAIL_IF_NULL(p);
384
385 char sig[] = "alert tcp any any -> any any (content:\"abc\"; nocase; content:\"d\"; distance:0; within:1; sid:1;)";
386
388
389 UTHFreePacket(p);
390
391 PASS;
392}
393
394/** \test Negative distance matching */
395static int PayloadTestSig03 (void)
396{
397 uint8_t *buf = (uint8_t *)
398 "abcaBcd";
399 uint16_t buflen = strlen((char *)buf);
400 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
401
402 FAIL_IF_NULL(p);
403
404 char sig[] = "alert tcp any any -> any any (content:\"aBc\"; nocase; content:\"abca\"; distance:-10; within:4; sid:1;)";
405
407
408 UTHFreePacket(p);
409
410 PASS;
411}
412
413/**
414 * \test Test multiple relative matches.
415 */
416static int PayloadTestSig04(void)
417{
418 uint8_t *buf = (uint8_t *)"now this is is big big string now";
419 uint16_t buflen = strlen((char *)buf);
420 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
421
422 FAIL_IF_NULL(p);
423
424 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
425 "content:\"this\"; content:\"is\"; within:6; content:\"big\"; within:8; "
426 "content:\"string\"; within:8; sid:1;)";
427
429
430 UTHFreePacket(p);
431
432 PASS;
433}
434
435/**
436 * \test Test multiple relative matches.
437 */
438static int PayloadTestSig05(void)
439{
440 uint8_t *buf = (uint8_t *)"now this is is is big big big string now";
441 uint16_t buflen = strlen((char *)buf);
442 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
443
444 FAIL_IF_NULL(p);
445
446 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
447 "content:\"this\"; content:\"is\"; within:9; content:\"big\"; within:12; "
448 "content:\"string\"; within:8; sid:1;)";
449
451
452 UTHFreePacket(p);
453
454 PASS;
455}
456
457/**
458 * \test Test multiple relative matches.
459 */
460static int PayloadTestSig06(void)
461{
462 uint8_t *buf = (uint8_t *)"this this now is is big string now";
463 uint16_t buflen = strlen((char *)buf);
464 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
465
466 FAIL_IF_NULL(p);
467
468 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
469 "content:\"now\"; content:\"this\"; content:\"is\"; within:12; content:\"big\"; within:8; "
470 "content:\"string\"; within:8; sid:1;)";
471
473
474 UTHFreePacket(p);
475
476 PASS;
477}
478
479/**
480 * \test Test multiple relative matches.
481 */
482static int PayloadTestSig07(void)
483{
484 uint8_t *buf = (uint8_t *)" thus thus is a big";
485 uint16_t buflen = strlen((char *)buf);
486 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
487
488 FAIL_IF_NULL(p);
489
490 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
491 "content:\"thus\"; offset:8; content:\"is\"; within:6; content:\"big\"; within:8; sid:1;)";
492
494
495 UTHFreePacket(p);
496
497 PASS;
498}
499
500/**
501 * \test Test multiple relative matches with negative matches
502 * and show the need for det_ctx->discontinue_matching.
503 */
504static int PayloadTestSig08(void)
505{
506 uint8_t *buf = (uint8_t *)"we need to fix this and yes fix this now";
507 uint16_t buflen = strlen((char *)buf);
508 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
509
510 FAIL_IF_NULL(p);
511
512 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
513 "content:\"fix\"; content:\"this\"; within:6; content:!\"and\"; distance:0; sid:1;)";
514
516
517 UTHFreePacket(p);
518
519 PASS;
520}
521
522/**
523 * \test Test pcre recursive matching.
524 */
525static int PayloadTestSig09(void)
526{
527 uint8_t *buf = (uint8_t *)"this is a super duper nova in super nova now";
528 uint16_t buflen = strlen((char *)buf);
529 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
530
531 FAIL_IF_NULL(p);
532
533 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
534 "pcre:/super/; content:\"nova\"; within:7; sid:1;)";
535
537
538 UTHFreePacket(p);
539
540 PASS;
541}
542
543/**
544 * \test Test invalid sig.
545 */
546static int PayloadTestSig10(void)
547{
548 uint8_t *buf = (uint8_t *)"this is a super duper nova in super nova now";
549 uint16_t buflen = strlen((char *)buf);
550 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
551
552 FAIL_IF_NULL(p);
553
554 char sig[] = "alert udp any any -> any any (msg:\"crash\"; "
555 "byte_test:4,>,2,0,relative; sid:11;)";
556
558
559 UTHFreePacket(p);
560
561 PASS;
562}
563
564/**
565 * \test Test invalid sig.
566 */
567static int PayloadTestSig11(void)
568{
569 uint8_t *buf = (uint8_t *)"this is a super duper nova in super nova now";
570 uint16_t buflen = strlen((char *)buf);
571 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
572
573 FAIL_IF_NULL(p);
574
575 char sig[] = "alert udp any any -> any any (msg:\"crash\"; "
576 "byte_jump:1,0,relative; sid:11;)";
577
579
580 UTHFreePacket(p);
581
582 PASS;
583}
584
585/**
586 * \test Test invalid sig.
587 */
588static int PayloadTestSig12(void)
589{
590 uint8_t *buf = (uint8_t *)"this is a super duper nova in super nova now";
591 uint16_t buflen = strlen((char *)buf);
592 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
593
594 FAIL_IF_NULL(p);
595
596 char sig[] = "alert udp any any -> any any (msg:\"crash\"; "
597 "isdataat:10,relative; sid:11;)";
598
600
601 UTHFreePacket(p);
602
603 PASS;
604}
605
606/**
607 * \test Used to check the working of recursion_limit counter.
608 */
609static int PayloadTestSig13(void)
610{
611 uint8_t *buf = (uint8_t *)"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
612 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
613 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
614 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
615 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
616 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
617 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
618 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
619 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
620 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
621 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
622 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
623 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
624 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
626 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
627 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
628 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
629 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
630 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
631
632 uint16_t buflen = strlen((char *)buf);
633 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
634 uint16_t mpm_type = mpm_default_matcher;
635
636 FAIL_IF_NULL(p);
637
638 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
639 "content:\"aa\"; content:\"aa\"; distance:0; content:\"aa\"; distance:0; "
640 "byte_test:1,>,200,0,relative; sid:1;)";
641
643 ThreadVars th_v;
645
646 memset(&dtv, 0, sizeof(DecodeThreadVars));
647 memset(&th_v, 0, sizeof(th_v));
648
651
653
655 de_ctx->mpm_matcher = mpm_type;
656
657 de_ctx->sig_list = SigInit(de_ctx, sig);
659
661 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
662
664
666
667 DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
669
670 UTHFreePacket(p);
671
672 PASS;
673}
674
675/**
676 * \test normal & negated matching, both absolute and relative
677 */
678static int PayloadTestSig14(void)
679{
680 uint8_t *buf = (uint8_t *)"User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b4) Gecko/20090423 Firefox/3.6 GTB5";
681 uint16_t buflen = strlen((char *)buf);
682 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
683
684 FAIL_IF_NULL(p);
685
686 char sig[] = "alert tcp any any -> any any (content:\"User-Agent|3A| Mozilla/5.0 |28|Macintosh|3B| \"; content:\"Firefox/3.\"; distance:0; content:!\"Firefox/3.6.12\"; distance:-10; content:!\"Mozilla/5.0 |28|Macintosh|3B| U|3B| Intel Mac OS X 10.5|3B| en-US|3B| rv|3A|1.9.1b4|29| Gecko/20090423 Firefox/3.6 GTB5\"; sid:1; rev:1;)";
687
688 //char sig[] = "alert tcp any any -> any any (content:\"User-Agent: Mozilla/5.0 (Macintosh; \"; content:\"Firefox/3.\"; distance:0; content:!\"Firefox/3.6.12\"; distance:-10; content:!\"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b4) Gecko/20090423 Firefox/3.6 GTB5\"; sid:1; rev:1;)";
689
691
692 UTHFreePacket(p);
693
694 PASS;
695}
696
697static int PayloadTestSig15(void)
698{
699 uint8_t *buf = (uint8_t *)"this is a super duper nova in super nova now";
700 uint16_t buflen = strlen((char *)buf);
701 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
702
703 FAIL_IF_NULL(p);
704
705 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
706 "content:\"nova\"; isdataat:18,relative; sid:1;)";
707
709
710 UTHFreePacket(p);
711
712 PASS;
713}
714
715static int PayloadTestSig16(void)
716{
717 uint8_t *buf = (uint8_t *)"this is a super duper nova in super nova now";
718 uint16_t buflen = strlen((char *)buf);
719 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
720
721 FAIL_IF_NULL(p);
722
723 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
724 "content:\"nova\"; isdataat:!20,relative; sid:1;)";
725
727
728 UTHFreePacket(p);
729
730 PASS;
731}
732
733static int PayloadTestSig17(void)
734{
735 uint8_t buf[] = { 0xEB, 0x29, 0x25, 0x38, 0x78, 0x25, 0x38, 0x78, 0x25 };
736 uint16_t buflen = 9;
737 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
738
739 FAIL_IF_NULL(p);
740
741 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
742 "content:\"%\"; depth:4; offset:0; "
743 "content:\"%\"; within:2; distance:1; sid:1;)";
744
746
747 UTHFreePacket(p);
748
749 PASS;
750}
751
752static int PayloadTestSig18(void)
753{
754 uint8_t buf[] = {
755 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x35, /* the last byte is 2 */
756 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
757 0x0E, 0x0F,
758 };
759 uint16_t buflen = sizeof(buf);
760 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
761
762 FAIL_IF_NULL(p);
763
764 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
765 "content:\"|01 02 03 04|\"; "
766 "byte_extract:1,2,one,string,dec,relative; "
767 "content:\"|0C 0D 0E 0F|\"; distance:one; sid:1;)";
768
770
771 UTHFreePacket(p);
772
773 PASS;
774}
775
776static int PayloadTestSig19(void)
777{
778 uint8_t buf[] = {
779 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x35, /* the last byte is 2 */
780 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
781 0x0E, 0x0F,
782 };
783 uint16_t buflen = sizeof(buf);
784 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
785
786 FAIL_IF_NULL(p);
787
788 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
789 "content:\"|01 02 03 04|\"; "
790 "byte_extract:1,2,one,string,hex,relative; "
791 "content:\"|0C 0D 0E 0F|\"; distance:one; sid:1;)";
792
794
795 UTHFreePacket(p);
796
797 PASS;
798}
799
800static int PayloadTestSig20(void)
801{
802 uint8_t buf[] = {
803 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x35, /* the last byte is 2 */
804 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
805 0x0E, 0x0F,
806 };
807 uint16_t buflen = sizeof(buf);
808 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
809
810 FAIL_IF_NULL(p);
811
812 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
813 "content:\"|01 02 03 04|\"; "
814 "byte_extract:1,2,one,string,dec,relative; "
815 "content:\"|06 35 07 08|\"; offset:one; sid:1;)";
816
818
819 UTHFreePacket(p);
820
821 PASS;
822}
823
824static int PayloadTestSig21(void)
825{
826 uint8_t buf[] = {
827 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x36, /* the last byte is 2 */
828 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
829 0x0E, 0x0F,
830 };
831 uint16_t buflen = sizeof(buf);
832 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
833
834 FAIL_IF_NULL(p);
835
836 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
837 "content:\"|01 02 03 04|\"; "
838 "byte_extract:1,2,one,string,dec,relative; "
839 "content:\"|03 04 05 06|\"; depth:one; sid:1;)";
840
842
843 UTHFreePacket(p);
844
845 PASS;
846}
847
848static int PayloadTestSig22(void)
849{
850 uint8_t buf[] = {
851 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x36, /* the last byte is 2 */
852 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
853 0x0E, 0x0F,
854 };
855 uint16_t buflen = sizeof(buf);
856 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
857
858 FAIL_IF_NULL(p);
859
860 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
861 "content:\"|01 02 03 04|\"; "
862 "byte_extract:1,2,one,string,dec,relative; "
863 "content:\"|09 0A 0B 0C|\"; within:one; sid:1;)";
864
866
867 UTHFreePacket(p);
868
869 PASS;
870}
871
872static int PayloadTestSig23(void)
873{
874 uint8_t buf[] = {
875 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x32, /* the last byte is 2 */
876 0x07, 0x08, 0x09, 0x33, 0x0B, 0x0C, 0x0D,
877 0x32, 0x0F,
878 };
879 uint16_t buflen = sizeof(buf);
880 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
881
882 FAIL_IF_NULL(p);
883
884 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
885 "content:\"|01 02 03 04|\"; "
886 "byte_extract:1,2,one,string,dec,relative; "
887 "byte_extract:1,3,two,string,dec,relative; "
888 "byte_test:1,=,one,two,string,dec,relative; sid:1;)";
889
891
892 UTHFreePacket(p);
893
894 PASS;
895}
896
897static int PayloadTestSig24(void)
898{
899 uint8_t buf[] = {
900 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x32, /* the last byte is 2 */
901 0x07, 0x08, 0x33, 0x0A, 0x0B, 0x0C, 0x0D,
902 0x0E, 0x0F,
903 };
904 uint16_t buflen = sizeof(buf);
905 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
906
907 FAIL_IF_NULL(p);
908
909 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
910 "content:\"|01 02 03 04|\"; "
911 "byte_extract:1,2,one,string,dec,relative; "
912 "byte_jump:1,one,string,dec,relative; "
913 "content:\"|0D 0E 0F|\"; distance:0; sid:1;)";
914
916
917 UTHFreePacket(p);
918
919 PASS;
920}
921
922/*
923 * \test Test negative byte extract.
924 */
925static int PayloadTestSig25(void)
926{
927 uint8_t buf[] = {
928 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x35, /* the last byte is 2 */
929 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
930 0x0E, 0x0F,
931 };
932 uint16_t buflen = sizeof(buf);
933 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
934
935 FAIL_IF_NULL(p);
936
937 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
938 "content:\"|35 07 08 09|\"; "
939 "byte_extract:1,-4,one,string,dec,relative; "
940 "content:\"|0C 0D 0E 0F|\"; distance:one; sid:1;)";
941
943
944 UTHFreePacket(p);
945
946 PASS;
947}
948
949/*
950 * \test Test negative byte extract.
951 */
952static int PayloadTestSig26(void)
953{
954 uint8_t buf[] = {
955 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x35, /* the last byte is 2 */
956 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
957 0x0E, 0x0F,
958 };
959 uint16_t buflen = sizeof(buf);
960 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
961
962 FAIL_IF_NULL(p);
963
964 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
965 "content:\"|35 07 08 09|\"; "
966 "byte_extract:1,-3000,one,string,dec,relative; "
967 "content:\"|0C 0D 0E 0F|\"; distance:one; sid:1;)";
968
970
971 UTHFreePacket(p);
972
973 PASS;
974}
975
976/*
977 * \test Test packet/stream sigs
978 */
979static int PayloadTestSig27(void)
980{
981 uint8_t buf[] = "dummypayload";
982 uint16_t buflen = sizeof(buf) - 1;
983 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
984
985 FAIL_IF_NULL(p);
986
987 char sig[] = "alert tcp any any -> any any (content:\"dummy\"; "
988 "depth:5; sid:1;)";
989
990 p->flags |= PKT_STREAM_ADD;
992
993 UTHFreePacket(p);
994
995 PASS;
996}
997
998/*
999 * \test Test packet/stream sigs
1000 */
1001static int PayloadTestSig28(void)
1002{
1003 uint8_t buf[] = "dummypayload";
1004 uint16_t buflen = sizeof(buf) - 1;
1005 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1006
1007 FAIL_IF_NULL(p);
1008
1009 char sig[] = "alert tcp any any -> any any (content:\"payload\"; "
1010 "offset:4; depth:12; sid:1;)";
1011
1012 p->flags |= PKT_STREAM_ADD;
1014
1015 UTHFreePacket(p);
1016
1017 PASS;
1018}
1019
1020/**
1021 * \test Test pcre recursive matching - bug #529
1022 */
1023static int PayloadTestSig29(void)
1024{
1025 uint8_t *buf = (uint8_t *)"this is a super dupernova in super nova now";
1026 uint16_t buflen = strlen((char *)buf);
1027 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1028
1029 FAIL_IF_NULL(p);
1030
1031 char sig[] = "alert tcp any any -> any any (msg:\"dummy\"; "
1032 "pcre:/^.{4}/; content:\"nova\"; within:4; sid:1;)";
1033
1035
1036 UTHFreePacket(p);
1037
1038 PASS;
1039}
1040
1041static int PayloadTestSig30(void)
1042{
1043 uint8_t *buf = (uint8_t *)
1044 "xyonexxxxxxtwojunkonetwo";
1045 uint16_t buflen = strlen((char *)buf);
1046 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1047
1048 FAIL_IF_NULL(p);
1049
1050 char sig[] = "alert tcp any any -> any any (content:\"one\"; pcre:\"/^two/R\"; sid:1;)";
1051
1053
1054 UTHFreePacket(p);
1055
1056 PASS;
1057}
1058
1059static int PayloadTestSig31(void)
1060{
1061 uint8_t *buf = (uint8_t *)
1062 "xyonexxxxxxtwojunkonetwo";
1063 uint16_t buflen = strlen((char *)buf);
1064 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1065
1066 FAIL_IF_NULL(p);
1067
1068 char sig[] = "alert tcp any any -> any any (content:\"one\"; pcre:\"/(fiv|^two)/R\"; sid:1;)";
1069
1071
1072 UTHFreePacket(p);
1073
1074 PASS;
1075}
1076
1077/**
1078 * \test Test byte_jump.
1079 */
1080static int PayloadTestSig32(void)
1081{
1082 uint8_t *buf = (uint8_t *)"dummy2xxcardmessage";
1083 uint16_t buflen = strlen((char *)buf);
1084 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1085
1086 FAIL_IF_NULL(p);
1087
1088 char sig[] = "alert tcp any any -> any any (msg:\"crash\"; "
1089 "content:\"message\"; byte_jump:2,-14,string,dec,relative; content:\"card\"; within:4; sid:1;)";
1090
1092
1093 UTHFreePacket(p);
1094
1095 PASS;
1096}
1097
1098/**
1099 * \test Test byte_test.
1100 */
1101static int PayloadTestSig33(void)
1102{
1103 uint8_t *buf = (uint8_t *)"dummy2xxcardmessage";
1104 uint16_t buflen = strlen((char *)buf);
1105 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1106
1107 FAIL_IF_NULL(p);
1108
1109 char sig[] = "alert tcp any any -> any any (msg:\"crash\"; "
1110 "content:\"message\"; byte_test:1,=,2,-14,string,dec,relative; sid:1;)";
1111
1113
1114 UTHFreePacket(p);
1115
1116 PASS;
1117}
1118
1119/**
1120 * \test Test byte_extract.
1121 */
1122static int PayloadTestSig34(void)
1123{
1124 uint8_t *buf = (uint8_t *)"dummy2xxcardmessage";
1125 uint16_t buflen = strlen((char *)buf);
1126 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1127
1128 FAIL_IF_NULL(p);
1129
1130 char sig[] = "alert tcp any any -> any any (msg:\"crash\"; "
1131 "content:\"message\"; byte_extract:1,-14,boom,string,dec,relative; sid:1;)";
1132
1134
1135 UTHFreePacket(p);
1136
1137 PASS;
1138}
1139
1140#endif /* UNITTESTS */
1141
1143{
1144#ifdef UNITTESTS
1145 UtRegisterTest("PayloadTestSig01", PayloadTestSig01);
1146 UtRegisterTest("PayloadTestSig02", PayloadTestSig02);
1147 UtRegisterTest("PayloadTestSig03", PayloadTestSig03);
1148 UtRegisterTest("PayloadTestSig04", PayloadTestSig04);
1149 UtRegisterTest("PayloadTestSig05", PayloadTestSig05);
1150 UtRegisterTest("PayloadTestSig06", PayloadTestSig06);
1151 UtRegisterTest("PayloadTestSig07", PayloadTestSig07);
1152 UtRegisterTest("PayloadTestSig08", PayloadTestSig08);
1153 UtRegisterTest("PayloadTestSig09", PayloadTestSig09);
1154 UtRegisterTest("PayloadTestSig10", PayloadTestSig10);
1155 UtRegisterTest("PayloadTestSig11", PayloadTestSig11);
1156 UtRegisterTest("PayloadTestSig12", PayloadTestSig12);
1157 UtRegisterTest("PayloadTestSig13", PayloadTestSig13);
1158 UtRegisterTest("PayloadTestSig14", PayloadTestSig14);
1159 UtRegisterTest("PayloadTestSig15", PayloadTestSig15);
1160 UtRegisterTest("PayloadTestSig16", PayloadTestSig16);
1161 UtRegisterTest("PayloadTestSig17", PayloadTestSig17);
1162
1163 UtRegisterTest("PayloadTestSig18", PayloadTestSig18);
1164 UtRegisterTest("PayloadTestSig19", PayloadTestSig19);
1165 UtRegisterTest("PayloadTestSig20", PayloadTestSig20);
1166 UtRegisterTest("PayloadTestSig21", PayloadTestSig21);
1167 UtRegisterTest("PayloadTestSig22", PayloadTestSig22);
1168 UtRegisterTest("PayloadTestSig23", PayloadTestSig23);
1169 UtRegisterTest("PayloadTestSig24", PayloadTestSig24);
1170 UtRegisterTest("PayloadTestSig25", PayloadTestSig25);
1171 UtRegisterTest("PayloadTestSig26", PayloadTestSig26);
1172 UtRegisterTest("PayloadTestSig27", PayloadTestSig27);
1173 UtRegisterTest("PayloadTestSig28", PayloadTestSig28);
1174 UtRegisterTest("PayloadTestSig29", PayloadTestSig29);
1175
1176 UtRegisterTest("PayloadTestSig30", PayloadTestSig30);
1177 UtRegisterTest("PayloadTestSig31", PayloadTestSig31);
1178 UtRegisterTest("PayloadTestSig32", PayloadTestSig32);
1179 UtRegisterTest("PayloadTestSig33", PayloadTestSig33);
1180 UtRegisterTest("PayloadTestSig34", PayloadTestSig34);
1181#endif /* UNITTESTS */
1182}
uint8_t flags
Definition decode-gre.h:0
#define PKT_NOPAYLOAD_INSPECTION
Definition decode.h:1252
#define PKT_STREAM_ADD
Definition decode.h:1260
#define PKT_DETECT_HAS_STREAMDATA
Definition decode.h:1305
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
bool DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, const uint8_t *buffer, const uint32_t buffer_len, const uint64_t stream_start_offset, const uint8_t flags, const enum DetectContentInspectionType inspection_mode)
wrapper around DetectEngineContentInspectionInternal to return true/false only
@ DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD
@ DETECT_ENGINE_CONTENT_INSPECTION_MODE_STREAM
#define DETECT_CI_FLAGS_SINGLE
uint8_t DetectEngineInspectPacketPayload(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, Flow *f, Packet *p)
Do the content inspection & validation for a signature.
int DetectEngineInspectStreamPayload(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, Flow *f, Packet *p)
Do the content inspection & validation for a signature on the raw stream.
int PrefilterPktPayloadRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx)
uint8_t DetectEngineInspectStream(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
inspect engine for stateful rules
void PayloadRegisterTests(void)
int PrefilterPktStreamRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx)
int PrefilterAppendPayloadEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterPktFn PrefilterFunc, void *pectx, void(*FreeFunc)(void *pectx), const char *name)
DetectEngineCtx * DetectEngineCtxInit(void)
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Data structures and function prototypes for keeping state for the detection engine.
#define DETECT_ENGINE_INSPECT_SIG_MATCH
#define DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
#define DETECT_ENGINE_INSPECT_SIG_NO_MATCH
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition detect.c:2420
#define DE_QUIET
Definition detect.h:330
#define SIG_FLAG_FLUSH
Definition detect.h:259
@ DETECT_SM_LIST_PMATCH
Definition detect.h:119
DecodeThreadVars * dtv
DetectEngineCtx * de_ctx
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
#define STREAMTCP_STREAM_FLAG_DEPTH_REACHED
int StreamReassembleRaw(TcpSession *ssn, const Packet *p, StreamReassembleRawFunc Callback, void *cb_data, uint64_t *progress_out, bool respect_inspect_depth)
Structure to hold thread specific data for all decode modules.
Definition decode.h:963
main detection engine ctx
Definition detect.h:932
int inspection_recursion_limit
Definition detect.h:973
uint8_t mpm_matcher
Definition detect.h:935
uint8_t flags
Definition detect.h:934
Signature * sig_list
Definition detect.h:941
MpmThreadCtx mtc
Definition detect.h:1345
uint64_t raw_stream_progress
Definition detect.h:1265
PrefilterRuleStore pmq
Definition detect.h:1349
Flow data structure.
Definition flow.h:356
void * protoctx
Definition flow.h:441
uint8_t mpm_type
Definition util-mpm.h:95
uint16_t minlen
Definition util-mpm.h:104
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition util-mpm.h:178
uint64_t pcap_cnt
Definition decode.h:626
struct Flow_ * flow
Definition decode.h:546
uint8_t * payload
Definition decode.h:605
uint16_t payload_len
Definition decode.h:606
uint32_t flags
Definition decode.h:544
uint8_t proto
Definition decode.h:523
Container for matching data for a signature group.
Definition detect.h:1629
Data needed for Match()
Definition detect.h:365
Signature container.
Definition detect.h:668
uint32_t flags
Definition detect.h:669
uint32_t id
Definition detect.h:713
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition detect.h:731
DetectEngineThreadCtx * det_ctx
const MpmCtx * mpm_ctx
DetectEngineThreadCtx * det_ctx
Per thread variable structure.
Definition threadvars.h:58
#define SCEnter(...)
Definition util-debug.h:277
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCReturn
Definition util-debug.h:279
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition util-mpm.c:47
uint8_t mpm_default_matcher
Definition util-mpm.c:48
#define PREFILTER_PROFILING_ADD_BYTES(det_ctx, bytes)
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself.
int UTHPacketMatchSigMpm(Packet *p, char *sig, uint16_t mpm_type)