... | ... |
@@ -615,7 +615,7 @@ Byte compare subsignatures can be used to evaluate a numeric value at a given of |
615 | 615 |
|
616 | 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 |
- - `l|b` where `l` specifies the byte sequence will be in little endian order and `b` big endian. |
|
618 |
+ - `l|b` where `l` specifies the byte sequence will be in little endian order and `b` big endian. If decimal `d` is specified, big-endian is implied and using `l` will result in a malformed database error. |
|
619 | 619 |
|
620 | 620 |
- `e` specifies that ClamAV will only evaluate the comparison if it can extract the exact number of bytes specified. This option is implicitly declared when using the `i` flag. |
621 | 621 |
|
... | ... |
@@ -131,7 +131,7 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons |
131 | 131 |
/* use the passed hexsig buffer to find the start and ending parens and store the param length (minus starting paren) */ |
132 | 132 |
buf_start = buf_end; |
133 | 133 |
if (buf_start[0] == '(') { |
134 |
- if (buf_end = strchr(buf_start, ')')) { |
|
134 |
+ if (( buf_end = strchr(buf_start, ')') )) { |
|
135 | 135 |
len = (size_t) (buf_end - ++buf_start); |
136 | 136 |
} |
137 | 137 |
else { |
... | ... |
@@ -230,10 +230,12 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons |
230 | 230 |
|
231 | 231 |
case 'd': |
232 | 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 |
+ /* decimal may not be used with little-endian. big-endian is implied. */ |
|
234 |
+ if (bcomp->options & CLI_BCOMP_HEX || bcomp->options & CLI_BCOMP_BIN || bcomp->options & CLI_BCOMP_AUTO || bcomp->options & CLI_BCOMP_LE) { |
|
234 | 235 |
ret = CL_EMALFDB; |
235 | 236 |
} else { |
236 | 237 |
bcomp->options |= CLI_BCOMP_DEC; |
238 |
+ bcomp->options |= CLI_BCOMP_BE; |
|
237 | 239 |
} break; |
238 | 240 |
|
239 | 241 |
case 'i': |
... | ... |
@@ -255,7 +257,8 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons |
255 | 255 |
|
256 | 256 |
case 'l': |
257 | 257 |
/* little and big endian options are mutually exclusive parameters */ |
258 |
- if (bcomp->options & CLI_BCOMP_BE) { |
|
258 |
+ /* decimal may not be used with little-endian */ |
|
259 |
+ if (bcomp->options & CLI_BCOMP_BE || bcomp->options & CLI_BCOMP_DEC) { |
|
259 | 260 |
ret = CL_EMALFDB; |
260 | 261 |
} else { |
261 | 262 |
bcomp->options |= CLI_BCOMP_LE; |
... | ... |
@@ -485,7 +488,7 @@ cl_error_t cli_bcomp_scanbuf(const unsigned char *buffer, size_t buffer_length, |
485 | 485 |
} |
486 | 486 |
|
487 | 487 |
/* ensures the referenced subsig matches as expected, and also ensures mdata has the needed offset */ |
488 |
- if (ret = lsig_sub_matched(root, mdata, lsigid, ref_subsigid, CLI_OFF_NONE, 0)) { |
|
488 |
+ if (( ret = lsig_sub_matched(root, mdata, lsigid, ref_subsigid, CLI_OFF_NONE, 0) )) { |
|
489 | 489 |
break; |
490 | 490 |
} |
491 | 491 |
|
... | ... |
@@ -629,7 +632,17 @@ cl_error_t cli_bcomp_compare_check(const unsigned char* buffer, size_t buffer_le |
629 | 629 |
opt_val = opt; |
630 | 630 |
if (opt_val & CLI_BCOMP_AUTO) { |
631 | 631 |
if (tmp_buffer) { |
632 |
- if(!strncmp((char*) tmp_buffer, "0x", 2) || !strncmp((char*) tmp_buffer, "0X", 2)) { |
|
632 |
+ /* tmp_buffer is based on the size of byte_len, so we can check against that safely */ |
|
633 |
+ if ((opt & 0x00F0) & CLI_BCOMP_LE && byte_len >= 3) { |
|
634 |
+ if(!strncmp((char*) &tmp_buffer[byte_len-2], "0x", 2) || !strncmp((char*) &tmp_buffer[byte_len-2], "0X", 2)) { |
|
635 |
+ tmp_buffer[byte_len-2] = '\0'; |
|
636 |
+ bcm_dbgmsg("cli_bcomp_compare_check: adjusted bytes before comparison %.*s\n", byte_len-2, tmp_buffer); |
|
637 |
+ opt |= CLI_BCOMP_HEX; |
|
638 |
+ } else { |
|
639 |
+ opt |= CLI_BCOMP_DEC; |
|
640 |
+ } |
|
641 |
+ } |
|
642 |
+ else if(!strncmp((char*) tmp_buffer, "0x", 2) || !strncmp((char*) tmp_buffer, "0X", 2)) { |
|
633 | 643 |
opt |= CLI_BCOMP_HEX; |
634 | 644 |
} else { |
635 | 645 |
opt |= CLI_BCOMP_DEC; |
... | ... |
@@ -689,28 +702,9 @@ cl_error_t cli_bcomp_compare_check(const unsigned char* buffer, size_t buffer_le |
689 | 689 |
|
690 | 690 |
/*dl*/ |
691 | 691 |
case CLI_BCOMP_DEC | CLI_BCOMP_LE: |
692 |
- value = cli_strntol((char*) buffer, byte_len, (char**) &end_buf, 10); |
|
693 |
- if ((((value == LONG_MAX) || (value == LONG_MIN)) && errno == ERANGE) || NULL == end_buf) { |
|
694 |
- |
|
695 |
- if (tmp_buffer) { |
|
696 |
- free(tmp_buffer); |
|
697 |
- } |
|
698 |
- bcm_dbgmsg("cli_bcomp_compare_check: little endian decimal conversion unsuccessful\n"); |
|
699 |
- return CL_CLEAN; |
|
700 |
- } |
|
701 |
- /*dle*/ |
|
702 |
- if (opt & CLI_BCOMP_EXACT) { |
|
703 |
- if (buffer+byte_len != end_buf) { |
|
704 |
- |
|
705 |
- if (tmp_buffer) { |
|
706 |
- free(tmp_buffer); |
|
707 |
- } |
|
708 |
- bcm_dbgmsg("cli_bcomp_compare_check: couldn't extract the exact number of requested bytes\n"); |
|
709 |
- return CL_CLEAN; |
|
710 |
- } |
|
711 |
- } |
|
712 |
- |
|
713 |
- value = le64_to_host(value); |
|
692 |
+ /* it may be possible for the auto option to proc this */ |
|
693 |
+ bcm_dbgmsg("cli_bcomp_compare_check: auto detection found ascii decimal for specified little endian byte extraction, which is unsupported\n"); |
|
694 |
+ return CL_CLEAN; |
|
714 | 695 |
break; |
715 | 696 |
|
716 | 697 |
/*db*/ |
... | ... |
@@ -577,7 +577,7 @@ long cli_strntol(const char* nptr, size_t n, char** endptr, register int base) |
577 | 577 |
} |
578 | 578 |
|
579 | 579 |
if (base == 0 || base == 16) { |
580 |
- if (c == '0' && (*s == 'x' || *s == 'X')) { |
|
580 |
+ if (c == '0' && (s + 1 < nptr + n) && (*(s+1) == 'x' || *(s+1) == 'X')) { |
|
581 | 581 |
if (s + 2 >= nptr + n) { |
582 | 582 |
goto done; |
583 | 583 |
} |
... | ... |
@@ -696,7 +696,7 @@ cli_strntoul(const char* nptr, size_t n, char** endptr, register int base) |
696 | 696 |
} |
697 | 697 |
|
698 | 698 |
if (base == 0 || base == 16) { |
699 |
- if (c == '0' && (*s == 'x' || *s == 'X')) { |
|
699 |
+ if (c == '0' && (s + 1 < nptr + n) && (*(s+1) == 'x' || *(s+1) == 'X')) { |
|
700 | 700 |
if (s + 2 >= nptr + n) { |
701 | 701 |
goto done; |
702 | 702 |
} |