git-svn: trunk@3588
Tomasz Kojm authored on 2008/02/06 21:26:16... | ... |
@@ -1,3 +1,9 @@ |
1 |
+Wed Feb 6 13:12:24 CET 2008 (tk) |
|
2 |
+--------------------------------- |
|
3 |
+ * libclamav/matcher-ac.[ch]: add support for matching single bytes anchored |
|
4 |
+ to sub-signatures (see bb#776 for details) |
|
5 |
+ * libclamav/others.h: bump f-level |
|
6 |
+ |
|
1 | 7 |
Wed Feb 6 14:07:45 EET 2008 (edwin) |
2 | 8 |
------------------------------------ |
3 | 9 |
* libclamav/regex_list.c: fix -pedantic warning. |
... | ... |
@@ -1,4 +1,7 @@ |
1 | 1 |
/* |
2 |
+ * Copyright (C) 2007 - 2008 Sourcefire, Inc. |
|
3 |
+ * Author: Tomasz Kojm <tkojm@clamav.net> |
|
4 |
+ * |
|
2 | 5 |
* Copyright (C) 2002 - 2007 Tomasz Kojm <tkojm@clamav.net> |
3 | 6 |
* |
4 | 7 |
* This program is free software; you can redistribute it and/or modify |
... | ... |
@@ -341,11 +344,7 @@ void cli_ac_free(struct cli_matcher *root) |
341 | 341 |
|
342 | 342 |
for(i = 0; i < root->ac_patterns; i++) { |
343 | 343 |
patt = root->ac_pattable[i]; |
344 |
- |
|
345 |
- if(patt->prefix) |
|
346 |
- free(patt->prefix); |
|
347 |
- else |
|
348 |
- free(patt->pattern); |
|
344 |
+ patt->prefix ? free(patt->prefix) : free(patt->pattern); |
|
349 | 345 |
free(patt->virname); |
350 | 346 |
if(patt->offset) |
351 | 347 |
free(patt->offset); |
... | ... |
@@ -383,19 +382,19 @@ void cli_ac_free(struct cli_matcher *root) |
383 | 383 |
switch(wc = p & CLI_MATCH_WILDCARD) { \ |
384 | 384 |
case CLI_MATCH_CHAR: \ |
385 | 385 |
if((unsigned char) p != b) \ |
386 |
- return 0; \ |
|
386 |
+ match = 0; \ |
|
387 | 387 |
break; \ |
388 | 388 |
\ |
389 | 389 |
case CLI_MATCH_IGNORE: \ |
390 | 390 |
break; \ |
391 | 391 |
\ |
392 | 392 |
case CLI_MATCH_ALTERNATIVE: \ |
393 |
- found = 0; \ |
|
393 |
+ match = 0; \ |
|
394 | 394 |
alt = pattern->alttable[altcnt]; \ |
395 | 395 |
if(alt->chmode) { \ |
396 | 396 |
for(j = 0; j < alt->num; j++) { \ |
397 | 397 |
if(alt->str[j] == b) { \ |
398 |
- found = 1; \ |
|
398 |
+ match = 1; \ |
|
399 | 399 |
break; \ |
400 | 400 |
} \ |
401 | 401 |
} \ |
... | ... |
@@ -403,7 +402,7 @@ void cli_ac_free(struct cli_matcher *root) |
403 | 403 |
while(alt) { \ |
404 | 404 |
if(bp + alt->len <= length) { \ |
405 | 405 |
if(!memcmp(&buffer[bp], alt->str, alt->len)) { \ |
406 |
- found = 1; \ |
|
406 |
+ match = 1; \ |
|
407 | 407 |
bp += alt->len - 1; \ |
408 | 408 |
break; \ |
409 | 409 |
} \ |
... | ... |
@@ -411,31 +410,28 @@ void cli_ac_free(struct cli_matcher *root) |
411 | 411 |
alt = alt->next; \ |
412 | 412 |
} \ |
413 | 413 |
} \ |
414 |
- if(!found) \ |
|
415 |
- return 0; \ |
|
416 | 414 |
altcnt++; \ |
417 | 415 |
break; \ |
418 | 416 |
\ |
419 | 417 |
case CLI_MATCH_NIBBLE_HIGH: \ |
420 | 418 |
if((unsigned char) (p & 0x00f0) != (b & 0xf0)) \ |
421 |
- return 0; \ |
|
419 |
+ match = 0; \ |
|
422 | 420 |
break; \ |
423 | 421 |
\ |
424 | 422 |
case CLI_MATCH_NIBBLE_LOW: \ |
425 | 423 |
if((unsigned char) (p & 0x000f) != (b & 0x0f)) \ |
426 |
- return 0; \ |
|
424 |
+ match = 0; \ |
|
427 | 425 |
break; \ |
428 | 426 |
\ |
429 | 427 |
default: \ |
430 | 428 |
cli_errmsg("ac_findmatch: Unknown wildcard 0x%x\n", wc); \ |
431 |
- return 0; \ |
|
429 |
+ match = 0; \ |
|
432 | 430 |
} |
433 | 431 |
|
434 | 432 |
inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uint32_t length, const struct cli_ac_patt *pattern, uint32_t *end) |
435 | 433 |
{ |
436 |
- uint32_t bp; |
|
434 |
+ uint32_t bp, match; |
|
437 | 435 |
uint16_t wc, i, j, altcnt = pattern->alt_pattern; |
438 |
- uint8_t found; |
|
439 | 436 |
struct cli_ac_alt *alt; |
440 | 437 |
|
441 | 438 |
|
... | ... |
@@ -444,22 +440,61 @@ inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uin |
444 | 444 |
|
445 | 445 |
bp = offset + pattern->depth; |
446 | 446 |
|
447 |
+ match = 1; |
|
447 | 448 |
for(i = pattern->depth; i < pattern->length && bp < length; i++) { |
448 | 449 |
AC_MATCH_CHAR(pattern->pattern[i],buffer[bp]); |
450 |
+ if(!match) |
|
451 |
+ return 0; |
|
449 | 452 |
bp++; |
450 | 453 |
} |
451 | 454 |
*end = bp; |
452 | 455 |
|
456 |
+ if(!(pattern->ch[1] & CLI_MATCH_IGNORE)) { |
|
457 |
+ bp += pattern->ch_mindist[1]; |
|
458 |
+ for(i = pattern->ch_mindist[1]; i <= pattern->ch_maxdist[1]; i++) { |
|
459 |
+ if(bp >= length) |
|
460 |
+ return 0; |
|
461 |
+ match = 1; |
|
462 |
+ AC_MATCH_CHAR(pattern->ch[1],buffer[bp]); |
|
463 |
+ if(match) |
|
464 |
+ break; |
|
465 |
+ bp++; |
|
466 |
+ } |
|
467 |
+ if(!match) |
|
468 |
+ return 0; |
|
469 |
+ } |
|
470 |
+ |
|
453 | 471 |
if(pattern->prefix) { |
454 | 472 |
altcnt = 0; |
455 | 473 |
bp = offset - pattern->prefix_length; |
456 |
- |
|
474 |
+ match = 1; |
|
457 | 475 |
for(i = 0; i < pattern->prefix_length; i++) { |
458 | 476 |
AC_MATCH_CHAR(pattern->prefix[i],buffer[bp]); |
477 |
+ if(!match) |
|
478 |
+ return 0; |
|
459 | 479 |
bp++; |
460 | 480 |
} |
461 | 481 |
} |
462 | 482 |
|
483 |
+ if(!(pattern->ch[0] & CLI_MATCH_IGNORE)) { |
|
484 |
+ bp = offset - pattern->prefix_length; |
|
485 |
+ if(pattern->ch_mindist[0] + 1 > bp) |
|
486 |
+ return 0; |
|
487 |
+ bp -= pattern->ch_mindist[0] + 1; |
|
488 |
+ for(i = pattern->ch_mindist[0]; i <= pattern->ch_maxdist[0]; i++) { |
|
489 |
+ match = 1; |
|
490 |
+ AC_MATCH_CHAR(pattern->ch[0],buffer[bp]); |
|
491 |
+ if(match) |
|
492 |
+ break; |
|
493 |
+ if(!bp) |
|
494 |
+ return 0; |
|
495 |
+ else |
|
496 |
+ bp--; |
|
497 |
+ } |
|
498 |
+ if(!match) |
|
499 |
+ return 0; |
|
500 |
+ } |
|
501 |
+ |
|
463 | 502 |
return 1; |
464 | 503 |
} |
465 | 504 |
|
... | ... |
@@ -707,8 +742,8 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v |
707 | 707 |
int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, uint32_t sigid, uint16_t parts, uint16_t partno, uint16_t type, uint32_t mindist, uint32_t maxdist, const char *offset, uint8_t target) |
708 | 708 |
{ |
709 | 709 |
struct cli_ac_patt *new; |
710 |
- char *pt, *hex = NULL; |
|
711 |
- uint16_t i, j, ppos = 0, pend; |
|
710 |
+ char *pt, *pt2, *hex = NULL, *hexcpy = NULL; |
|
711 |
+ uint16_t i, j, ppos = 0, pend, *dec; |
|
712 | 712 |
uint8_t wprefix = 0, zprefix = 1, namelen, plen = 0; |
713 | 713 |
struct cli_ac_alt *newalt, *altpt, **newtable; |
714 | 714 |
int ret, error = CL_SUCCESS; |
... | ... |
@@ -727,11 +762,94 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex |
727 | 727 |
new->mindist = mindist; |
728 | 728 |
new->maxdist = maxdist; |
729 | 729 |
new->target = target; |
730 |
+ new->ch[0] |= CLI_MATCH_IGNORE; |
|
731 |
+ new->ch[1] |= CLI_MATCH_IGNORE; |
|
732 |
+ |
|
733 |
+ if(strchr(hexsig, '[')) { |
|
734 |
+ if(!(hexcpy = cli_strdup(hexsig))) { |
|
735 |
+ free(new); |
|
736 |
+ return CL_EMEM; |
|
737 |
+ } |
|
738 |
+ |
|
739 |
+ hex = hexcpy; |
|
740 |
+ for(i = 0; i < 2; i++) { |
|
741 |
+ unsigned int n1, n2; |
|
742 |
+ |
|
743 |
+ if(!(pt = strchr(hex, '['))) |
|
744 |
+ break; |
|
745 |
+ *pt++ = 0; |
|
746 |
+ |
|
747 |
+ if(!(pt2 = strchr(pt, ']'))) { |
|
748 |
+ cli_dbgmsg("cli_ac_addsig: missing closing square bracket\n"); |
|
749 |
+ error = CL_EMALFDB; |
|
750 |
+ break; |
|
751 |
+ } |
|
752 |
+ *pt2++ = 0; |
|
753 |
+ |
|
754 |
+ if(sscanf(pt, "%u-%u", &n1, &n2) != 2) { |
|
755 |
+ cli_dbgmsg("cli_ac_addsig: incorrect range inside square brackets\n"); |
|
756 |
+ error = CL_EMALFDB; |
|
757 |
+ break; |
|
758 |
+ } |
|
759 |
+ |
|
760 |
+ if((n1 > n2) || (n2 > AC_CH_MAXDIST)) { |
|
761 |
+ cli_dbgmsg("cli_ac_addsig: incorrect range inside square brackets\n"); |
|
762 |
+ error = CL_EMALFDB; |
|
763 |
+ break; |
|
764 |
+ } |
|
765 |
+ |
|
766 |
+ if(strlen(hex) == 2) { |
|
767 |
+ if(i) { |
|
768 |
+ error = CL_EMALFDB; |
|
769 |
+ break; |
|
770 |
+ } |
|
771 |
+ dec = cli_hex2ui(hex); |
|
772 |
+ if(!dec) { |
|
773 |
+ error = CL_EMALFDB; |
|
774 |
+ break; |
|
775 |
+ } |
|
776 |
+ new->ch[i] = *dec; |
|
777 |
+ free(dec); |
|
778 |
+ new->ch_mindist[i] = n1; |
|
779 |
+ new->ch_maxdist[i] = n2; |
|
780 |
+ hex = pt2; |
|
781 |
+ } else if(strlen(pt2) == 2) { |
|
782 |
+ i = 1; |
|
783 |
+ dec = cli_hex2ui(pt2); |
|
784 |
+ if(!dec) { |
|
785 |
+ error = CL_EMALFDB; |
|
786 |
+ break; |
|
787 |
+ } |
|
788 |
+ new->ch[i] = *dec; |
|
789 |
+ free(dec); |
|
790 |
+ new->ch_mindist[i] = n1; |
|
791 |
+ new->ch_maxdist[i] = n2; |
|
792 |
+ } else { |
|
793 |
+ error = CL_EMALFDB; |
|
794 |
+ break; |
|
795 |
+ } |
|
796 |
+ } |
|
797 |
+ |
|
798 |
+ if(error) { |
|
799 |
+ free(hexcpy); |
|
800 |
+ free(new); |
|
801 |
+ return error; |
|
802 |
+ } |
|
803 |
+ |
|
804 |
+ hex = cli_strdup(hex); |
|
805 |
+ free(hexcpy); |
|
806 |
+ if(!hex) { |
|
807 |
+ free(new); |
|
808 |
+ return CL_EMEM; |
|
809 |
+ } |
|
810 |
+ } |
|
730 | 811 |
|
731 | 812 |
if(strchr(hexsig, '(')) { |
732 |
- char *hexcpy, *hexnew, *start, *h, *c; |
|
813 |
+ char *hexnew, *start, *h, *c; |
|
733 | 814 |
|
734 |
- if(!(hexcpy = cli_strdup(hexsig))) { |
|
815 |
+ if(hex) { |
|
816 |
+ hexcpy = hex; |
|
817 |
+ } else if(!(hexcpy = cli_strdup(hexsig))) { |
|
735 | 818 |
free(new); |
736 | 819 |
return CL_EMEM; |
737 | 820 |
} |
... | ... |
@@ -860,17 +978,15 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex |
860 | 860 |
} |
861 | 861 |
} |
862 | 862 |
|
863 |
- if((new->pattern = cli_hex2ui(new->alt ? hex : hexsig)) == NULL) { |
|
864 |
- if(new->alt) { |
|
865 |
- free(hex); |
|
863 |
+ if((new->pattern = cli_hex2ui(hex ? hex : hexsig)) == NULL) { |
|
864 |
+ if(new->alt) |
|
866 | 865 |
ac_free_alt(new); |
867 |
- } |
|
866 |
+ free(hex); |
|
868 | 867 |
free(new); |
869 | 868 |
return CL_EMALFDB; |
870 | 869 |
} |
871 |
- new->length = strlen(new->alt ? hex : hexsig) / 2; |
|
872 |
- if(new->alt) |
|
873 |
- free(hex); |
|
870 |
+ new->length = strlen(hex ? hex : hexsig) / 2; |
|
871 |
+ free(hex); |
|
874 | 872 |
|
875 | 873 |
for(i = 0; i < root->ac_maxdepth && i < new->length; i++) { |
876 | 874 |
if(new->pattern[i] & CLI_MATCH_WILDCARD) { |
... | ... |
@@ -928,20 +1044,14 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex |
928 | 928 |
|
929 | 929 |
if(!namelen) { |
930 | 930 |
cli_errmsg("cli_ac_addsig: No virus name\n"); |
931 |
- if(new->prefix) |
|
932 |
- free(new->prefix); |
|
933 |
- else |
|
934 |
- free(new->pattern); |
|
931 |
+ new->prefix ? free(new->prefix) : free(new->pattern); |
|
935 | 932 |
ac_free_alt(new); |
936 | 933 |
free(new); |
937 | 934 |
return CL_EMALFDB; |
938 | 935 |
} |
939 | 936 |
|
940 | 937 |
if((new->virname = cli_calloc(namelen + 1, sizeof(char))) == NULL) { |
941 |
- if(new->prefix) |
|
942 |
- free(new->prefix); |
|
943 |
- else |
|
944 |
- free(new->pattern); |
|
938 |
+ new->prefix ? free(new->prefix) : free(new->pattern); |
|
945 | 939 |
ac_free_alt(new); |
946 | 940 |
free(new); |
947 | 941 |
return CL_EMEM; |
... | ... |
@@ -951,10 +1061,7 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex |
951 | 951 |
if(offset) { |
952 | 952 |
new->offset = cli_strdup(offset); |
953 | 953 |
if(!new->offset) { |
954 |
- if(new->prefix) |
|
955 |
- free(new->prefix); |
|
956 |
- else |
|
957 |
- free(new->pattern); |
|
954 |
+ new->prefix ? free(new->prefix) : free(new->pattern); |
|
958 | 955 |
ac_free_alt(new); |
959 | 956 |
free(new->virname); |
960 | 957 |
free(new); |
... | ... |
@@ -963,10 +1070,7 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex |
963 | 963 |
} |
964 | 964 |
|
965 | 965 |
if((ret = cli_ac_addpatt(root, new))) { |
966 |
- if(new->prefix) |
|
967 |
- free(new->prefix); |
|
968 |
- else |
|
969 |
- free(new->pattern); |
|
966 |
+ new->prefix ? free(new->prefix) : free(new->pattern); |
|
970 | 967 |
free(new->virname); |
971 | 968 |
ac_free_alt(new); |
972 | 969 |
if(new->offset) |
... | ... |
@@ -1,4 +1,7 @@ |
1 | 1 |
/* |
2 |
+ * Copyright (C) 2007 - 2008 Sourcefire, Inc. |
|
3 |
+ * Author: Tomasz Kojm <tkojm@clamav.net> |
|
4 |
+ * |
|
2 | 5 |
* Copyright (C) 2002 - 2007 Tomasz Kojm <tkojm@clamav.net> |
3 | 6 |
* |
4 | 7 |
* This program is free software; you can redistribute it and/or modify |
... | ... |
@@ -27,6 +30,7 @@ |
27 | 27 |
#define AC_DEFAULT_MIN_DEPTH 2 |
28 | 28 |
#define AC_DEFAULT_MAX_DEPTH 3 |
29 | 29 |
#define AC_DEFAULT_TRACKLEN 8 |
30 |
+#define AC_CH_MAXDIST 32 |
|
30 | 31 |
extern uint8_t cli_ac_mindepth, cli_ac_maxdepth; |
31 | 32 |
|
32 | 33 |
struct cli_ac_data { |
... | ... |
@@ -46,6 +50,9 @@ struct cli_ac_patt { |
46 | 46 |
uint32_t mindist, maxdist; |
47 | 47 |
uint32_t sigid; |
48 | 48 |
char *virname, *offset; |
49 |
+ uint16_t ch[2]; |
|
50 |
+ uint16_t ch_mindist[2]; |
|
51 |
+ uint16_t ch_maxdist[2]; |
|
49 | 52 |
uint16_t parts, partno, alt, alt_pattern; |
50 | 53 |
struct cli_ac_alt **alttable; |
51 | 54 |
struct cli_ac_patt *next, *next_same; |
... | ... |
@@ -88,7 +88,7 @@ static pthread_mutex_t cli_ctime_mutex = PTHREAD_MUTEX_INITIALIZER; |
88 | 88 |
#define P_tmpdir "C:\\WINDOWS\\TEMP" |
89 | 89 |
#endif |
90 | 90 |
|
91 |
-#define CL_FLEVEL 25 /* don't touch it */ |
|
91 |
+#define CL_FLEVEL 27 /* don't touch it */ |
|
92 | 92 |
|
93 | 93 |
uint8_t cli_debug_flag = 0, cli_leavetemps_flag = 0; |
94 | 94 |
|