Browse code

yara: added clamav hexstr verification and handling yara: handles lack of 'wide' sigopt within load_oneyara yara: upgraded some suppressed debug messages to warnings

Kevin Lin authored on 2015/03/25 06:48:54
Showing 1 changed files
... ...
@@ -3188,6 +3188,109 @@ static void ytable_delete(struct cli_ytable *ytable)
3188 3188
     }
3189 3189
 }
3190 3190
 
3191
+static int yara_subhex_verify(const char *hexstr)
3192
+{
3193
+    size_t max_sublen = 0;
3194
+    const char *track = hexstr;
3195
+    int in = 0;
3196
+
3197
+    /* REQUIRES - subpatterns must be at least length 2 */
3198
+    while (*track != '\0' && max_sublen < 4) {
3199
+        switch(*track) {
3200
+        case '*':
3201
+        case '?':
3202
+            max_sublen = 0;
3203
+            break;
3204
+        case '[':
3205
+        case '{':
3206
+            if (in) {
3207
+                cli_warnmsg("load_oneyara[verify]: string has invalid nesting\n");
3208
+                return CL_EMALFDB;
3209
+            }
3210
+            in = 1;
3211
+            break;
3212
+        case ']':
3213
+        case '}':
3214
+            if (!in) {
3215
+                cli_warnmsg("load_oneyara[verify]: string has invalid sequence close\n");
3216
+                return CL_EMALFDB;
3217
+            }
3218
+            in = 0;
3219
+            break;
3220
+        default:
3221
+            max_sublen++;
3222
+            break;
3223
+        }
3224
+
3225
+        track++;
3226
+    }
3227
+    if (in) {
3228
+        cli_warnmsg("load_oneyara[verify]: string has unterminated sequence\n");
3229
+        return CL_EMALFDB;
3230
+    }
3231
+    if (max_sublen < 4) {
3232
+        cli_warnmsg("load_oneyara[verify]: cannot find a static subpattern of length 2\n");
3233
+        return CL_EMALFDB;
3234
+    }
3235
+
3236
+    return CL_SUCCESS;
3237
+}
3238
+
3239
+static int yara_altstr_verify(const char *hexstr)
3240
+{
3241
+    cli_warnmsg("load_oneyara[verify]: string has alternating sequence\n");
3242
+    return 1;
3243
+}
3244
+
3245
+/* should only operate on HEX STRINGS */
3246
+static int yara_hexstr_verify(YR_STRING *string, const char *hexstr)
3247
+{
3248
+    int ret = CL_SUCCESS;
3249
+    char *hexcpy, *track, *alt;
3250
+
3251
+
3252
+    /* Quick Check 1: NULL String */
3253
+    if (!hexstr || !string) {
3254
+        cli_warnmsg("load_oneyara[verify]: string is empty\n");
3255
+        return CL_ENULLARG;
3256
+    }
3257
+
3258
+    /* Quick Check 2: String Too Short */
3259
+    if (strlen(hexstr)/2 < CLI_DEFAULT_AC_MINDEPTH) {
3260
+        cli_warnmsg("load_oneyara[verify]: string is too short %s\n", string->identifier);
3261
+        return CL_EMALFDB;
3262
+    }
3263
+
3264
+    /* Long Check: No Alternating Strings, Subhex must be Length 2 */
3265
+    hexcpy = cli_strdup(hexstr);
3266
+    track = hexcpy;
3267
+    while ((alt = strchr(track, '('))) {
3268
+        char *start = alt+1;
3269
+        *alt = '\0';
3270
+
3271
+        alt = strchr(start, ')');
3272
+        *alt = '\0';
3273
+
3274
+        ret = yara_subhex_verify(track);
3275
+        if (ret != CL_SUCCESS) {
3276
+            free(hexcpy);
3277
+            return ret;
3278
+        }
3279
+
3280
+        ret = yara_altstr_verify(start);
3281
+        if (ret != CL_SUCCESS) {
3282
+            free(hexcpy);
3283
+            return ret;
3284
+        }
3285
+
3286
+        track = alt+1;
3287
+    }
3288
+    ret = yara_subhex_verify(track);
3289
+    free(hexcpy);
3290
+
3291
+    return ret;
3292
+}
3293
+
3191 3294
 static unsigned int yara_total, yara_loaded, yara_malform, yara_empty, yara_complex;
3192 3295
 #define YARATARGET0 "Target:0"
3193 3296
 #define YARATARGET1 "Target:1"
... ...
@@ -3311,11 +3414,14 @@ static int load_oneyara(YR_RULE *rule, struct cl_engine *engine, unsigned int op
3311 3311
                 break;
3312 3312
             }
3313 3313
 
3314
-            if (strlen(substr)/2 < CLI_DEFAULT_AC_MINDEPTH) {
3315
-                cli_warnmsg("load_oneyara: string is too short %s\n", string->identifier);
3314
+            /* handle lack of hexstr support here in order to suppress */
3315
+            ret = yara_hexstr_verify(string, substr);
3316
+            if (ret != CL_SUCCESS) {
3316 3317
                 str_error++;
3317 3318
                 free(substr);
3318
-                continue;
3319
+                /* suppress the error */
3320
+                ret = CL_SUCCESS;
3321
+                break;
3319 3322
             }
3320 3323
 
3321 3324
             cli_yaramsg("load_oneyara: hex string: [%.*s] => [%s]\n", string->length, string->string, substr);
... ...
@@ -3384,7 +3490,7 @@ static int load_oneyara(YR_RULE *rule, struct cl_engine *engine, unsigned int op
3384 3384
         if (STRING_IS_NO_CASE(string)) {
3385 3385
             cli_yaramsg("STRING_IS_NO_CASE         %s\n", STRING_IS_SINGLE_MATCH(string) ? "yes" : "no");
3386 3386
             if ((ret = ytable_add_attrib(&ytable, NULL, "i", 1)) != CL_SUCCESS) {
3387
-                cli_yaramsg("load_oneyara: failed to add 'nocase' sigopt\n");
3387
+                cli_warnmsg("load_oneyara: failed to add 'nocase' sigopt\n");
3388 3388
                 str_error++;
3389 3389
                 break;
3390 3390
             }
... ...
@@ -3392,15 +3498,21 @@ static int load_oneyara(YR_RULE *rule, struct cl_engine *engine, unsigned int op
3392 3392
         if (STRING_IS_ASCII(string)) {
3393 3393
             cli_yaramsg("STRING_IS_ASCII           %s\n", STRING_IS_SINGLE_MATCH(string) ? "yes" : "no");
3394 3394
             if ((ret = ytable_add_attrib(&ytable, NULL, "a", 1)) != CL_SUCCESS) {
3395
-                cli_yaramsg("load_oneyara: failed to add 'ascii' sigopt\n");
3395
+                cli_warnmsg("load_oneyara: failed to add 'ascii' sigopt\n");
3396 3396
                 str_error++;
3397 3397
                 break;
3398 3398
             }
3399 3399
         }
3400 3400
         if (STRING_IS_WIDE(string)) {
3401 3401
             cli_yaramsg("STRING_IS_WIDE            %s\n", STRING_IS_SINGLE_MATCH(string) ? "yes" : "no");
3402
+            /* handle lack of 'wide' support for regex here in order to suppress */
3403
+            if (STRING_IS_REGEXP(string)) {
3404
+                cli_warnmsg("load_oneyara[verify]: wide modifier [w] is not supported for regex subsigs\n");
3405
+                str_error++;
3406
+                break;
3407
+            }
3402 3408
             if ((ret = ytable_add_attrib(&ytable, NULL, "w", 1)) != CL_SUCCESS) {
3403
-                cli_yaramsg("load_oneyara: failed to add 'wide' sigopt\n");
3409
+                cli_warnmsg("load_oneyara: failed to add 'wide' sigopt\n");
3404 3410
                 str_error++;
3405 3411
                 break;
3406 3412
             }
... ...
@@ -3408,7 +3520,7 @@ static int load_oneyara(YR_RULE *rule, struct cl_engine *engine, unsigned int op
3408 3408
         if (STRING_IS_FULL_WORD(string)) {
3409 3409
             cli_yaramsg("STRING_IS_FULL_WORD       %s\n", STRING_IS_SINGLE_MATCH(string) ? "yes" : "no");
3410 3410
             if ((ret = ytable_add_attrib(&ytable, NULL, "f", 1)) != CL_SUCCESS) {
3411
-                cli_yaramsg("load_oneyara: failed to add 'fullword' sigopt\n");
3411
+                cli_warnmsg("load_oneyara: failed to add 'fullword' sigopt\n");
3412 3412
                 str_error++;
3413 3413
                 break;
3414 3414
             }