... | ... |
@@ -229,7 +229,7 @@ int cli_sigopts_handler(struct cli_matcher *root, const char *virname, const cha |
229 | 229 |
|
230 | 230 |
/* clamav-specific wildcards need to be handled here! */ |
231 | 231 |
for (i = 0; i < strlen(hexcpy); ++i) { |
232 |
- size_t len = strlen(hexovr); |
|
232 |
+ size_t len = strlen(hexovr); |
|
233 | 233 |
|
234 | 234 |
if (hexcpy[i] == '*' || hexcpy[i] == '|' || hexcpy[i] == ')') { |
235 | 235 |
hexovr[len] = hexcpy[i]; |
... | ... |
@@ -3254,18 +3254,28 @@ static void ytable_delete(struct cli_ytable *ytable) |
3254 | 3254 |
} |
3255 | 3255 |
} |
3256 | 3256 |
|
3257 |
-static int yara_subhex_verify(const char *hexstr) |
|
3257 |
+static int yara_subhex_verify(const char *hexstr, const char *end, size_t *maxsublen) |
|
3258 | 3258 |
{ |
3259 |
- size_t max_sublen = 0; |
|
3260 |
- const char *track = hexstr; |
|
3261 |
- int in = 0; |
|
3259 |
+ size_t sublen = 0; |
|
3260 |
+ const char *track; |
|
3261 |
+ char in = 0; |
|
3262 |
+ int hexbyte = 0; |
|
3262 | 3263 |
|
3263 |
- /* REQUIRES - subpatterns must be at least length 2 */ |
|
3264 |
- while (*track != '\0' && max_sublen < 4) { |
|
3265 |
- switch(*track) { |
|
3264 |
+ if (hexstr == end) { |
|
3265 |
+ cli_warnmsg("load_oneyara[verify]: string has empty sequence\n"); |
|
3266 |
+ return CL_EMALFDB; |
|
3267 |
+ } |
|
3268 |
+ |
|
3269 |
+ track = hexstr; |
|
3270 |
+ while (track != end) { |
|
3271 |
+ switch (*track) { |
|
3266 | 3272 |
case '*': |
3267 | 3273 |
case '?': |
3268 |
- max_sublen = 0; |
|
3274 |
+ if (*track == '?') |
|
3275 |
+ hexbyte = !hexbyte; |
|
3276 |
+ if (maxsublen && (sublen > *maxsublen)) |
|
3277 |
+ *maxsublen = sublen; |
|
3278 |
+ sublen = 0; |
|
3269 | 3279 |
break; |
3270 | 3280 |
case '[': |
3271 | 3281 |
case '{': |
... | ... |
@@ -3273,71 +3283,120 @@ static int yara_subhex_verify(const char *hexstr) |
3273 | 3273 |
cli_warnmsg("load_oneyara[verify]: string has invalid nesting\n"); |
3274 | 3274 |
return CL_EMALFDB; |
3275 | 3275 |
} |
3276 |
- in = 1; |
|
3276 |
+ if (hexbyte) { |
|
3277 |
+ cli_warnmsg("load_oneyara[verify]: string has invalid hex sequence\n"); |
|
3278 |
+ return CL_EMALFDB; |
|
3279 |
+ } |
|
3280 |
+ if (maxsublen && (sublen > *maxsublen)) |
|
3281 |
+ *maxsublen = sublen; |
|
3282 |
+ sublen = 0; |
|
3283 |
+ in = *track; |
|
3277 | 3284 |
break; |
3278 | 3285 |
case ']': |
3286 |
+ if (in != '[') { |
|
3287 |
+ cli_warnmsg("load_oneyara[verify]: string has invalid ranged anchored\n"); |
|
3288 |
+ return CL_EMALFDB; |
|
3289 |
+ } |
|
3290 |
+ in = 0; |
|
3291 |
+ break; |
|
3279 | 3292 |
case '}': |
3280 |
- if (!in) { |
|
3281 |
- cli_warnmsg("load_oneyara[verify]: string has invalid sequence close\n"); |
|
3293 |
+ if (in != '{') { |
|
3294 |
+ cli_warnmsg("load_oneyara[verify]: string has invalid ranged wildcard\n"); |
|
3282 | 3295 |
return CL_EMALFDB; |
3283 | 3296 |
} |
3284 | 3297 |
in = 0; |
3285 | 3298 |
break; |
3286 | 3299 |
default: |
3287 |
- max_sublen++; |
|
3300 |
+ if (!in) { |
|
3301 |
+ if ((*track >= 'A' && *track <= 'F') || |
|
3302 |
+ (*track >= 'a' && *track <= 'f') || |
|
3303 |
+ (*track >= '0' && *track <= '9')) { |
|
3304 |
+ |
|
3305 |
+ hexbyte = !hexbyte; |
|
3306 |
+ sublen++; |
|
3307 |
+ } else { |
|
3308 |
+ cli_warnmsg("load_oneyara[verify]: unknown character: %x\n", *track); |
|
3309 |
+ return CL_EMALFDB; |
|
3310 |
+ } |
|
3311 |
+ } |
|
3288 | 3312 |
break; |
3289 | 3313 |
} |
3290 | 3314 |
|
3291 | 3315 |
track++; |
3292 | 3316 |
} |
3317 |
+ |
|
3293 | 3318 |
if (in) { |
3294 |
- cli_warnmsg("load_oneyara[verify]: string has unterminated sequence\n"); |
|
3319 |
+ cli_warnmsg("load_oneyara[verify]: string has unterminated wildcard sequence\n"); |
|
3295 | 3320 |
return CL_EMALFDB; |
3296 | 3321 |
} |
3297 |
- if (max_sublen < 4) { |
|
3298 |
- cli_warnmsg("load_oneyara[verify]: cannot find a static subpattern of length 2\n"); |
|
3322 |
+ if (hexbyte) { |
|
3323 |
+ cli_warnmsg("load_oneyara[verify]: string has invalid hex sequence\n"); |
|
3299 | 3324 |
return CL_EMALFDB; |
3300 | 3325 |
} |
3326 |
+ if (maxsublen && (sublen > *maxsublen)) |
|
3327 |
+ *maxsublen = sublen; |
|
3301 | 3328 |
|
3302 | 3329 |
return CL_SUCCESS; |
3303 | 3330 |
} |
3304 | 3331 |
|
3305 |
-static int yara_altstr_verify(const char *hexstr) |
|
3332 |
+static int yara_altstr_verify(const char *hexstr, int lvl, const char **end) |
|
3306 | 3333 |
{ |
3307 |
- const char *end; |
|
3308 |
- int i, range, lvl = 0; |
|
3309 |
- |
|
3310 |
- for (i = 0; i < strlen(hexstr); i++) { |
|
3311 |
- if (hexstr[i] == '(') { |
|
3312 |
- lvl++; |
|
3313 |
- if (lvl > ACPATT_ALTN_MAXNEST) { |
|
3314 |
- cli_warnmsg("load_oneyara[verify]: string has unsupported alternating sequence (nest level)\n"); |
|
3315 |
- return CL_EMALFDB; |
|
3316 |
- } |
|
3317 |
- } else if (hexstr[i] == ')') { |
|
3318 |
- if (!lvl) { |
|
3319 |
- break; |
|
3320 |
- } |
|
3321 |
- } else if (hexstr[i] == '{') { /* clamav converted '[' */ |
|
3322 |
- end = &hexstr[i]; |
|
3323 |
- while (*end != '}' && *end != '-' && *end != '\0') |
|
3324 |
- end++; |
|
3334 |
+ const char *track, *sub; |
|
3335 |
+ int ret, range; |
|
3336 |
+ size_t offset; |
|
3325 | 3337 |
|
3326 |
- switch (*end) { |
|
3327 |
- case '\0': |
|
3328 |
- cli_warnmsg("load_oneyara[verify]: string has unsupported alternating sequence (unterminated ranged wildcard)\n"); |
|
3329 |
- return CL_EMALFDB; |
|
3330 |
- case '-': |
|
3331 |
- cli_warnmsg("load_oneyara[verify]: string has unsupported alternating sequence (variable ranged wildcard)\n"); |
|
3332 |
- return CL_EMALFDB; |
|
3333 |
- case '}': |
|
3334 |
- sscanf(&hexstr[i], "{%d}", &range); |
|
3335 |
- if (range >= 128) { |
|
3336 |
- cli_warnmsg("load_oneyara[verify]: string has unsupported alternating sequence (128+ ranged wildcard)\n"); |
|
3338 |
+ if (lvl > ACPATT_ALTN_MAXNEST) { |
|
3339 |
+ cli_warnmsg("load_oneyara[verify]: string has unsupported alternate sequence (nest level)\n"); |
|
3340 |
+ return CL_EMALFDB; |
|
3341 |
+ } |
|
3342 |
+ |
|
3343 |
+ track = hexstr; |
|
3344 |
+ while ((offset = strcspn(track, "(|){}"))) { |
|
3345 |
+ sub = track + offset; |
|
3346 |
+ if (*sub == '\0') { |
|
3347 |
+ cli_warnmsg("load_oneyara[verify]: string has unterminated alternate sequence\n"); |
|
3348 |
+ return CL_EMALFDB; |
|
3349 |
+ } |
|
3350 |
+ |
|
3351 |
+ /* verify subhex */ |
|
3352 |
+ if ((ret = yara_subhex_verify(track, sub, NULL)) != CL_SUCCESS) |
|
3353 |
+ return ret; |
|
3354 |
+ |
|
3355 |
+ track = sub; |
|
3356 |
+ if (*track == '(') { |
|
3357 |
+ if ((ret = yara_altstr_verify(track+1, lvl+1, &sub)) != CL_SUCCESS) |
|
3358 |
+ return ret; |
|
3359 |
+ } else if (*track == ')') { |
|
3360 |
+ if (end) |
|
3361 |
+ *end = track; |
|
3362 |
+ break; |
|
3363 |
+ } else if (*track == '{') { /* clamav converted '[' */ |
|
3364 |
+ if ((offset = strcspn(track, "}-"))) { |
|
3365 |
+ sub = track + offset; |
|
3366 |
+ switch (*sub) { |
|
3367 |
+ case '\0': |
|
3368 |
+ cli_warnmsg("load_oneyara[verify]: string has unsupported alternating sequence (unterminated ranged wildcard)\n"); |
|
3337 | 3369 |
return CL_EMALFDB; |
3370 |
+ case '-': |
|
3371 |
+ cli_warnmsg("load_oneyara[verify]: string has unsupported alternating sequence (variable ranged wildcard)\n"); |
|
3372 |
+ return CL_EMALFDB; |
|
3373 |
+ case '}': |
|
3374 |
+ sscanf(track, "{%d}", &range); |
|
3375 |
+ if (range >= 128) { |
|
3376 |
+ cli_warnmsg("load_oneyara[verify]: string has unsupported alternating sequence (128+ ranged wildcard)\n"); |
|
3377 |
+ return CL_EMALFDB; |
|
3378 |
+ } |
|
3338 | 3379 |
} |
3380 |
+ } else { |
|
3381 |
+ cli_warnmsg("load_oneyara[verify]: string has unsupported alternating sequence (unterminated ranged wildcard)\n"); |
|
3382 |
+ return CL_EMALFDB; |
|
3339 | 3383 |
} |
3384 |
+ } else if (*track != '|') { |
|
3385 |
+ cli_warnmsg("load_oneyara[verify]: string has unsupported alternating sequence (invalid sequence)\n"); |
|
3386 |
+ return CL_EMALFDB; |
|
3340 | 3387 |
} |
3388 |
+ |
|
3389 |
+ track = ++sub; |
|
3341 | 3390 |
} |
3342 | 3391 |
|
3343 | 3392 |
return CL_SUCCESS; |
... | ... |
@@ -3347,7 +3406,8 @@ static int yara_altstr_verify(const char *hexstr) |
3347 | 3347 |
static int yara_hexstr_verify(YR_STRING *string, const char *hexstr) |
3348 | 3348 |
{ |
3349 | 3349 |
int ret = CL_SUCCESS; |
3350 |
- char *hexcpy, *track, *alt; |
|
3350 |
+ const char *track, *end; |
|
3351 |
+ size_t maxsublen = 0, length; |
|
3351 | 3352 |
|
3352 | 3353 |
/* Quick Check 1: NULL String */ |
3353 | 3354 |
if (!hexstr || !string) { |
... | ... |
@@ -3362,35 +3422,33 @@ static int yara_hexstr_verify(YR_STRING *string, const char *hexstr) |
3362 | 3362 |
} |
3363 | 3363 |
|
3364 | 3364 |
/* Long Check: No Alternating Strings, Subhex must be Length 2 */ |
3365 |
- hexcpy = cli_strdup(hexstr); |
|
3366 |
- if (!hexcpy) |
|
3367 |
- return CL_EMEM; |
|
3368 |
- track = hexcpy; |
|
3369 |
- while ((alt = strchr(track, '('))) { |
|
3370 |
- char *start = alt+1; |
|
3371 |
- *alt = '\0'; |
|
3372 |
- |
|
3373 |
- alt = strchr(start, ')'); |
|
3374 |
- *alt = '\0'; |
|
3365 |
+ track = hexstr; |
|
3366 |
+ while ((end = strchr(track, '('))) { |
|
3367 |
+ if (track != end) { |
|
3368 |
+ if ((ret = yara_subhex_verify(track, end, &maxsublen)) != CL_SUCCESS) |
|
3369 |
+ return ret; |
|
3370 |
+ } |
|
3375 | 3371 |
|
3376 |
- ret = yara_subhex_verify(track); |
|
3377 |
- if (ret != CL_SUCCESS) { |
|
3378 |
- free(hexcpy); |
|
3372 |
+ track = end + 1; |
|
3373 |
+ if ((ret = yara_altstr_verify(track, 0, &end)) != CL_SUCCESS) |
|
3379 | 3374 |
return ret; |
3380 |
- } |
|
3381 | 3375 |
|
3382 |
- ret = yara_altstr_verify(start); |
|
3383 |
- if (ret != CL_SUCCESS) { |
|
3384 |
- free(hexcpy); |
|
3376 |
+ track = end + 1; |
|
3377 |
+ } |
|
3378 |
+ |
|
3379 |
+ /* Check: Suffix (or Non-Alt Hex) */ |
|
3380 |
+ length = strlen(track); |
|
3381 |
+ if (length > 0) |
|
3382 |
+ if ((ret = yara_subhex_verify(track, track + length, &maxsublen)) != CL_SUCCESS) |
|
3385 | 3383 |
return ret; |
3386 |
- } |
|
3387 | 3384 |
|
3388 |
- track = alt+1; |
|
3385 |
+ /* REQUIRES - Subpatterns must be at least length 2 */ |
|
3386 |
+ if (maxsublen < 2) { |
|
3387 |
+ cli_warnmsg("load_oneyara[verify]: cannot find a static subpattern of length 2\n"); |
|
3388 |
+ return CL_EMALFDB; |
|
3389 | 3389 |
} |
3390 |
- ret = yara_subhex_verify(track); |
|
3391 |
- free(hexcpy); |
|
3392 | 3390 |
|
3393 |
- return ret; |
|
3391 |
+ return CL_SUCCESS; |
|
3394 | 3392 |
} |
3395 | 3393 |
|
3396 | 3394 |
static unsigned int yara_total, yara_loaded, yara_malform, yara_empty, yara_complex; |