Browse code

bcomp - updating and fixing binary extraction based on Micah's suggested solution; adding ability to compare and extract negative values

Mickey Sola authored on 2018/09/27 08:14:14
Showing 2 changed files
... ...
@@ -71,7 +71,7 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons
71 71
     int64_t offset_param = 0;
72 72
     int64_t ret = CL_SUCCESS;
73 73
     size_t byte_length = 0;
74
-    uint64_t comp_val = 0;
74
+    int64_t comp_val = 0;
75 75
     char *hexcpy = NULL;
76 76
 
77 77
     if (!hexsig || !(*hexsig) || !root || !virname) {
... ...
@@ -274,14 +274,14 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons
274 274
     buf_end = NULL;
275 275
     byte_length = strtol(buf_start, (char **) &buf_end, 0);
276 276
     if (buf_end && buf_end+1 != tokens[2]) {
277
-        cli_errmsg("cli_bcomp_addpatt: while parsing (%s#%s#%s), byte length parameter included invalid characters\n", tokens[0], tokens[1], tokens[3]);
277
+        cli_errmsg("cli_bcomp_addpatt: while parsing (%s#%s#%s), byte length parameter included invalid characters\n", tokens[0], tokens[1], tokens[2]);
278 278
         free(buf);
279 279
         cli_bcomp_freemeta(root, bcomp);
280 280
         return CL_EMALFDB;
281 281
     }
282 282
 
283
-    if (bcomp->options | CLI_BCOMP_BIN && byte_length > CLI_BCOMP_MAX_BIN_BLEN) {
284
-        cli_errmsg("cli_bcomp_addpatt: while parsing (%s#%s#%s), byte length for binary extraction was too long (max size (%d))\n", tokens[0], tokens[1], tokens[3], CLI_BCOMP_MAX_BIN_BLEN);
283
+    if (bcomp->options & CLI_BCOMP_BIN && (byte_length > CLI_BCOMP_MAX_BIN_BLEN || CLI_BCOMP_MAX_BIN_BLEN % byte_length)) {
284
+        cli_errmsg("cli_bcomp_addpatt: while parsing (%s#%s#%s), byte length was either too long or not a valid number of bytes\n", tokens[0], tokens[1], tokens[2]);
285 285
         free(buf);
286 286
         cli_bcomp_freemeta(root, bcomp);
287 287
         return CL_EMALFDB;
... ...
@@ -319,7 +319,7 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons
319 319
     bcomp->comp_value = comp_val;
320 320
 
321 321
     /* manually verify successful pattern parsing */
322
-    bcm_dbgmsg("Matcher Byte Compare: (%s%ld#%c%c%s%zu#%c%lu)\n",
322
+    bcm_dbgmsg("Matcher Byte Compare: (%s%ld#%c%c%s%zu#%c%ld)\n",
323 323
                     bcomp->offset ==  0 ? "" : 
324 324
                     (bcomp->offset < 0 ? "<<" : ">>"),
325 325
                     bcomp->offset,
... ...
@@ -456,8 +456,7 @@ cl_error_t cli_bcomp_compare_check(fmap_t *map, int offset, struct cli_bcomp_met
456 456
     uint16_t opt = 0;
457 457
     const unsigned char *buffer = NULL;
458 458
     unsigned char *conversion_buf = NULL;
459
-    uint64_t value = 0;
460
-    uint64_t *bin_value = NULL;
459
+    int64_t value = 0;
461 460
     const unsigned char* end_buf = NULL;
462 461
 
463 462
     if (!map || !bm) {
... ...
@@ -496,7 +495,7 @@ cl_error_t cli_bcomp_compare_check(fmap_t *map, int offset, struct cli_bcomp_met
496 496
         /*hl*/
497 497
         case CLI_BCOMP_HEX | CLI_BCOMP_LE:
498 498
             errno = 0;
499
-            value = cli_strntoul((char*) buffer, byte_len, (char**) &end_buf, 16);
499
+            value = cli_strntol((char*) buffer, byte_len, (char**) &end_buf, 16);
500 500
             if ((((value == LONG_MAX) || (value == LONG_MIN)) && errno == ERANGE) || NULL == end_buf) {
501 501
 
502 502
                 bcm_dbgmsg("bcmp_compare_check: little endian hex conversion unsuccessful\n");
... ...
@@ -516,7 +515,7 @@ cl_error_t cli_bcomp_compare_check(fmap_t *map, int offset, struct cli_bcomp_met
516 516
 
517 517
         /*hb*/  
518 518
         case CLI_BCOMP_HEX | CLI_BCOMP_BE:
519
-            value = cli_strntoul((char*) buffer, byte_len, (char**) &end_buf, 16);
519
+            value = cli_strntol((char*) buffer, byte_len, (char**) &end_buf, 16);
520 520
             if ((((value == LONG_MAX) || (value == LONG_MIN)) && errno == ERANGE) || NULL == end_buf) {
521 521
 
522 522
                 bcm_dbgmsg("bcmp_compare_check: big endian hex conversion unsuccessful\n");
... ...
@@ -536,7 +535,7 @@ cl_error_t cli_bcomp_compare_check(fmap_t *map, int offset, struct cli_bcomp_met
536 536
 
537 537
         /*dl*/
538 538
         case CLI_BCOMP_DEC | CLI_BCOMP_LE:
539
-            value = cli_strntoul((char*) buffer, byte_len, (char**) &end_buf, 10);
539
+            value = cli_strntol((char*) buffer, byte_len, (char**) &end_buf, 10);
540 540
             if ((((value == LONG_MAX) || (value == LONG_MIN)) && errno == ERANGE) || NULL == end_buf) {
541 541
 
542 542
                 bcm_dbgmsg("bcmp_compare_check: little endian decimal conversion unsuccessful\n");
... ...
@@ -556,7 +555,7 @@ cl_error_t cli_bcomp_compare_check(fmap_t *map, int offset, struct cli_bcomp_met
556 556
 
557 557
         /*db*/
558 558
         case CLI_BCOMP_DEC | CLI_BCOMP_BE:
559
-            value = cli_strntoul((char*) buffer, byte_len, (char**) &end_buf, 10);
559
+            value = cli_strntol((char*) buffer, byte_len, (char**) &end_buf, 10);
560 560
             if ((((value == LONG_MAX) || (value == LONG_MIN)) && errno == ERANGE) || NULL == end_buf) {
561 561
 
562 562
                 bcm_dbgmsg("bcmp_compare_check: big endian decimal conversion unsuccessful\n");
... ...
@@ -573,25 +572,33 @@ cl_error_t cli_bcomp_compare_check(fmap_t *map, int offset, struct cli_bcomp_met
573 573
 
574 574
             value = be64_to_host(value);
575 575
             break;
576
+        /*il*/
576 577
         case CLI_BCOMP_BIN | CLI_BCOMP_LE:
577
-            /* dropping bin_value on the heap to ensure our local stack is isolated from raw user input */
578
-            bin_value = cli_calloc(1, sizeof(uint64_t));
579
-
580
-            /* copy, then shift to align */
581
-            memcpy(bin_value, buffer, byte_len);
582
-            *bin_value = *bin_value >> CLI_BCOMP_MAX_BIN_BLEN - byte_len;
583
-
584
-            value = le64_to_host(*bin_value);
578
+            /* exact byte_length option is implied for binary extraction */
579
+            switch (byte_len) {
580
+                case 1: value = ( *(int8_t*) buffer);              break;
581
+                case 2: value = le16_to_host( *(int16_t*) buffer); break;
582
+                case 4: value = le32_to_host( *(int32_t*) buffer); break;
583
+                case 8: value = le64_to_host( *(int64_t*) buffer); break;
584
+
585
+                default:
586
+                    bcm_dbgmsg("bcmp_compare_check: invalid byte size for binary integer field (%u)\n", byte_len);
587
+                    return CL_EARG;
588
+            }
585 589
             break;
590
+        /*ib*/
586 591
         case CLI_BCOMP_BIN | CLI_BCOMP_BE:
587
-            /* dropping bin_value on the heap to ensure our local stack is isolated from raw user input */
588
-            bin_value = cli_calloc(1, sizeof(uint64_t));
589
-
590
-            /* copy, then shift to align */
591
-            memcpy(bin_value, buffer, byte_len);
592
-            *bin_value = *bin_value >> CLI_BCOMP_MAX_BIN_BLEN - byte_len;
593
-
594
-            value = be64_to_host(*bin_value);
592
+            /* exact byte_length option is implied for binary extraction */
593
+            switch (byte_len) {
594
+                case 1: value = ( *(int8_t*) buffer);              break;
595
+                case 2: value = be16_to_host( *(int16_t*) buffer); break;
596
+                case 4: value = be32_to_host( *(int32_t*) buffer); break;
597
+                case 8: value = be64_to_host( *(int64_t*) buffer); break;
598
+
599
+                default:
600
+                    bcm_dbgmsg("bcmp_compare_check: invalid byte size for binary integer field (%u)\n", byte_len);
601
+                    return CL_EARG;
602
+            }
595 603
             break;
596 604
         default:
597 605
             return CL_ENULLARG;
... ...
@@ -602,21 +609,21 @@ cl_error_t cli_bcomp_compare_check(fmap_t *map, int offset, struct cli_bcomp_met
602 602
 
603 603
         case '>':
604 604
             if (value > bm->comp_value) {
605
-                bcm_dbgmsg("bcmp_compare_check: extracted value (%lu) greater than comparison value (%lu)\n", value, bm->comp_value);
605
+                bcm_dbgmsg("bcmp_compare_check: extracted value (%ld) greater than comparison value (%ld)\n", value, bm->comp_value);
606 606
                 return CL_VIRUS;
607 607
             }
608 608
             break;
609 609
 
610 610
         case '<':
611 611
             if (value < bm->comp_value) {
612
-                bcm_dbgmsg("bcmp_compare_check: extracted value (%lu) less than comparison value (%lu)\n", value, bm->comp_value);
612
+                bcm_dbgmsg("bcmp_compare_check: extracted value (%ld) less than comparison value (%ld)\n", value, bm->comp_value);
613 613
                 return CL_VIRUS;
614 614
             }
615 615
             break;
616 616
 
617 617
         case '=':
618 618
             if (value == bm->comp_value) {
619
-                bcm_dbgmsg("bcmp_compare_check: extracted value (%lu) equal to comparison value (%lu)\n", value, bm->comp_value);
619
+                bcm_dbgmsg("bcmp_compare_check: extracted value (%ld) equal to comparison value (%ld)\n", value, bm->comp_value);
620 620
                 return CL_VIRUS;
621 621
             }
622 622
             break;
... ...
@@ -627,7 +634,7 @@ cl_error_t cli_bcomp_compare_check(fmap_t *map, int offset, struct cli_bcomp_met
627 627
     }
628 628
 
629 629
     /* comparison was not successful */
630
-    bcm_dbgmsg("bcmp_compare_check: extracted value was not %c %lu\n", bm->comp_symbol, bm->comp_value);
630
+    bcm_dbgmsg("bcmp_compare_check: extracted value was not %c %ld\n", bm->comp_symbol, bm->comp_value);
631 631
     return CL_CLEAN;
632 632
 }
633 633
 
... ...
@@ -51,7 +51,7 @@ struct cli_bcomp_meta {
51 51
     uint16_t options; /* bitmask */
52 52
     size_t byte_len;
53 53
     char comp_symbol; /* <, >, = are supported */
54
-    uint64_t comp_value;
54
+    int64_t comp_value;
55 55
 };
56 56
 
57 57
 cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, const char* hexsig, const uint32_t *lsigid, unsigned int options);