suricata
detect-bytejump.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2020 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 Brian Rectanus <brectanu@gmail.com>
22  *
23  * Implements byte_jump keyword.
24  */
25 
26 #include "suricata-common.h"
27 #include "decode.h"
28 #include "detect.h"
29 #include "detect-parse.h"
30 #include "detect-engine.h"
31 #include "detect-engine-buffer.h"
32 #include "app-layer.h"
33 
34 #include "detect-byte.h"
35 #include "detect-byte-extract.h"
36 #include "detect-bytejump.h"
37 #include "detect-content.h"
38 #include "detect-uricontent.h"
39 
40 #include "util-byte.h"
41 #include "util-unittest.h"
42 #include "util-debug.h"
43 #include "util-validate.h"
44 #include "detect-pcre.h"
45 #include "detect-engine-build.h"
46 
47 /**
48  * \brief Regex for parsing our options
49  */
50 #define PARSE_REGEX \
51  "^\\s*" \
52  "([^\\s,]+\\s*,\\s*[^\\s,]+)" \
53  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
54  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
55  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
56  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
57  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
58  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
59  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
60  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
61  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
62  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
63  "\\s*$"
64 
65 static DetectParseRegex parse_regex;
66 
67 static DetectBytejumpData *DetectBytejumpParse(
68  DetectEngineCtx *de_ctx, const char *optstr, char **nbytes, char **offset);
69 static int DetectBytejumpSetup(DetectEngineCtx *de_ctx, Signature *s, const char *optstr);
70 static void DetectBytejumpFree(DetectEngineCtx*, void *ptr);
71 #ifdef UNITTESTS
72 static void DetectBytejumpRegisterTests(void);
73 #endif
74 
76 {
77  sigmatch_table[DETECT_BYTEJUMP].name = "byte_jump";
78  sigmatch_table[DETECT_BYTEJUMP].desc = "allow the ability to select a <num of bytes> from an <offset> and move the detection pointer to that position";
79  sigmatch_table[DETECT_BYTEJUMP].url = "/rules/payload-keywords.html#byte-jump";
81  sigmatch_table[DETECT_BYTEJUMP].Setup = DetectBytejumpSetup;
82  sigmatch_table[DETECT_BYTEJUMP].Free = DetectBytejumpFree;
83 #ifdef UNITTESTS
84  sigmatch_table[DETECT_BYTEJUMP].RegisterTests = DetectBytejumpRegisterTests;
85 #endif
86  DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
87 }
88 
89 /* 23 - This is the largest string (octal, with a zero prefix) that
90  * will not overflow uint64_t. The only way this length
91  * could be over 23 and still not overflow is if it were zero
92  * prefixed and we only support 1 byte of zero prefix for octal.
93  *
94  * "01777777777777777777777" = 0xffffffffffffffff
95  *
96  * 8 - Without string, the maximum byte extract count is 8.
97  */
98 static inline bool DetectBytejumpValidateNbytesOnly(const DetectBytejumpData *data, int32_t nbytes)
99 {
100  return (data->flags & DETECT_BYTEJUMP_STRING && nbytes <= 23) || (nbytes <= 8);
101 }
102 
103 static bool DetectBytejumpValidateNbytes(const DetectBytejumpData *data, int32_t nbytes)
104 {
105  if (!DetectBytejumpValidateNbytesOnly(data, nbytes)) {
106  if (data->flags & DETECT_BYTEJUMP_STRING) {
107  /* 23 - This is the largest string (octal, with a zero prefix) that
108  * will not overflow uint64_t. The only way this length
109  * could be over 23 and still not overflow is if it were zero
110  * prefixed and we only support 1 byte of zero prefix for octal.
111  *
112  * "01777777777777777777777" = 0xffffffffffffffff
113  */
114  if (nbytes > 23) {
115  SCLogError("Cannot test more than 23 bytes "
116  "with \"string\"");
117  }
118  } else {
119  if (nbytes > 8) {
120  SCLogError("Cannot test more than 8 bytes "
121  "without \"string\"");
122  }
123  }
124  return false;
125  }
126 
127  return true;
128 }
129 
130 /** \brief Byte jump match function
131  * \param det_ctx thread detect engine ctx
132  * \param s signature
133  * \param m byte jump sigmatch
134  * \param payload ptr to the payload
135  * \param payload_len length of the payload
136  * \retval true match
137  * \retval false no match
138  */
140  const SigMatchCtx *ctx, const uint8_t *payload, uint32_t payload_len, uint16_t flags,
141  int32_t nbytes, int32_t offset)
142 {
143  SCEnter();
144 
145  const DetectBytejumpData *data = (const DetectBytejumpData *)ctx;
146  const uint8_t *ptr = NULL;
147  int32_t len = 0;
148  uint64_t val = 0;
149  int extbytes;
150 
151  if (payload_len == 0) {
152  SCReturnBool(false);
153  }
154 
155  /* Validate the number of bytes we are testing
156  * If the validation is successful, we know that
157  * it contains a value <= 23. Thus, we can
158  * safely cast it when extracting bytes
159  */
160  if (data->flags & DETECT_BYTEJUMP_NBYTES_VAR) {
161  if (!DetectBytejumpValidateNbytesOnly(data, nbytes)) {
162  SCLogDebug("Invalid byte_jump nbytes "
163  "seen in byte_jump - %d",
164  nbytes);
165  SCReturnBool(false);
166  }
167  }
168 
169  /* Calculate the ptr value for the bytejump and length remaining in
170  * the packet from that point.
171  */
172  ptr = payload + offset;
173  len = payload_len - offset;
175  ptr += det_ctx->buffer_offset;
176  len -= det_ctx->buffer_offset;
177 
178  SCLogDebug("[relative] after: ptr %p [len %d]", ptr, len);
179 
180  /* No match if there is no relative base */
181  if (ptr == NULL || (nbytes && len <= 0)) {
182  SCReturnBool(false);
183  }
184  }
185 
186  /* Verify the to-be-extracted data is within the packet */
187  if (ptr < payload || nbytes > len) {
188  SCLogDebug("Data not within payload "
189  "pkt=%p, ptr=%p, len=%" PRIi32 ", nbytes=%" PRIi32,
190  payload, ptr, len, nbytes);
191  SCReturnBool(false);
192  }
193 
194  /* Extract the byte data */
196  extbytes = ByteExtractStringUint64(&val, data->base, nbytes, (const char *)ptr);
197  if(extbytes <= 0) {
198  SCLogDebug("error extracting %d bytes of string data: %d", nbytes, extbytes);
199  SCReturnBool(false);
200  }
201  }
202  else {
204  extbytes = ByteExtractUint64(&val, endianness, (uint16_t)nbytes, ptr);
205  if (extbytes != nbytes) {
206  SCLogDebug("error extracting %d bytes of numeric data: %d", nbytes, extbytes);
207  SCReturnBool(false);
208  }
209  }
210 
211  SCLogDebug("VAL: (%" PRIu64 " x %" PRIu32 ") + %" PRIi32 " + %" PRId32, val, data->multiplier,
212  extbytes, data->post_offset);
213 
214  /* Apply the bitmask value and bitmask shift count; note, the bitmask is applied
215  * before the multiplier per snort */
216  if (data->flags & DETECT_BYTEJUMP_BITMASK) {
217  SCLogDebug("[before bitmask] val: %" PRIi64 " bitmask_value: %" PRIx32, val,
218  data->bitmask_value);
219  val &= data->bitmask_value;
220  if (val && data->bitmask_shift_count) {
221  val = val >> data->bitmask_shift_count;
222  }
223  SCLogDebug("[after bitmask] val: %" PRIi64 " bitmask_value: %" PRIx32, val,
224  data->bitmask_value);
225  }
226 
227  /* Adjust the jump value based on flags */
228  val *= data->multiplier;
230  if ((val % 4) != 0) {
231  val += 4 - (val % 4);
232  }
233  }
234 
235  val += data->post_offset;
236  SCLogDebug("val: %" PRIi64 " post_offset: %" PRIi32, val, data->post_offset);
237 
238  const uint8_t *jumpptr;
239  /* Calculate the jump location */
241  jumpptr = payload + (int64_t)val;
242  SCLogDebug("NEWVAL: payload %p + %" PRIi64 " = %p", payload, (int64_t)val, jumpptr + val);
243  } else if (flags & DETECT_BYTEJUMP_END) {
244  jumpptr = payload + payload_len + (int64_t)val;
245  SCLogDebug(
246  "NEWVAL: payload %p + %" PRIu32 " + %" PRIi64, payload, payload_len, (int64_t)val);
247  } else {
248  jumpptr = ptr + (int64_t)val + extbytes;
249  SCLogDebug("NEWVAL: ptr %p + %" PRIi64 " = %p", ptr, val, jumpptr);
250  }
251 
252  /* Validate that the jump location is still in the packet
253  * \todo Should this validate it is still in the *payload*?
254  */
255  if (jumpptr < payload) {
256  jumpptr = payload;
257  SCLogDebug("jump location is before buffer start; resetting to buffer start");
258  } else if (jumpptr > (payload + payload_len)) {
259  SCLogDebug("Jump location (%" PRIu64 ") is not within payload (%" PRIu32 ")",
260  payload_len + val, payload_len);
261  SCReturnBool(false);
262  }
263 
264 #ifdef DEBUG
265  if (SCLogDebugEnabled()) {
266  const uint8_t *sptr = (flags & DETECT_BYTEJUMP_BEGIN) ? payload : ptr;
267  SCLogDebug("jumping %" PRId64 " bytes from %p (%08x)", val, sptr, (int)(sptr - payload));
268  }
269 #endif /* DEBUG */
270 
271  /* Adjust the detection context to the jump location. */
272  DEBUG_VALIDATE_BUG_ON(jumpptr < payload);
273  det_ctx->buffer_offset = (uint32_t)(jumpptr - payload);
274 
275  SCReturnBool(true);
276 }
277 
278 static DetectBytejumpData *DetectBytejumpParse(
279  DetectEngineCtx *de_ctx, const char *optstr, char **nbytes_str, char **offset)
280 {
281  DetectBytejumpData *data = NULL;
282  char args[11][64];
283  int res = 0;
284  size_t pcre2len;
285  int numargs = 0;
286  int i = 0;
287  uint32_t nbytes = 0;
288  char *str_ptr;
289  char *end_ptr;
290  pcre2_match_data *match = NULL;
291 
292  memset(args, 0x00, sizeof(args));
293 
294  /* Execute the regex and populate args with captures. */
295  int ret = DetectParsePcreExec(&parse_regex, &match, optstr, 0, 0);
296  if (ret < 2 || ret > 11) {
297  SCLogError("parse error, ret %" PRId32 ", string \"%s\"", ret, optstr);
298  goto error;
299  }
300 
301  /* The first two arguments are stashed in the first PCRE substring.
302  * This is because byte_jump can take 10 arguments, but PCRE only
303  * supports 9 substrings, sigh.
304  */
305  char str[512] = "";
306  pcre2len = sizeof(str);
307  res = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)str, &pcre2len);
308  if (res < 0) {
309  SCLogError("pcre2_substring_copy_bynumber failed "
310  "for arg 1");
311  goto error;
312  }
313 
314  /* Break up first substring into two parameters
315  *
316  * NOTE: Because of this, we cannot free args[1] as it is part of args[0],
317  * and *yes* this *is* ugly.
318  */
319  end_ptr = str;
320  while (!(isspace((unsigned char)*end_ptr) || (*end_ptr == ','))) end_ptr++;
321  *(end_ptr++) = '\0';
322  strlcpy(args[0], str, sizeof(args[0]));
323  numargs++;
324 
325  str_ptr = end_ptr;
326  while (isspace((unsigned char)*str_ptr) || (*str_ptr == ',')) str_ptr++;
327  end_ptr = str_ptr;
328  while (!(isspace((unsigned char)*end_ptr) || (*end_ptr == ',')) && (*end_ptr != '\0'))
329  end_ptr++;
330  *(end_ptr++) = '\0';
331  strlcpy(args[1], str_ptr, sizeof(args[1]));
332  numargs++;
333 
334  /* The remaining args are directly from PCRE substrings */
335  for (i = 1; i < (ret - 1); i++) {
336  pcre2len = sizeof(args[0]);
337  res = pcre2_substring_copy_bynumber(match, i + 1, (PCRE2_UCHAR8 *)args[i + 1], &pcre2len);
338  if (res < 0) {
339  SCLogError("pcre2_substring_copy_bynumber failed for arg %d", i + 1);
340  goto error;
341  }
342  numargs++;
343  }
344 
345  /* Initialize the data */
346  data = SCMalloc(sizeof(DetectBytejumpData));
347  if (unlikely(data == NULL))
348  goto error;
350  data->flags = 0;
351  data->multiplier = 1;
352  data->post_offset = 0;
353 
354  /*
355  * The first two options are required and positional. The
356  * remaining arguments are flags and are not positional.
357  */
358 
359  /* Number of bytes */
360  if (args[0][0] != '-' && isalpha((unsigned char)args[0][0])) {
361  if (nbytes_str == NULL) {
362  SCLogError("byte_jump supplied with "
363  "var name for nbytes. \"value\" argument supplied to "
364  "this function has to be non-NULL");
365  goto error;
366  }
367  *nbytes_str = SCStrdup(args[0]);
368  if (*nbytes_str == NULL)
369  goto error;
371  } else {
372  if (StringParseUint32(&nbytes, 10, (uint16_t)strlen(args[0]), args[0]) <= 0) {
373  SCLogError("Malformed number of bytes: %s", optstr);
374  goto error;
375  }
376  }
377 
378  /* Offset */
379  if (args[1][0] != '-' && isalpha((unsigned char)args[1][0])) {
380  if (offset == NULL) {
381  SCLogError("byte_jump supplied with "
382  "var name for offset. \"value\" argument supplied to "
383  "this function has to be non-NULL");
384  goto error;
385  }
386  *offset = SCStrdup(args[1]);
387  if (*offset == NULL)
388  goto error;
389  } else {
391  &data->offset, 10, (uint16_t)strlen(args[1]), args[1], -65535, 65535) <= 0) {
392  SCLogError("Malformed offset: %s", optstr);
393  goto error;
394  }
395  }
396 
397  /* The remaining options are flags. */
398  /** \todo Error on dups? */
399  for (i = 2; i < numargs; i++) {
400  if (strcmp("relative", args[i]) == 0) {
402  } else if (strcasecmp("string", args[i]) == 0) {
403  data->flags |= DETECT_BYTEJUMP_STRING;
404  } else if (strcasecmp("dec", args[i]) == 0) {
406  } else if (strcasecmp("hex", args[i]) == 0) {
408  } else if (strcasecmp("oct", args[i]) == 0) {
410  } else if (strcasecmp("big", args[i]) == 0) {
411  if (data->flags & DETECT_BYTEJUMP_LITTLE) {
412  data->flags ^= DETECT_BYTEJUMP_LITTLE;
413  }
414  data->flags |= DETECT_BYTEJUMP_BIG;
415  } else if (strcasecmp("little", args[i]) == 0) {
416  data->flags |= DETECT_BYTEJUMP_LITTLE;
417  } else if (strcasecmp("from_beginning", args[i]) == 0) {
418  data->flags |= DETECT_BYTEJUMP_BEGIN;
419  } else if (strcasecmp("from_end", args[i]) == 0) {
420  data->flags |= DETECT_BYTEJUMP_END;
421  } else if (strcasecmp("align", args[i]) == 0) {
422  data->flags |= DETECT_BYTEJUMP_ALIGN;
423  } else if (strncasecmp("multiplier ", args[i], 11) == 0) {
424  if (StringParseU16RangeCheck(&data->multiplier, 10, (uint16_t)strlen(args[i]) - 11,
425  args[i] + 11, 1, 65535) <= 0) {
426  SCLogError("Malformed multiplier: %s", optstr);
427  goto error;
428  }
429  } else if (strncasecmp("post_offset ", args[i], 12) == 0) {
430  if (StringParseI32RangeCheck(&data->post_offset, 10, (uint16_t)strlen(args[i]) - 12,
431  args[i] + 12, -65535, 65535) <= 0) {
432  SCLogError("Malformed post_offset: %s", optstr);
433  goto error;
434  }
435  SCLogDebug("post_offset: %s [%d]", optstr, data->post_offset);
436  } else if (strncasecmp("bitmask ", args[i], 8) == 0) {
438  if (ByteExtractStringUint32(&data->bitmask_value, 0, 0, args[i] + strlen("bitmask ")) <=
439  0) {
440  SCLogError("Malformed bitmask: %s", optstr);
441  goto error;
442  }
443  if (data->bitmask_value == 0) {
444  SCLogError("Invalid bitmask value: %d", data->bitmask_value);
445  goto error;
446  }
447  } else if (strcasecmp("dce", args[i]) == 0) {
448  data->flags |= DETECT_BYTEJUMP_DCE;
449  } else {
450  SCLogError("Unknown option: \"%s\"", args[i]);
451  goto error;
452  }
453  }
454 
455  if ((data->flags & DETECT_BYTEJUMP_END) && (data->flags & DETECT_BYTEJUMP_BEGIN)) {
456  SCLogError("'from_end' and 'from_beginning' "
457  "cannot be used in the same byte_jump statement");
458  goto error;
459  }
460 
461  if (!(data->flags & DETECT_BYTEJUMP_NBYTES_VAR)) {
462  if (!DetectBytejumpValidateNbytes(data, nbytes)) {
463  goto error;
464  }
465 
466  /* This is max 23 so it will fit in a byte (see validation function) */
467  data->nbytes = (uint8_t)nbytes;
468  }
469  if (!(data->flags & DETECT_BYTEJUMP_STRING)) {
470  if (data->base != DETECT_BYTEJUMP_BASE_UNSET) {
471  SCLogError("Cannot use a base "
472  "without \"string\": %s",
473  optstr);
474  goto error;
475  }
476  }
477 
478  data->bitmask_shift_count = 0;
479  if (data->flags & DETECT_BYTEJUMP_BITMASK) {
480  uint32_t bmask = data->bitmask_value;
481  while (!(bmask & 0x1)) {
482  bmask = bmask >> 1;
483  data->bitmask_shift_count++;
484  }
485  SCLogDebug("bitmask value 0x%x -> shift value %d", data->bitmask_value,
486  data->bitmask_shift_count);
487  }
488 
489  pcre2_match_data_free(match);
490  return data;
491 
492 error:
493  if (offset != NULL && *offset != NULL) {
494  SCFree(*offset);
495  *offset = NULL;
496  }
497  if (nbytes_str != NULL && *nbytes_str != NULL) {
498  SCFree(*nbytes_str);
499  *nbytes_str = NULL;
500  }
501  if (data != NULL)
502  DetectBytejumpFree(de_ctx, data);
503  if (match) {
504  pcre2_match_data_free(match);
505  }
506  return NULL;
507 }
508 
509 static int DetectBytejumpSetup(DetectEngineCtx *de_ctx, Signature *s, const char *optstr)
510 {
511  SigMatch *prev_pm = NULL;
512  DetectBytejumpData *data = NULL;
513  char *offset = NULL;
514  char *nbytes = NULL;
515  int ret = -1;
516 
517  data = DetectBytejumpParse(de_ctx, optstr, &nbytes, &offset);
518  if (data == NULL)
519  goto error;
520 
521  int sm_list;
522  if (s->init_data->list != DETECT_SM_LIST_NOTSET) {
523  if (DetectBufferGetActiveList(de_ctx, s) == -1)
524  goto error;
525 
526  sm_list = s->init_data->list;
527 
528  if (data->flags & DETECT_BYTEJUMP_RELATIVE) {
530  }
531  } else if (data->flags & DETECT_BYTEJUMP_DCE) {
532  if (data->flags & DETECT_BYTEJUMP_RELATIVE) {
535  if (prev_pm == NULL) {
536  sm_list = DETECT_SM_LIST_PMATCH;
537  } else {
538  sm_list = SigMatchListSMBelongsTo(s, prev_pm);
539  if (sm_list < 0)
540  goto error;
541  }
542  } else {
543  sm_list = DETECT_SM_LIST_PMATCH;
544  }
545 
547  goto error;
548 
549  } else if (data->flags & DETECT_BYTEJUMP_RELATIVE) {
552  if (prev_pm == NULL) {
553  sm_list = DETECT_SM_LIST_PMATCH;
554  } else {
555  sm_list = SigMatchListSMBelongsTo(s, prev_pm);
556  if (sm_list < 0)
557  goto error;
558  }
559 
560  } else {
561  sm_list = DETECT_SM_LIST_PMATCH;
562  }
563 
564  if (data->flags & DETECT_BYTEJUMP_DCE) {
565  if ((data->flags & DETECT_BYTEJUMP_STRING) ||
566  (data->flags & DETECT_BYTEJUMP_LITTLE) ||
567  (data->flags & DETECT_BYTEJUMP_BIG) ||
568  (data->flags & DETECT_BYTEJUMP_BEGIN) ||
569  (data->flags & DETECT_BYTEJUMP_END) ||
570  (data->base == DETECT_BYTEJUMP_BASE_DEC) ||
571  (data->base == DETECT_BYTEJUMP_BASE_HEX) ||
572  (data->base == DETECT_BYTEJUMP_BASE_OCT) ) {
573  SCLogError("Invalid option. "
574  "A byte_jump keyword with dce holds other invalid modifiers.");
575  goto error;
576  }
577  }
578 
579  if (nbytes != NULL) {
580  DetectByteIndexType index;
581  if (!DetectByteRetrieveSMVar(nbytes, s, sm_list, &index)) {
582  SCLogError("Unknown byte_extract var "
583  "seen in byte_jump - %s",
584  nbytes);
585  goto error;
586  }
587  data->nbytes = index;
588  SCFree(nbytes);
589  nbytes = NULL;
590  }
591 
592  if (offset != NULL) {
593  DetectByteIndexType index;
594  if (!DetectByteRetrieveSMVar(offset, s, sm_list, &index)) {
595  SCLogError("Unknown byte_extract var "
596  "seen in byte_jump - %s",
597  offset);
598  goto error;
599  }
600  data->offset = index;
602  SCFree(offset);
603  offset = NULL;
604  }
605 
606  if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_BYTEJUMP, (SigMatchCtx *)data, sm_list) ==
607  NULL) {
608  goto error;
609  }
610 
611  if (!(data->flags & DETECT_BYTEJUMP_RELATIVE))
612  goto okay;
613 
614  if (prev_pm == NULL)
615  goto okay;
616 
617  if (prev_pm->type == DETECT_CONTENT) {
618  DetectContentData *cd = (DetectContentData *)prev_pm->ctx;
620  } else if (prev_pm->type == DETECT_PCRE) {
621  DetectPcreData *pd = (DetectPcreData *)prev_pm->ctx;
623  }
624 
625  okay:
626  ret = 0;
627  return ret;
628 
629  error:
630  if (nbytes != NULL) {
631  SCFree(nbytes);
632  }
633  if (offset != NULL) {
634  SCFree(offset);
635  }
636  DetectBytejumpFree(de_ctx, data);
637  return ret;
638 }
639 
640 /**
641  * \brief this function will free memory associated with DetectBytejumpData
642  *
643  * \param data pointer to DetectBytejumpData
644  */
645 static void DetectBytejumpFree(DetectEngineCtx *de_ctx, void *ptr)
646 {
647  if (ptr == NULL)
648  return;
649 
650  DetectBytejumpData *data = (DetectBytejumpData *)ptr;
651  SCFree(data);
652 }
653 
654 
655 /* UNITTESTS */
656 #ifdef UNITTESTS
657 #include "util-unittest-helper.h"
658 static int g_file_data_buffer_id = 0;
659 static int g_dce_stub_data_buffer_id = 0;
660 
661 /**
662  * \test DetectBytejumpTestParse01 is a test to make sure that we return
663  * "something" when given valid bytejump opt
664  */
665 static int DetectBytejumpTestParse01(void)
666 {
667  DetectBytejumpData *data = NULL;
668  data = DetectBytejumpParse(NULL, "4,0", NULL, NULL);
669  FAIL_IF_NULL(data);
670 
671  DetectBytejumpFree(NULL, data);
672  PASS;
673 }
674 
675 /**
676  * \test DetectBytejumpTestParse02 is a test for setting the required opts
677  */
678 static int DetectBytejumpTestParse02(void)
679 {
680  DetectBytejumpData *data = NULL;
681  data = DetectBytejumpParse(NULL, "4, 0", NULL, NULL);
682  FAIL_IF_NULL(data);
683  FAIL_IF_NOT(data->nbytes == 4);
684  FAIL_IF_NOT(data->offset == 0);
685  FAIL_IF_NOT(data->multiplier == 1);
686  FAIL_IF_NOT(data->post_offset == 0);
687  FAIL_IF_NOT(data->flags == 0);
689 
690  DetectBytejumpFree(NULL, data);
691  PASS;
692 }
693 
694 /**
695  * \test DetectBytejumpTestParse03 is a test for setting the optional flags
696  */
697 static int DetectBytejumpTestParse03(void)
698 {
699  DetectBytejumpData *data = NULL;
700  data = DetectBytejumpParse(NULL,
701  " 4,0 , relative , little, string, "
702  "dec, align, from_beginning",
703  NULL, NULL);
704  FAIL_IF_NULL(data);
705  FAIL_IF_NOT(data->nbytes == 4);
706  FAIL_IF_NOT(data->offset == 0);
707  FAIL_IF_NOT(data->multiplier == 1);
708  FAIL_IF_NOT(data->post_offset == 0);
709  FAIL_IF_NOT(data->flags ==
713 
714  DetectBytejumpFree(NULL, data);
715  PASS;
716 }
717 
718 /**
719  * \test DetectBytejumpTestParse04 is a test for setting the optional flags
720  * with parameters
721  *
722  * \todo This fails because we can only have 9 captures and there are 10.
723  */
724 static int DetectBytejumpTestParse04(void)
725 {
726  DetectBytejumpData *data = NULL;
727  data = DetectBytejumpParse(NULL,
728  " 4,0 , relative , little, string, "
729  "dec, align, from_beginning , "
730  "multiplier 2 , post_offset -16 ",
731  NULL, NULL);
732  FAIL_IF_NULL(data);
733  FAIL_IF_NOT(data->nbytes == 4);
734  FAIL_IF_NOT(data->offset == 0);
735  FAIL_IF_NOT(data->multiplier == 2);
736  FAIL_IF_NOT(data->post_offset == -16);
737  FAIL_IF_NOT(data->flags ==
741 
742  DetectBytejumpFree(NULL, data);
743  PASS;
744 }
745 
746 /**
747  * \test DetectBytejumpTestParse05 is a test for setting base without string
748  */
749 static int DetectBytejumpTestParse05(void)
750 {
751  DetectBytejumpData *data = NULL;
752  data = DetectBytejumpParse(NULL,
753  " 4,0 , relative , little, dec, "
754  "align, from_beginning",
755  NULL, NULL);
756  FAIL_IF_NOT_NULL(data);
757 
758  PASS;
759 }
760 
761 /**
762  * \test DetectBytejumpTestParse06 is a test for too many bytes to extract
763  */
764 static int DetectBytejumpTestParse06(void)
765 {
766  DetectBytejumpData *data = NULL;
767  data = DetectBytejumpParse(NULL, "9, 0", NULL, NULL);
768  FAIL_IF_NOT_NULL(data);
769 
770  PASS;
771 }
772 
773 /**
774  * \test DetectBytejumpTestParse07 is a test for too many string bytes to extract
775  */
776 static int DetectBytejumpTestParse07(void)
777 {
778  DetectBytejumpData *data = NULL;
779  data = DetectBytejumpParse(NULL, "24, 0, string, dec", NULL, NULL);
780  FAIL_IF_NOT_NULL(data);
781 
782  PASS;
783 }
784 
785 /**
786  * \test DetectBytejumpTestParse08 is a test for offset too big
787  */
788 static int DetectBytejumpTestParse08(void)
789 {
790  DetectBytejumpData *data = NULL;
791  data = DetectBytejumpParse(NULL, "4, 0xffffffffffffffff", NULL, NULL);
792  FAIL_IF_NOT_NULL(data);
793 
794  PASS;
795 }
796 
797 /**
798  * \test Test dce option.
799  */
800 static int DetectBytejumpTestParse09(void)
801 {
802  Signature *s = SigAlloc();
803  FAIL_IF_NULL(s);
804 
806 
807  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s,
808  "4,0, align, multiplier 2, "
809  "post_offset -16,dce") == 0);
810  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s,
811  "4,0, multiplier 2, "
812  "post_offset -16,dce") == 0);
813  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0,post_offset -16,dce") == 0);
814  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0,dce") == 0);
815  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0,dce") == 0);
816  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, string, dce") == -1);
817  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, big, dce") == -1);
818  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, little, dce") == -1);
819  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, string, dec, dce") == -1);
820  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, string, oct, dce") == -1);
821  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, string, hex, dce") == -1);
822  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, from_beginning, dce") == -1);
823 
825  SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
826  FAIL_IF_NOT_NULL(sm);
827 
828  SigFree(NULL, s);
829  PASS;
830 }
831 
832 /**
833  * \test Test dce option.
834  */
835 static int DetectBytejumpTestParse10(void)
836 {
839  de_ctx->flags |= DE_QUIET;
840 
841  Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
842  "(msg:\"Testing bytejump_body\"; "
843  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
844  "dce_stub_data; "
845  "content:\"one\"; distance:0; "
846  "byte_jump:4,0,align,multiplier 2, "
847  "post_offset -16,relative,dce; sid:1;)");
848  FAIL_IF_NULL(s);
849  SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
850  FAIL_IF_NULL(sm);
852  FAIL_IF_NULL(sm->next);
853  sm = sm->next;
855 
862 
863  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
864  "(msg:\"Testing bytejump_body\"; "
865  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
866  "dce_stub_data; "
867  "content:\"one\"; distance:0; "
868  "byte_jump:4,0,align,multiplier 2, "
869  "post_offset -16,relative,dce; sid:2;)");
870  FAIL_IF_NULL(s);
871  sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
872  FAIL_IF_NULL(sm);
873 
875  FAIL_IF_NULL(sm->next);
876  sm = sm->next;
878 
879  bd = (DetectBytejumpData *)sm->ctx;
885 
886  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
887  "(msg:\"Testing bytejump_body\"; "
888  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
889  "dce_stub_data; "
890  "content:\"one\"; distance:0; "
891  "byte_jump:4,0,align,multiplier 2, "
892  "post_offset -16,relative; sid:3;)");
893  FAIL_IF_NULL(s);
894  sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
895  FAIL_IF_NULL(sm);
896 
898  FAIL_IF_NULL(sm->next);
899  sm = sm->next;
901 
902  bd = (DetectBytejumpData *)sm->ctx;
908 
910  PASS;
911 }
912 
913 /**
914  * \test Test dce option.
915  */
916 static int DetectBytejumpTestParse11(void)
917 {
918  DetectEngineCtx *de_ctx = NULL;
919  Signature *s = NULL;
920 
923 
924  de_ctx->flags |= DE_QUIET;
925  s = SigInit(de_ctx, "alert tcp any any -> any any "
926  "(msg:\"Testing bytejump_body\"; "
927  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
928  "dce_stub_data; "
929  "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
930  "post_offset -16,string,dce; sid:1;)");
931  FAIL_IF_NOT_NULL(s);
932 
933  s = SigInit(de_ctx, "alert tcp any any -> any any "
934  "(msg:\"Testing bytejump_body\"; "
935  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
936  "dce_sub_data; "
937  "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
938  "post_offset -16,big,dce; sid:1;)");
939  FAIL_IF_NOT_NULL(s);
940 
941  s = SigInit(de_ctx, "alert tcp any any -> any any "
942  "(msg:\"Testing bytejump_body\"; "
943  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
944  "dce_stub_data; "
945  "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
946  "post_offset -16,little,dce; sid:1;)");
947  FAIL_IF_NOT_NULL(s);
948 
949  s = SigInit(de_ctx, "alert tcp any any -> any any "
950  "(msg:\"Testing bytejump_body\"; "
951  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
952  "dce_stub_data; "
953  "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
954  "post_offset -16,string,hex,dce; sid:1;)");
955  FAIL_IF_NOT_NULL(s);
956 
957  s = SigInit(de_ctx, "alert tcp any any -> any any "
958  "(msg:\"Testing bytejump_body\"; "
959  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
960  "dce_stub_data; "
961  "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
962  "post_offset -16,string,dec,dce; sid:1;)");
963  FAIL_IF_NOT_NULL(s);
964 
965  s = SigInit(de_ctx, "alert tcp any any -> any any "
966  "(msg:\"Testing bytejump_body\"; "
967  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
968  "dce_stub_data; "
969  "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
970  "post_offset -16,string,oct,dce; sid:1;)");
971  FAIL_IF_NOT_NULL(s);
972 
973  s = SigInit(de_ctx, "alert tcp any any -> any any "
974  "(msg:\"Testing bytejump_body\"; "
975  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
976  "dce_stub_data; "
977  "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
978  "post_offset -16,from_beginning,dce; sid:1;)");
979  FAIL_IF_NOT_NULL(s);
980 
984  PASS;
985 }
986 
987 /**
988  * \test Test file_data
989  */
990 static int DetectBytejumpTestParse12(void)
991 {
994  de_ctx->flags |= DE_QUIET;
995 
996  Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
997  "(file_data; byte_jump:4,0,align,multiplier 2, "
998  "post_offset -16,relative; sid:1;)");
999  FAIL_IF_NULL(s);
1000 
1001  SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_file_data_buffer_id);
1002  FAIL_IF_NULL(sm);
1004 
1007  FAIL_IF((bd->flags &
1010 
1012  PASS;
1013 }
1014 
1015 static int DetectBytejumpTestParse13(void)
1016 {
1017  DetectBytejumpData *data = DetectBytejumpParse(NULL,
1018  " 4,0 , relative , little, string, dec, "
1019  "align, from_end",
1020  NULL, NULL);
1021  FAIL_IF_NULL(data);
1023 
1024  DetectBytejumpFree(NULL, data);
1025 
1026  PASS;
1027 }
1028 
1029 static int DetectBytejumpTestParse14(void)
1030 {
1031  DetectBytejumpData *data = DetectBytejumpParse(NULL,
1032  " 4,0 , relative , little, string, dec, "
1033  "align, from_beginning, from_end",
1034  NULL, NULL);
1035 
1036  FAIL_IF_NOT_NULL(data);
1037 
1038  PASS;
1039 }
1040 
1041 static int DetectBytejumpTestParse15(void)
1042 {
1045  de_ctx->flags |= DE_QUIET;
1046 
1047  Signature *s =
1048  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1049  "(msg:\"Testing bytejump_body\"; "
1050  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1051  "dce_stub_data; "
1052  "content:\"one\"; distance:0; "
1053  "byte_jump:4,0,align,multiplier 2, "
1054  "post_offset -16,relative,bitmask 0x8f40,dce; sid:1;)");
1055  FAIL_IF_NULL(s);
1056  SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
1057  FAIL_IF_NULL(sm);
1059  FAIL_IF_NULL(sm->next);
1060  sm = sm->next;
1062 
1069 
1071  FAIL_IF_NOT(bd->bitmask_value == 0x8f40);
1072  FAIL_IF_NOT(bd->bitmask_shift_count == 6);
1073 
1075  PASS;
1076 }
1077 
1078 static int DetectBytejumpTestParse16(void)
1079 {
1082  de_ctx->flags |= DE_QUIET;
1083 
1084  Signature *s =
1085  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1086  "(msg:\"Testing bytejump_body\"; "
1087  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1088  "dce_stub_data; "
1089  "content:\"one\"; distance:0; "
1090  "byte_jump:4,0,align,multiplier 2, "
1091  "post_offset -16,relative,bitmask 5304,dce; sid:1;)");
1092  FAIL_IF_NULL(s);
1093  SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
1094  FAIL_IF_NULL(sm);
1096  FAIL_IF_NULL(sm->next);
1097  sm = sm->next;
1099 
1106 
1108  FAIL_IF_NOT(bd->bitmask_value == 5304);
1109  FAIL_IF_NOT(bd->bitmask_shift_count == 3);
1110 
1112  PASS;
1113 }
1114 
1115 /**
1116  * \test DetectByteJumpTestPacket01 is a test to check matches of
1117  * byte_jump and byte_jump relative works if the previous keyword is pcre
1118  * (bug 142)
1119  */
1120 static int DetectByteJumpTestPacket01 (void)
1121 {
1122  uint8_t *buf = (uint8_t *)"GET /AllWorkAndNoPlayMakesWillADullBoy HTTP/1.0"
1123  "User-Agent: Wget/1.11.4"
1124  "Accept: */*"
1125  "Host: www.google.com"
1126  "Connection: Keep-Alive"
1127  "Date: Mon, 04 Jan 2010 17:29:39 GMT";
1128  uint16_t buflen = strlen((char *)buf);
1129  Packet *p;
1130  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1131 
1132  FAIL_IF_NULL(p);
1133 
1134  char sig[] = "alert tcp any any -> any any (msg:\"pcre + byte_test + "
1135  "relative\"; pcre:\"/AllWorkAndNoPlayMakesWillADullBoy/\"; byte_jump:1,6,"
1136  "relative,string,dec; content:\"0\"; sid:134; rev:1;)";
1137 
1138  FAIL_IF_NOT(UTHPacketMatchSig(p, sig));
1139 
1140  UTHFreePacket(p);
1141  PASS;
1142 }
1143 
1144 /**
1145  * \test DetectByteJumpTestPacket02 is a test to check matches of
1146  * byte_jump and byte_jump relative works if the previous keyword is byte_jump
1147  * (bug 165)
1148  */
1149 static int DetectByteJumpTestPacket02 (void)
1150 {
1151  uint8_t buf[] = { 0x00, 0x00, 0x00, 0x77, 0xff, 0x53,
1152  0x4d, 0x42, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x18,
1153  0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1154  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
1155  0x92, 0xa4, 0x01, 0x08, 0x17, 0x5c, 0x0e, 0xff,
1156  0x00, 0x00, 0x00, 0x01, 0x40, 0x48, 0x00, 0x00,
1157  0x00, 0xff };
1158  uint16_t buflen = sizeof(buf);
1159  Packet *p;
1160  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1161 
1162  FAIL_IF_NULL(p);
1163 
1164  char sig[] = "alert tcp any any -> any any (msg:\"byte_jump with byte_jump"
1165  " + relative\"; byte_jump:1,13; byte_jump:4,0,relative; "
1166  "content:\"|48 00 00|\"; within:3; sid:144; rev:1;)";
1167 
1168  FAIL_IF_NOT(UTHPacketMatchSig(p, sig));
1169 
1170  UTHFreePacket(p);
1171  PASS;
1172 }
1173 
1174 static int DetectByteJumpTestPacket03(void)
1175 {
1176  uint8_t *buf = NULL;
1177  uint16_t buflen = 0;
1178  buf = SCMalloc(4);
1179  if (unlikely(buf == NULL)) {
1180  printf("malloc failed\n");
1181  exit(EXIT_FAILURE);
1182  }
1183  memcpy(buf, "boom", 4);
1184  buflen = 4;
1185 
1186  Packet *p;
1187  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1188 
1189  FAIL_IF_NULL(p);
1190 
1191  char sig[] = "alert tcp any any -> any any (msg:\"byte_jump\"; "
1192  "byte_jump:1,214748364; sid:1; rev:1;)";
1193 
1194  FAIL_IF(UTHPacketMatchSig(p, sig));
1195 
1196  UTHFreePacket(p);
1197  FAIL_IF_NULL(buf);
1198 
1199  SCFree(buf);
1200  PASS;
1201 }
1202 
1203 /**
1204  * \test check matches of with from_beginning (bug 626/627)
1205  */
1206 static int DetectByteJumpTestPacket04 (void)
1207 {
1208  uint8_t *buf = (uint8_t *)"XYZ04abcdABCD";
1209  uint16_t buflen = strlen((char *)buf);
1210  Packet *p;
1211  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1212 
1213  FAIL_IF_NULL(p);
1214 
1215  char sig[] = "alert tcp any any -> any any (content:\"XYZ\"; byte_jump:2,0,relative,string,dec; content:\"ABCD\"; distance:0; within:4; sid:1; rev:1;)";
1216 
1217  FAIL_IF_NOT(UTHPacketMatchSig(p, sig));
1218 
1219  UTHFreePacket(p);
1220  PASS;
1221 }
1222 
1223 /**
1224  * \test check matches of with from_beginning (bug 626/627)
1225  */
1226 static int DetectByteJumpTestPacket05 (void)
1227 {
1228  uint8_t *buf = (uint8_t *)"XYZ04abcdABCD";
1229  uint16_t buflen = strlen((char *)buf);
1230  Packet *p;
1231  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1232 
1233  FAIL_IF_NULL(p);
1234 
1235  char sig[] = "alert tcp any any -> any any (content:\"XYZ\"; byte_jump:2,0,relative,string,dec; content:\"cdABCD\"; within:6; sid:1; rev:1;)";
1236 
1237  FAIL_IF_NOT(UTHPacketMatchSig(p, sig) ? 0 : 1);
1238 
1239  UTHFreePacket(p);
1240  PASS;
1241 }
1242 
1243 /**
1244  * \test check matches of with from_beginning (bug 626/627)
1245  */
1246 static int DetectByteJumpTestPacket06 (void)
1247 {
1248  uint8_t *buf = (uint8_t *)"XX04abcdABCD";
1249  uint16_t buflen = strlen((char *)buf);
1250  Packet *p;
1251  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1252 
1253  FAIL_IF_NULL(p);
1254 
1255  char sig[] = "alert tcp any any -> any any (content:\"XX\"; byte_jump:2,0,relative,string,dec,from_beginning; content:\"ABCD\"; distance:4; within:4; sid:1; rev:1;)";
1256 
1257  FAIL_IF_NOT(UTHPacketMatchSig(p, sig));
1258 
1259  UTHFreePacket(p);
1260  PASS;
1261 }
1262 
1263 /**
1264  * \test check matches of with from_beginning (bug 626/627)
1265  */
1266 static int DetectByteJumpTestPacket07 (void)
1267 {
1268  uint8_t *buf = (uint8_t *)"XX04abcdABCD";
1269  uint16_t buflen = strlen((char *)buf);
1270  Packet *p;
1271  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1272 
1273  FAIL_IF_NULL(p);
1274 
1275  char sig[] = "alert tcp any any -> any any (content:\"XX\"; byte_jump:2,0,relative,string,dec,from_beginning; content:\"abcdABCD\"; distance:0; within:8; sid:1; rev:1;)";
1276 
1277  FAIL_IF_NOT(UTHPacketMatchSig(p, sig) ? 1 : 0);
1278 
1279  UTHFreePacket(p);
1280  PASS;
1281 }
1282 
1283 /**
1284  * \test check matches of with from_end
1285  */
1286 static int DetectByteJumpTestPacket08 (void)
1287 {
1288  uint8_t *buf = (uint8_t *)"XX04abcdABCD";
1289  uint16_t buflen = strlen((char *)buf);
1290  Packet *p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1291 
1292  FAIL_IF_NULL(p);
1293 
1294  char sig[] = "alert tcp any any -> any any (content:\"XX\"; byte_jump:2,0,"
1295  "relative,string,dec,from_end, post_offset -8; content:\"ABCD\"; sid:1; rev:1;)";
1296 
1297  FAIL_IF_NOT(UTHPacketMatchSig(p, sig));
1298 
1299  UTHFreePacket(p);
1300 
1301  PASS;
1302 }
1303 
1304 /**
1305  * \brief this function registers unit tests for DetectBytejump
1306  */
1307 static void DetectBytejumpRegisterTests(void)
1308 {
1309  g_file_data_buffer_id = DetectBufferTypeGetByName("file_data");
1310  g_dce_stub_data_buffer_id = DetectBufferTypeGetByName("dce_stub_data");
1311 
1312  UtRegisterTest("DetectBytejumpTestParse01", DetectBytejumpTestParse01);
1313  UtRegisterTest("DetectBytejumpTestParse02", DetectBytejumpTestParse02);
1314  UtRegisterTest("DetectBytejumpTestParse03", DetectBytejumpTestParse03);
1315  UtRegisterTest("DetectBytejumpTestParse04", DetectBytejumpTestParse04);
1316  UtRegisterTest("DetectBytejumpTestParse05", DetectBytejumpTestParse05);
1317  UtRegisterTest("DetectBytejumpTestParse06", DetectBytejumpTestParse06);
1318  UtRegisterTest("DetectBytejumpTestParse07", DetectBytejumpTestParse07);
1319  UtRegisterTest("DetectBytejumpTestParse08", DetectBytejumpTestParse08);
1320  UtRegisterTest("DetectBytejumpTestParse09", DetectBytejumpTestParse09);
1321  UtRegisterTest("DetectBytejumpTestParse10", DetectBytejumpTestParse10);
1322  UtRegisterTest("DetectBytejumpTestParse11", DetectBytejumpTestParse11);
1323  UtRegisterTest("DetectBytejumpTestParse12", DetectBytejumpTestParse12);
1324  UtRegisterTest("DetectBytejumpTestParse13", DetectBytejumpTestParse13);
1325  UtRegisterTest("DetectBytejumpTestParse14", DetectBytejumpTestParse14);
1326  UtRegisterTest("DetectBytejumpTestParse15", DetectBytejumpTestParse15);
1327  UtRegisterTest("DetectBytejumpTestParse16", DetectBytejumpTestParse16);
1328 
1329  UtRegisterTest("DetectByteJumpTestPacket01", DetectByteJumpTestPacket01);
1330  UtRegisterTest("DetectByteJumpTestPacket02", DetectByteJumpTestPacket02);
1331  UtRegisterTest("DetectByteJumpTestPacket03", DetectByteJumpTestPacket03);
1332  UtRegisterTest("DetectByteJumpTestPacket04", DetectByteJumpTestPacket04);
1333  UtRegisterTest("DetectByteJumpTestPacket05", DetectByteJumpTestPacket05);
1334  UtRegisterTest("DetectByteJumpTestPacket06", DetectByteJumpTestPacket06);
1335  UtRegisterTest("DetectByteJumpTestPacket07", DetectByteJumpTestPacket07);
1336  UtRegisterTest("DetectByteJumpTestPacket08", DetectByteJumpTestPacket08);
1337 }
1338 #endif /* UNITTESTS */
DetectBytejumpData_::post_offset
int32_t post_offset
Definition: detect-bytejump.h:52
util-byte.h
SigTableElmt_::url
const char * url
Definition: detect.h:1461
DETECT_CONTENT_RELATIVE_NEXT
#define DETECT_CONTENT_RELATIVE_NEXT
Definition: detect-content.h:66
detect-content.h
len
uint8_t len
Definition: app-layer-dnp3.h:2
DetectEngineThreadCtx_::buffer_offset
uint32_t buffer_offset
Definition: detect.h:1269
detect-engine.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:119
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SignatureInitData_::smlists
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition: detect.h:642
SigTableElmt_::desc
const char * desc
Definition: detect.h:1460
ByteExtractUint64
int ByteExtractUint64(uint64_t *res, int e, uint16_t len, const uint8_t *bytes)
Definition: util-byte.c:75
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:79
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
ALPROTO_DCERPC
@ ALPROTO_DCERPC
Definition: app-layer-protos.h:44
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1445
PARSE_REGEX
#define PARSE_REGEX
Regex for parsing our options.
Definition: detect-bytejump.c:50
DetectBufferGetFirstSigMatch
SigMatch * DetectBufferGetFirstSigMatch(const Signature *s, const uint32_t buf_id)
Definition: detect-engine-buffer.c:157
DetectParseRegex
Definition: detect-parse.h:92
SigTableElmt_::name
const char * name
Definition: detect.h:1458
DETECT_BYTEJUMP
@ DETECT_BYTEJUMP
Definition: detect-engine-register.h:83
SigFree
void SigFree(DetectEngineCtx *, Signature *)
Definition: detect-parse.c:2063
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
DETECT_BYTEJUMP_LITTLE
#define DETECT_BYTEJUMP_LITTLE
Definition: detect-bytejump.h:35
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:69
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
DETECT_BYTEJUMP_NBYTES_VAR
#define DETECT_BYTEJUMP_NBYTES_VAR
Definition: detect-bytejump.h:43
SCDetectGetLastSMFromLists
SigMatch * SCDetectGetLastSMFromLists(const Signature *s,...)
Returns the sm with the largest index (added latest) from the lists passed to us.
Definition: detect-parse.c:563
ctx
struct Thresholds ctx
DETECT_BYTEJUMP_BASE_OCT
#define DETECT_BYTEJUMP_BASE_OCT
Definition: detect-bytejump.h:29
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:933
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2684
DE_QUIET
#define DE_QUIET
Definition: detect.h:329
UTHPacketMatchSig
int UTHPacketMatchSig(Packet *p, const char *sig)
Definition: util-unittest-helper.c:834
DETECT_BYTEJUMP_DCE
#define DETECT_BYTEJUMP_DCE
Definition: detect-bytejump.h:40
UTHBuildPacket
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.
Definition: util-unittest-helper.c:365
ByteExtractStringUint32
int ByteExtractStringUint32(uint32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:195
DetectParsePcreExec
int DetectParsePcreExec(DetectParseRegex *parse_regex, pcre2_match_data **match, const char *str, int start_offset, int options)
Definition: detect-parse.c:3500
DetectContentData_
Definition: detect-content.h:93
DetectPcreData_::flags
uint16_t flags
Definition: detect-pcre.h:51
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:56
SCDetectSignatureSetAppProto
int SCDetectSignatureSetAppProto(Signature *s, AppProto alproto)
Definition: detect-parse.c:2235
ByteExtractStringUint64
int ByteExtractStringUint64(uint64_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:190
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:3446
DETECT_BYTEJUMP_BIG
#define DETECT_BYTEJUMP_BIG
Definition: detect-bytejump.h:36
DetectBytejumpData_::base
uint8_t base
Definition: detect-bytejump.h:49
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1440
detect-pcre.h
DetectBytejumpData_
Definition: detect-bytejump.h:47
DetectByteIndexType
uint8_t DetectByteIndexType
Definition: detect-byte.h:28
util-unittest.h
DetectBytejumpData_::offset
int32_t offset
Definition: detect-bytejump.h:51
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
DetectBytejumpData_::multiplier
uint16_t multiplier
Definition: detect-bytejump.h:55
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1278
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
SCReturnBool
#define SCReturnBool(x)
Definition: util-debug.h:302
DetectBytejumpData_::bitmask_value
uint32_t bitmask_value
Definition: detect-bytejump.h:53
DetectBytejumpRegister
void DetectBytejumpRegister(void)
Definition: detect-bytejump.c:75
DETECT_BYTEJUMP_BITMASK
#define DETECT_BYTEJUMP_BITMASK
Definition: detect-bytejump.h:45
decode.h
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:19
DetectEngineThreadCtx_
Definition: detect.h:1245
DETECT_BYTEJUMP_ALIGN
#define DETECT_BYTEJUMP_ALIGN
Definition: detect-bytejump.h:39
StringParseI32RangeCheck
int StringParseI32RangeCheck(int32_t *res, int base, size_t len, const char *str, int32_t min, int32_t max)
Definition: util-byte.c:681
DetectSetupParseRegexes
void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
Definition: detect-parse.c:3626
DETECT_BYTEJUMP_END
#define DETECT_BYTEJUMP_END
Definition: detect-bytejump.h:42
SignatureInitData_::list
int list
Definition: detect.h:628
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
SCSigMatchAppendSMToList
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:387
detect.h
StringParseU16RangeCheck
int StringParseU16RangeCheck(uint16_t *res, int base, size_t len, const char *str, uint16_t min, uint16_t max)
Definition: util-byte.c:395
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:359
StringParseUint32
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:269
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:3104
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:358
BYTE_BIG_ENDIAN
#define BYTE_BIG_ENDIAN
Definition: util-byte.h:29
DetectBytejumpDoMatch
bool DetectBytejumpDoMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchCtx *ctx, const uint8_t *payload, uint32_t payload_len, uint16_t flags, int32_t nbytes, int32_t offset)
Byte jump match function.
Definition: detect-bytejump.c:139
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:2278
Packet_
Definition: decode.h:501
detect-engine-build.h
detect-bytejump.h
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:104
DETECT_BYTEJUMP_BASE_UNSET
#define DETECT_BYTEJUMP_BASE_UNSET
Definition: detect-bytejump.h:28
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:747
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1420
detect-byte.h
DETECT_BYTEJUMP_BASE_HEX
#define DETECT_BYTEJUMP_BASE_HEX
Definition: detect-bytejump.h:31
DETECT_PCRE
@ DETECT_PCRE
Definition: detect-engine-register.h:71
DetectBytejumpData_::bitmask_shift_count
uint8_t bitmask_shift_count
Definition: detect-bytejump.h:56
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:350
DETECT_SM_LIST_NOTSET
#define DETECT_SM_LIST_NOTSET
Definition: detect.h:144
DETECT_BYTETEST
@ DETECT_BYTETEST
Definition: detect-engine-register.h:82
BYTE_LITTLE_ENDIAN
#define BYTE_LITTLE_ENDIAN
Definition: util-byte.h:30
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
SigMatch_::type
uint16_t type
Definition: detect.h:356
detect-byte-extract.h
DetectBytejumpData_::nbytes
uint8_t nbytes
Definition: detect-bytejump.h:48
detect-engine-buffer.h
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
DETECT_BYTEJUMP_BASE_DEC
#define DETECT_BYTEJUMP_BASE_DEC
Definition: detect-bytejump.h:30
util-validate.h
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
str
#define str(s)
Definition: suricata-common.h:308
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
SigMatchListSMBelongsTo
int SigMatchListSMBelongsTo(const Signature *s, const SigMatch *key_sm)
Definition: detect-parse.c:762
SCFree
#define SCFree(p)
Definition: util-mem.h:61
UTHFreePacket
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:473
DETECT_BYTE_EXTRACT
@ DETECT_BYTE_EXTRACT
Definition: detect-engine-register.h:85
detect-parse.h
Signature_
Signature container.
Definition: detect.h:668
SigMatch_
a single match condition for a signature
Definition: detect.h:355
payload_len
uint16_t payload_len
Definition: stream-tcp-private.h:1
DETECT_ISDATAAT
@ DETECT_ISDATAAT
Definition: detect-engine-register.h:93
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2645
DETECT_PCRE_RELATIVE_NEXT
#define DETECT_PCRE_RELATIVE_NEXT
Definition: detect-pcre.h:34
DetectPcreData_
Definition: detect-pcre.h:47
DETECT_BYTEMATH
@ DETECT_BYTEMATH
Definition: detect-engine-register.h:84
DETECT_BYTEJUMP_STRING
#define DETECT_BYTEJUMP_STRING
Definition: detect-bytejump.h:37
detect-uricontent.h
DETECT_BYTEJUMP_BEGIN
#define DETECT_BYTEJUMP_BEGIN
Definition: detect-bytejump.h:34
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:935
DetectByteRetrieveSMVar
bool DetectByteRetrieveSMVar(const char *arg, const Signature *s, int sm_list, DetectByteIndexType *index)
Used to retrieve args from BM.
Definition: detect-byte.c:41
SigAlloc
Signature * SigAlloc(void)
Definition: detect-parse.c:1943
DetectBufferGetActiveList
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine-buffer.c:109
SCLogDebugEnabled
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:768
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
DETECT_BYTEJUMP_RELATIVE
#define DETECT_BYTEJUMP_RELATIVE
Definition: detect-bytejump.h:38
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1447
DETECT_BYTEJUMP_OFFSET_VAR
#define DETECT_BYTEJUMP_OFFSET_VAR
Definition: detect-bytejump.h:44
DetectBytejumpData_::flags
uint16_t flags
Definition: detect-bytejump.h:50
app-layer.h