Browse code

Add support for YARA private rules and referencing other rules in a YARA condition.

Steven Morgan authored on 2015/06/20 05:33:59
Showing 7 changed files
... ...
@@ -1258,10 +1258,22 @@ int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs,
1258 1258
         }
1259 1259
         for(i = 1; i < lsigs; i++)
1260 1260
             data->lsigcnt[i] = data->lsigcnt[0] + 64 * i;
1261
+        data->yr_matches = (uint8_t *) cli_calloc(lsigs, sizeof(uint8_t));
1262
+        if (data->yr_matches == NULL) {
1263
+            free(data->lsigcnt[0]);
1264
+            free(data->lsigcnt);
1265
+            if(partsigs)
1266
+                free(data->offmatrix);
1267
+            
1268
+            if(reloffsigs)
1269
+                free(data->offset);
1270
+            return CL_EMEM;
1271
+        }
1261 1272
 
1262 1273
         /* subsig offsets */
1263
-        data->lsig_matches = (struct cli_lsig_matches **) cli_calloc(lsigs * sizeof(struct cli_lsig_matches *), sizeof(struct cli_lsig_matches *));
1274
+        data->lsig_matches = (struct cli_lsig_matches **) cli_calloc(lsigs, sizeof(struct cli_lsig_matches *));
1264 1275
         if(!data->lsig_matches) {
1276
+            free(data->yr_matches);
1265 1277
             free(data->lsigcnt[0]);
1266 1278
             free(data->lsigcnt);
1267 1279
             if(partsigs)
... ...
@@ -1279,6 +1291,7 @@ int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs,
1279 1279
             free(data->lsig_matches);
1280 1280
             free(data->lsigsuboff_last);
1281 1281
             free(data->lsigsuboff_first);
1282
+            free(data->yr_matches);
1282 1283
             free(data->lsigcnt[0]);
1283 1284
             free(data->lsigcnt);
1284 1285
             if(partsigs)
... ...
@@ -1298,6 +1311,7 @@ int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs,
1298 1298
             free(data->lsigsuboff_first[0]);
1299 1299
             free(data->lsigsuboff_last);
1300 1300
             free(data->lsigsuboff_first);
1301
+            free(data->yr_matches);
1301 1302
             free(data->lsigcnt[0]);
1302 1303
             free(data->lsigcnt);
1303 1304
             if(partsigs)
... ...
@@ -1392,6 +1406,7 @@ void cli_ac_freedata(struct cli_ac_data *data)
1392 1392
             free(data->lsig_matches);
1393 1393
             data->lsig_matches = 0;
1394 1394
         }
1395
+        free(data->yr_matches);
1395 1396
         free(data->lsigcnt[0]);
1396 1397
         free(data->lsigcnt);
1397 1398
         free(data->lsigsuboff_last[0]);
... ...
@@ -61,6 +61,7 @@ struct cli_ac_data {
61 61
     uint32_t **lsigcnt;
62 62
     uint32_t **lsigsuboff_last, **lsigsuboff_first;
63 63
     struct cli_lsig_matches **lsig_matches;
64
+    uint8_t *yr_matches;
64 65
     uint32_t *offset;
65 66
     uint32_t macro_lastmatch[32];
66 67
     /** Hashset for versioninfo matching */
... ...
@@ -766,8 +766,7 @@ static int lsig_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data
766 766
 static int yara_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data *acdata, struct cli_target_info *target_info, const char *hash, uint32_t lsid)
767 767
 {
768 768
     struct cli_ac_lsig *ac_lsig = root->ac_lsigtable[lsid];
769
-    uint8_t * code_start = ac_lsig->u.code_start;
770
-    int rc = 0;
769
+    int rc;
771 770
     YR_SCAN_CONTEXT context = {0};
772 771
  
773 772
     if (target_info != NULL) {
... ...
@@ -779,9 +778,13 @@ static int yara_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data
779 779
 
780 780
     rc = yr_execute_code(ac_lsig, acdata, &context, 0, 0);
781 781
 
782
-    if (rc == CL_VIRUS)
783
-        cli_append_virus(ctx, ac_lsig->virname);
784
-
782
+    if (rc == CL_VIRUS) {
783
+        if (ac_lsig->flag & CLI_LSIG_FLAG_PRIVATE) {
784
+            rc = CL_CLEAN;
785
+        } else {
786
+            cli_append_virus(ctx, ac_lsig->virname);
787
+        }
788
+    }
785 789
     return rc;
786 790
 }
787 791
 
... ...
@@ -77,6 +77,8 @@ struct cli_lsig_tdb {
77 77
 #endif
78 78
 };
79 79
 
80
+#define CLI_LSIG_FLAG_PRIVATE 0x01
81
+
80 82
 struct cli_bc;
81 83
 struct cli_ac_lsig {
82 84
 #define CLI_LSIG_NORMAL 0
... ...
@@ -85,6 +87,7 @@ struct cli_ac_lsig {
85 85
     uint32_t id;
86 86
     unsigned bc_idx;
87 87
     uint8_t type;
88
+    uint8_t flag;
88 89
     union {
89 90
         char *logic;
90 91
         uint8_t *code_start;
... ...
@@ -3764,6 +3764,8 @@ static int load_oneyara(YR_RULE *rule, int chkpua, struct cl_engine *engine, uns
3764 3764
     } else {
3765 3765
         if (NULL != (lsig->u.code_start = rule->code_start)) {
3766 3766
             lsig->type = (rule->cl_flags & RULE_OFFSETS) ? CLI_YARA_OFFSET : CLI_YARA_NORMAL;
3767
+            if (RULE_IS_PRIVATE(rule))
3768
+                lsig->flag |= CLI_LSIG_FLAG_PRIVATE;
3767 3769
         } else {
3768 3770
             cli_errmsg("load_oneyara: code start is NULL\n");
3769 3771
             FREE_TDB(tdb);
... ...
@@ -3815,6 +3817,7 @@ static int load_oneyara(YR_RULE *rule, int chkpua, struct cl_engine *engine, uns
3815 3815
     memcpy(&lsig->tdb, &tdb, sizeof(tdb));
3816 3816
     ytable_delete(&ytable);
3817 3817
 
3818
+    rule->lsigid = root->ac_lsigs - 1;
3818 3819
     yara_loaded++;
3819 3820
     cli_yaramsg("load_oneyara: successfully loaded %s\n", rule->identifier);
3820 3821
     return CL_SUCCESS;
... ...
@@ -456,6 +456,7 @@ struct _yc_rule {
456 456
     uint32_t g_flags;
457 457
     uint32_t cl_flags;
458 458
     uint8_t * code_start;
459
+    uint32_t lsigid;
459 460
 };
460 461
 typedef struct _yc_rule yc_rule;
461 462
 typedef struct _yc_string {
... ...
@@ -157,6 +157,9 @@ int yr_execute_code(
157 157
   int cycle = 0;
158 158
 #if REAL_YARA
159 159
   int tidx = yr_get_tidx();
160
+#else
161
+
162
+  cli_dbgmsg("yara_exec: beginning execution for lsig %i\n", aclsig->id);
160 163
 #endif
161 164
 
162 165
   #ifdef PROFILING_ENABLED
... ...
@@ -422,8 +425,7 @@ int yr_execute_code(
422 422
 #if REAL_YARA
423 423
         push(rule->t_flags[tidx] & RULE_TFLAGS_MATCH ? 1 : 0);
424 424
 #else
425
-        //tbd clamav
426
-        push(rule->g_flags & RULE_TFLAGS_MATCH ? 1 : 0);
425
+        push(acdata->yr_matches[rule->lsigid]);
427 426
 #endif
428 427
         break;
429 428
 
... ...
@@ -436,7 +438,10 @@ int yr_execute_code(
436 436
 #if REAL_YARA
437 437
           rule->t_flags[tidx] |= RULE_TFLAGS_MATCH;
438 438
 #else
439
-          rule_matches++;
439
+        {
440
+            rule_matches++;
441
+            acdata->yr_matches[aclsig->id] = 1;
442
+        }
440 443
 #endif
441 444
 
442 445
         #ifdef PROFILING_ENABLED