... | ... |
@@ -611,9 +611,9 @@ Byte compare subsignatures can be used to evaluate a numeric value at a given of |
611 | 611 |
|
612 | 612 |
- `offset` must be a positive hex or decimal value. This will be the number of bytes from the start of the referenced `subsigid_trigger` match within the file buffer to begin the comparison. |
613 | 613 |
|
614 |
-- `byte_options` are used to specify the numeric type and endianess of the extracted byte sequence in that order as well as the number of bytes to be read. By default ClamAV will attempt to matchup up to the number of byte specified, unless the `e` (exact) option is specified or the numeric type is `b` (binary). This field follows the form `[h|d|i][l|b][e]num_bytes` |
|
614 |
+- `byte_options` are used to specify the numeric type and endianess of the extracted byte sequence in that order as well as the number of bytes to be read. By default ClamAV will attempt to matchup up to the number of byte specified, unless the `e` (exact) option is specified or the numeric type is `b` (binary). This field follows the form `[h|d|a|i][l|b][e]num_bytes` |
|
615 | 615 |
|
616 |
- - `h|d|i` where `h` specifies the byte sequence will be in hex, `d` decimal, and `i` signifies raw binary data. |
|
616 |
+ - `h|d|a|i` where `h` specifies the byte sequence will be in hex, `d` decimal, `a` automatic detection of hex or decimal at runtime, and `i` signifies raw binary data. |
|
617 | 617 |
|
618 | 618 |
- `l|b` where `l` specifies the byte sequence will be in little endian order and `b` big endian. |
619 | 619 |
|
... | ... |
@@ -221,26 +221,38 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons |
221 | 221 |
|
222 | 222 |
switch (*buf_start) { |
223 | 223 |
case 'h': |
224 |
- /* hex, decimal, and binary options are mutually exclusive parameters */ |
|
225 |
- if (bcomp->options & CLI_BCOMP_DEC || bcomp->options & CLI_BCOMP_BIN) { |
|
224 |
+ /* hex, decimal, auto, and binary options are mutually exclusive parameters */ |
|
225 |
+ if (bcomp->options & CLI_BCOMP_DEC || bcomp->options & CLI_BCOMP_BIN || bcomp->options & CLI_BCOMP_AUTO) { |
|
226 | 226 |
ret = CL_EMALFDB; |
227 | 227 |
} else { |
228 | 228 |
bcomp->options |= CLI_BCOMP_HEX; |
229 | 229 |
} break; |
230 |
+ |
|
230 | 231 |
case 'd': |
231 |
- /* hex, decimal, and binary options are mutually exclusive parameters */ |
|
232 |
- if (bcomp->options & CLI_BCOMP_HEX || bcomp->options & CLI_BCOMP_BIN) { |
|
232 |
+ /* hex, decimal, auto, and binary options are mutually exclusive parameters */ |
|
233 |
+ if (bcomp->options & CLI_BCOMP_HEX || bcomp->options & CLI_BCOMP_BIN || bcomp->options & CLI_BCOMP_AUTO) { |
|
233 | 234 |
ret = CL_EMALFDB; |
234 | 235 |
} else { |
235 | 236 |
bcomp->options |= CLI_BCOMP_DEC; |
236 | 237 |
} break; |
238 |
+ |
|
237 | 239 |
case 'i': |
238 |
- /* hex, decimal, and binary options are mutually exclusive parameters */ |
|
239 |
- if (bcomp->options & CLI_BCOMP_HEX || bcomp->options & CLI_BCOMP_DEC) { |
|
240 |
+ /* hex, decimal, auto, and binary options are mutually exclusive parameters */ |
|
241 |
+ if (bcomp->options & CLI_BCOMP_HEX || bcomp->options & CLI_BCOMP_DEC || bcomp->options & CLI_BCOMP_AUTO) { |
|
240 | 242 |
ret = CL_EMALFDB; |
241 | 243 |
} else { |
242 | 244 |
bcomp->options |= CLI_BCOMP_BIN; |
243 | 245 |
} break; |
246 |
+ |
|
247 |
+ case 'a': |
|
248 |
+ /* for automatic hex or decimal run-time detection */ |
|
249 |
+ /* hex, decimal, auto, and binary options are mutually exclusive parameters */ |
|
250 |
+ if (bcomp->options & CLI_BCOMP_HEX || bcomp->options & CLI_BCOMP_DEC || bcomp->options & CLI_BCOMP_BIN) { |
|
251 |
+ ret = CL_EMALFDB; |
|
252 |
+ } else { |
|
253 |
+ bcomp->options |= CLI_BCOMP_AUTO; |
|
254 |
+ } break; |
|
255 |
+ |
|
244 | 256 |
case 'l': |
245 | 257 |
/* little and big endian options are mutually exclusive parameters */ |
246 | 258 |
if (bcomp->options & CLI_BCOMP_BE) { |
... | ... |
@@ -248,6 +260,7 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons |
248 | 248 |
} else { |
249 | 249 |
bcomp->options |= CLI_BCOMP_LE; |
250 | 250 |
} break; |
251 |
+ |
|
251 | 252 |
case 'b': |
252 | 253 |
/* little and big endian options are mutually exclusive parameters */ |
253 | 254 |
if (bcomp->options & CLI_BCOMP_LE) { |
... | ... |
@@ -255,6 +268,7 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons |
255 | 255 |
} else { |
256 | 256 |
bcomp->options |= CLI_BCOMP_BE; |
257 | 257 |
} break; |
258 |
+ |
|
258 | 259 |
case 'e': |
259 | 260 |
/* for exact byte length matches */ |
260 | 261 |
bcomp->options |= CLI_BCOMP_EXACT; |
... | ... |
@@ -291,6 +305,14 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons |
291 | 291 |
return CL_EMALFDB; |
292 | 292 |
} |
293 | 293 |
|
294 |
+ /* same deal with hex byte lengths */ |
|
295 |
+ if (bcomp->options & CLI_BCOMP_HEX && (byte_length > CLI_BCOMP_MAX_HEX_BLEN)) { |
|
296 |
+ cli_errmsg("cli_bcomp_addpatt: while parsing (%s#%s#%s), byte length was too long\n", tokens[0], tokens[1], tokens[2]); |
|
297 |
+ free(buf); |
|
298 |
+ cli_bcomp_freemeta(root, bcomp); |
|
299 |
+ return CL_EMALFDB; |
|
300 |
+ } |
|
301 |
+ |
|
294 | 302 |
bcomp->byte_len = byte_length; |
295 | 303 |
|
296 | 304 |
/* we can have up to two comparison eval statements, each sperated by a comma, let's parse them in a separate string */ |
... | ... |
@@ -569,6 +591,47 @@ cl_error_t cli_bcomp_compare_check(const unsigned char* buffer, size_t buffer_le |
569 | 569 |
|
570 | 570 |
/* grab the first byte to handle byte length options to convert the string appropriately */ |
571 | 571 |
switch((opt & 0x00FF)) { |
572 |
+ /*al*/ |
|
573 |
+ case CLI_BCOMP_AUTO | CLI_BCOMP_LE: |
|
574 |
+ errno = 0; |
|
575 |
+ value = cli_strntol((char*) buffer, byte_len, (char**) &end_buf, 0); |
|
576 |
+ if ((((value == LONG_MAX) || (value == LONG_MIN)) && errno == ERANGE) || NULL == end_buf) { |
|
577 |
+ |
|
578 |
+ bcm_dbgmsg("cli_bcomp_compare_check: little endian conversion unsuccessful\n"); |
|
579 |
+ return CL_CLEAN; |
|
580 |
+ } |
|
581 |
+ /*hle*/ |
|
582 |
+ if (opt & CLI_BCOMP_EXACT) { |
|
583 |
+ if (buffer+byte_len != end_buf) { |
|
584 |
+ |
|
585 |
+ bcm_dbgmsg("cli_bcomp_compare_check: couldn't extract the exact number of requested bytes\n"); |
|
586 |
+ return CL_CLEAN; |
|
587 |
+ } |
|
588 |
+ } |
|
589 |
+ |
|
590 |
+ value = le64_to_host(value); |
|
591 |
+ break; |
|
592 |
+ |
|
593 |
+ /*ab*/ |
|
594 |
+ case CLI_BCOMP_AUTO | CLI_BCOMP_BE: |
|
595 |
+ value = cli_strntol((char*) buffer, byte_len, (char**) &end_buf, 0); |
|
596 |
+ if ((((value == LONG_MAX) || (value == LONG_MIN)) && errno == ERANGE) || NULL == end_buf) { |
|
597 |
+ |
|
598 |
+ bcm_dbgmsg("cli_bcomp_compare_check: big endian conversion unsuccessful\n"); |
|
599 |
+ return CL_CLEAN; |
|
600 |
+ } |
|
601 |
+ /*hbe*/ |
|
602 |
+ if (opt & CLI_BCOMP_EXACT) { |
|
603 |
+ if (buffer+byte_len != end_buf) { |
|
604 |
+ |
|
605 |
+ bcm_dbgmsg("cli_bcomp_compare_check: couldn't extract the exact number of requested bytes\n"); |
|
606 |
+ return CL_CLEAN; |
|
607 |
+ } |
|
608 |
+ } |
|
609 |
+ |
|
610 |
+ value = be64_to_host(value); |
|
611 |
+ break; |
|
612 |
+ |
|
572 | 613 |
/*hl*/ |
573 | 614 |
case CLI_BCOMP_HEX | CLI_BCOMP_LE: |
574 | 615 |
errno = 0; |
... | ... |
@@ -35,10 +35,12 @@ |
35 | 35 |
#include "mpool.h" |
36 | 36 |
|
37 | 37 |
#define CLI_BCOMP_MAX_BIN_BLEN 8 |
38 |
+#define CLI_BCOMP_MAX_HEX_BLEN 18 |
|
38 | 39 |
|
39 | 40 |
#define CLI_BCOMP_HEX 0x0001 |
40 | 41 |
#define CLI_BCOMP_DEC 0x0002 |
41 | 42 |
#define CLI_BCOMP_BIN 0x0004 |
43 |
+#define CLI_BCOMP_AUTO 0x0008 |
|
42 | 44 |
#define CLI_BCOMP_LE 0x0010 |
43 | 45 |
#define CLI_BCOMP_BE 0x0020 |
44 | 46 |
#define CLI_BCOMP_EXACT 0x0100 |