allow wildcarded prefix when signature contains static pattern of length AC_DEFAULT_DEPTH

git-svn: trunk@2047
remotes/push_mirror/metadata
Tomasz Kojm 19 years ago
parent 4241382468
commit f1f75e196e
  1. 5
      clamav-devel/ChangeLog
  2. 6
      clamav-devel/libclamav/clamav.h
  3. 49
      clamav-devel/libclamav/matcher-ac.c
  4. 112
      clamav-devel/libclamav/readdb.c

@ -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

@ -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;

@ -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;

@ -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;
}

Loading…
Cancel
Save