From f1f75e196e7421ffd5911b9823dbff59ebf58080 Mon Sep 17 00:00:00 2001 From: Tomasz Kojm Date: Mon, 26 Jun 2006 18:26:32 +0000 Subject: [PATCH] allow wildcarded prefix when signature contains static pattern of length AC_DEFAULT_DEPTH git-svn: trunk@2047 --- clamav-devel/ChangeLog | 5 ++ clamav-devel/libclamav/clamav.h | 6 +- clamav-devel/libclamav/matcher-ac.c | 49 +++++++++--- clamav-devel/libclamav/readdb.c | 112 +++++++++++++++++----------- 4 files changed, 115 insertions(+), 57 deletions(-) diff --git a/clamav-devel/ChangeLog b/clamav-devel/ChangeLog index 50d10fd60..91902a7d5 100644 --- a/clamav-devel/ChangeLog +++ b/clamav-devel/ChangeLog @@ -1,3 +1,8 @@ +Mon Jun 26 20:23:22 CEST 2006 (tk) +---------------------------------- + * libclamav: allow wildcarded prefix when signature contains static + pattern of length AC_DEFAULT_DEPTH + Sun Jun 25 14:29:22 CEST 2006 (tk) ---------------------------------- * libclamav/matcher-ac.c: fix possible false matches of alternatives diff --git a/clamav-devel/libclamav/clamav.h b/clamav-devel/libclamav/clamav.h index e8f57ba4b..398583c84 100644 --- a/clamav-devel/libclamav/clamav.h +++ b/clamav-devel/libclamav/clamav.h @@ -110,11 +110,11 @@ struct cli_bm_patt { }; struct cli_ac_patt { - short int *pattern; - unsigned int length, mindist, maxdist; + short int *pattern, *prefix; + unsigned int length, mindist, maxdist, prefix_length; char *virname, *offset; const char *viralias; - unsigned short int sigid, parts, partno, alt, *altn; + unsigned short int sigid, parts, partno, alt, *altn, alt_pattern; unsigned short type, target; char **altc; struct cli_ac_patt *next; diff --git a/clamav-devel/libclamav/matcher-ac.c b/clamav-devel/libclamav/matcher-ac.c index 9e1b935a6..c389df1e3 100644 --- a/clamav-devel/libclamav/matcher-ac.c +++ b/clamav-devel/libclamav/matcher-ac.c @@ -190,7 +190,10 @@ static void cli_freepatt(struct cli_ac_patt *list) handler = list; while(handler) { - free(handler->pattern); + if(handler->prefix) + free(handler->prefix); + else + free(handler->pattern); free(handler->virname); if(handler->offset && (!handler->sigid || handler->partno == 1)) free(handler->offset); @@ -227,8 +230,12 @@ inline static int cli_findpos(const char *buffer, unsigned int depth, unsigned i { unsigned int bufferpos = offset + depth; unsigned int postfixend = offset + length; - unsigned int i, j, alt = 0, found; + unsigned int i, j, alt = pattern->alt_pattern, found; + + if(pattern->prefix) + if(pattern->prefix_length > offset) + return 0; if(bufferpos >= length) bufferpos %= length; @@ -258,6 +265,30 @@ inline static int cli_findpos(const char *buffer, unsigned int depth, unsigned i bufferpos = 0; } + if(pattern->prefix) { + alt = 0; + bufferpos = offset - pattern->prefix_length; + + for(i = 0; i < pattern->prefix_length; i++) { + + if(pattern->prefix[i] == CLI_ALT) { + found = 0; + for(j = 0; j < pattern->altn[alt]; j++) { + if(pattern->altc[alt][j] == buffer[bufferpos]) + found = 1; + } + + if(!found) + return 0; + alt++; + + } else if(pattern->prefix[i] != CLI_IGN && (char) pattern->prefix[i] != buffer[bufferpos]) + return 0; + + bufferpos++; + } + } + return 1; } @@ -295,7 +326,7 @@ int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virnam else t = ftype; - if((fd == -1 && !t) || !cli_validatesig(t, pt->offset, offset + position, fd, pt->virname)) { + if((fd == -1 && !t) || !cli_validatesig(t, pt->offset, offset + position - pt->prefix_length, fd, pt->virname)) { pt = pt->next; continue; } @@ -305,11 +336,11 @@ int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virnam if(partcnt[pt->sigid] + 1 == pt->partno) { dist = 1; if(pt->maxdist) - if(offset + i - partoff[pt->sigid] > pt->maxdist) + if((offset + i - pt->prefix_length) - partoff[pt->sigid] > pt->maxdist) dist = 0; if(dist && pt->mindist) - if(offset + i - partoff[pt->sigid] < pt->mindist) + if((offset + i - pt->prefix_length) - partoff[pt->sigid] < pt->mindist) dist = 0; if(dist) { @@ -319,7 +350,7 @@ int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virnam if(pt->type) { if(otfrec) { if(pt->type > type || pt->type >= CL_TYPE_SFX) { - cli_dbgmsg("Matched signature for file type %s at %d\n", pt->virname, offset + position); + cli_dbgmsg("Matched signature for file type %s at %d\n", pt->virname, offset + position - pt->prefix_length); type = pt->type; if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < SFX_MAX_TESTS) && ftype == CL_TYPE_MSEXE && type >= CL_TYPE_SFX) { if(!(tnode = cli_calloc(1, sizeof(struct cli_matched_type)))) { @@ -328,7 +359,7 @@ int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virnam } tnode->type = type; - tnode->offset = offset + position; + tnode->offset = offset + position - pt->prefix_length; if(*ftoffset) tnode->cnt = (*ftoffset)->cnt + 1; @@ -355,7 +386,7 @@ int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virnam if(pt->type) { if(otfrec) { if(pt->type > type || pt->type >= CL_TYPE_SFX) { - cli_dbgmsg("Matched signature for file type %s at %d\n", pt->virname, offset + position); + cli_dbgmsg("Matched signature for file type %s at %d\n", pt->virname, offset + position - pt->prefix_length); type = pt->type; if(ftoffset && (!*ftoffset ||(*ftoffset)->cnt < SFX_MAX_TESTS) && ftype == CL_TYPE_MSEXE && type >= CL_TYPE_SFX) { if(!(tnode = cli_calloc(1, sizeof(struct cli_matched_type)))) { @@ -363,7 +394,7 @@ int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virnam return CL_EMEM; } tnode->type = type; - tnode->offset = offset + position; + tnode->offset = offset + position - pt->prefix_length; if(*ftoffset) tnode->cnt = (*ftoffset)->cnt + 1; diff --git a/clamav-devel/libclamav/readdb.c b/clamav-devel/libclamav/readdb.c index 84a78f4e7..51c088839 100644 --- a/clamav-devel/libclamav/readdb.c +++ b/clamav-devel/libclamav/readdb.c @@ -76,8 +76,16 @@ static int cli_ac_addsig(struct cli_matcher *root, const char *virname, const ch struct cli_ac_patt *new; char *pt, *hex; int virlen, ret, error = 0; - unsigned int i; - + unsigned int i, j, wprefix = 0; + +#define FREE_ALT \ + if(new->alt) { \ + free(new->altn); \ + for(i = 0; i < new->alt; i++) \ + free(new->altc[i]); \ + free(new->altc); \ + free(hex); \ + } if((new = (struct cli_ac_patt *) cli_calloc(1, sizeof(struct cli_ac_patt))) == NULL) return CL_EMEM; @@ -172,14 +180,7 @@ static int cli_ac_addsig(struct cli_matcher *root, const char *virname, const ch free(hexcpy); if(error) { - free(hexnew); - if(new->alt) { - free(new->altn); - for(i = 0; i < new->alt; i++) - if(new->altc[i]) - free(new->altc[i]); - free(new->altc); - } + FREE_ALT; free(new); return CL_EMALFDB; } @@ -187,51 +188,75 @@ static int cli_ac_addsig(struct cli_matcher *root, const char *virname, const ch } else hex = (char *) hexsig; + if((new->pattern = cli_hex2si(hex)) == NULL) { + FREE_ALT; + free(new); + return CL_EMALFDB; + } new->length = strlen(hex) / 2; - if(new->length > root->maxpatlen) - root->maxpatlen = new->length; + for(i = 0; i < AC_DEFAULT_DEPTH; i++) { + if(new->pattern[i] == CLI_IGN || new->pattern[i] == CLI_ALT) { + wprefix = 1; + break; + } + } - if((new->pattern = cli_hex2si(hex)) == NULL) { - if(new->alt) { - free(new->altn); - for(i = 0; i < new->alt; i++) - free(new->altc[i]); - free(new->altc); - free(hex); + if(wprefix) { + for(; i < new->length - AC_DEFAULT_DEPTH + 1; i++) { + wprefix = 0; + for(j = i; j < i + AC_DEFAULT_DEPTH; j++) { + if(new->pattern[j] == CLI_IGN || new->pattern[j] == CLI_ALT) { + wprefix = 1; + break; + } + } + if(!wprefix) + break; } - free(new); - return CL_EMALFDB; + + if(wprefix) { + FREE_ALT; + free(new->pattern); + free(new); + return CL_EMALFDB; + } + + new->prefix = new->pattern; + new->prefix_length = i; + new->pattern = &new->prefix[i]; + new->length -= i; + + for(i = 0; i < new->prefix_length; i++) + if(new->prefix[i] == CLI_ALT) + new->alt_pattern++; } + if(new->length > root->maxpatlen) + root->maxpatlen = new->length; + if((pt = strstr(virname, "(Clam)"))) virlen = strlen(virname) - strlen(pt) - 1; else virlen = strlen(virname); if(virlen <= 0) { - free(new->pattern); - if(new->alt) { - free(new->altn); - for(i = 0; i < new->alt; i++) - free(new->altc[i]); - free(new->altc); - free(hex); - } + if(new->prefix) + free(new->prefix); + else + free(new->pattern); + FREE_ALT; free(new); return CL_EMALFDB; } if((new->virname = cli_calloc(virlen + 1, sizeof(char))) == NULL) { - free(new->pattern); - if(new->alt) { - free(new->altn); - for(i = 0; i < new->alt; i++) - free(new->altc[i]); - free(new->altc); - free(hex); - } + if(new->prefix) + free(new->prefix); + else + free(new->pattern); + FREE_ALT; free(new); return CL_EMEM; } @@ -239,15 +264,12 @@ static int cli_ac_addsig(struct cli_matcher *root, const char *virname, const ch strncpy(new->virname, virname, virlen); if((ret = cli_ac_addpatt(root, new))) { - free(new->pattern); + if(new->prefix) + free(new->prefix); + else + free(new->pattern); free(new->virname); - if(new->alt) { - free(new->altn); - for(i = 0; i < new->alt; i++) - free(new->altc[i]); - free(new->altc); - free(hex); - } + FREE_ALT; free(new); return ret; }