Browse code

bcomp - adding option for automatic detection and extraction of decimal or hex values from the buffer

Mickey Sola authored on 2018/10/09 02:18:09
Showing 3 changed files
... ...
@@ -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