add support for signature based self-protection mode

git-svn: trunk@1831
remotes/push_mirror/metadata
Tomasz Kojm 20 years ago
parent e203ef98e7
commit 555c5390cc
  1. 4
      clamav-devel/ChangeLog
  2. 1
      clamav-devel/libclamav/clamav.h
  3. 2
      clamav-devel/libclamav/matcher-ac.c
  4. 2
      clamav-devel/libclamav/matcher-ac.h
  5. 2
      clamav-devel/libclamav/matcher.c
  6. 2
      clamav-devel/libclamav/matcher.h
  7. 2
      clamav-devel/libclamav/others.c
  8. 35
      clamav-devel/libclamav/readdb.c
  9. 169
      clamav-devel/libclamav/scanners.c

@ -1,3 +1,7 @@
Wed Jan 25 13:09:19 CET 2006 (tk)
---------------------------------
* libclamav: add support for signature based self-protection mode
Tue Jan 24 16:52:21 CET 2006 (tk) Tue Jan 24 16:52:21 CET 2006 (tk)
--------------------------------- ---------------------------------
* libclamav/unrar: fix compilation error on old linux systems * libclamav/unrar: fix compilation error on old linux systems

@ -150,6 +150,7 @@ struct cli_matcher {
struct cl_engine { struct cl_engine {
unsigned int refcount; /* reference counter */ unsigned int refcount; /* reference counter */
unsigned short hwaccel; unsigned short hwaccel;
unsigned short sdb;
/* Roots table */ /* Roots table */
struct cli_matcher **root; struct cli_matcher **root;

@ -260,7 +260,7 @@ inline static int cli_findpos(const char *buffer, unsigned int depth, unsigned i
return 1; return 1;
} }
int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cli_matcher *root, int *partcnt, short otfrec, unsigned long int offset, unsigned long int *partoff, unsigned short ftype, int fd, struct cli_matched_type **ftoffset) int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cli_matcher *root, int *partcnt, unsigned short otfrec, unsigned long int offset, unsigned long int *partoff, unsigned short ftype, int fd, struct cli_matched_type **ftoffset)
{ {
struct cli_ac_node *current; struct cli_ac_node *current;
struct cli_ac_patt *pt; struct cli_ac_patt *pt;

@ -26,7 +26,7 @@
#define AC_DEFAULT_DEPTH 2 #define AC_DEFAULT_DEPTH 2
int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern); int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern);
int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cli_matcher *root, int *partcnt, short otfrec, unsigned long int offset, unsigned long int *partoff, unsigned short ftype, int fd, struct cli_matched_type **ftoffset); int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cli_matcher *root, int *partcnt, unsigned short otfrec, unsigned long int offset, unsigned long int *partoff, unsigned short ftype, int fd, struct cli_matched_type **ftoffset);
int cli_ac_buildtrie(struct cli_matcher *root); int cli_ac_buildtrie(struct cli_matcher *root);
void cli_ac_free(struct cli_matcher *root); void cli_ac_free(struct cli_matcher *root);
void cli_ac_setdepth(unsigned int depth); void cli_ac_setdepth(unsigned int depth);

@ -274,7 +274,7 @@ int cli_validatesig(unsigned short target, unsigned short ftype, const char *off
return 1; return 1;
} }
int cli_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, short otfrec, unsigned short ftype, struct cli_matched_type **ftoffset) int cli_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned short otfrec, unsigned short ftype, struct cli_matched_type **ftoffset)
{ {
char *buffer, *buff, *endbl, *pt; char *buffer, *buff, *endbl, *pt;
int bytes, buffsize, length, ret, *gpartcnt, *tpartcnt; int bytes, buffsize, length, ret, *gpartcnt, *tpartcnt;

@ -24,7 +24,7 @@
#define CL_TARGET_TABLE_SIZE 7 #define CL_TARGET_TABLE_SIZE 7
int cli_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, short otfrec, unsigned short ftype, struct cli_matched_type **ftoffset); int cli_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned short otfrec, unsigned short ftype, struct cli_matched_type **ftoffset);
int cli_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_engine *engine, unsigned short ftype); int cli_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_engine *engine, unsigned short ftype);

@ -72,7 +72,7 @@ static pthread_mutex_t cli_gentempname_mutex = PTHREAD_MUTEX_INITIALIZER;
#define O_BINARY 0 #define O_BINARY 0
#endif #endif
#define CL_FLEVEL 6 /* don't touch it */ #define CL_FLEVEL 7 /* don't touch it */
#define MAX_ALLOCATION 134217728 #define MAX_ALLOCATION 134217728

@ -557,7 +557,7 @@ static int cli_loaddb(FILE *fd, struct cl_engine **engine, unsigned int *signo,
return 0; return 0;
} }
static int cli_loadndb(FILE *fd, struct cl_engine **engine, unsigned int *signo, unsigned int options) static int cli_loadndb(FILE *fd, struct cl_engine **engine, unsigned int *signo, unsigned short sdb, unsigned int options)
{ {
char buffer[FILEBUFF], *sig, *virname, *offset, *pt; char buffer[FILEBUFF], *sig, *virname, *offset, *pt;
struct cli_matcher *root; struct cli_matcher *root;
@ -594,7 +594,7 @@ static int cli_loadndb(FILE *fd, struct cl_engine **engine, unsigned int *signo,
break; break;
} }
if((pt = cli_strtok(buffer, 4, ":"))) { if((pt = cli_strtok(buffer, 4, ":"))) { /* min version */
if(!isdigit(*pt)) { if(!isdigit(*pt)) {
free(virname); free(virname);
free(pt); free(pt);
@ -611,6 +611,24 @@ static int cli_loadndb(FILE *fd, struct cl_engine **engine, unsigned int *signo,
} }
free(pt); free(pt);
if((pt = cli_strtok(buffer, 5, ":"))) { /* max version */
if(!isdigit(*pt)) {
free(virname);
free(pt);
ret = CL_EMALFDB;
break;
}
if(atoi(pt) < cl_retflevel()) {
sigs--;
free(virname);
free(pt);
continue;
}
free(pt);
}
} }
if(!(pt = cli_strtok(buffer, 1, ":")) || !isdigit(*pt)) { if(!(pt = cli_strtok(buffer, 1, ":")) || !isdigit(*pt)) {
@ -677,6 +695,11 @@ static int cli_loadndb(FILE *fd, struct cl_engine **engine, unsigned int *signo,
if(signo) if(signo)
*signo += sigs; *signo += sigs;
if(sdb && sigs && !(*engine)->sdb) {
(*engine)->sdb = 1;
cli_dbgmsg("*** Self protection mechanism activated.\n");
}
return 0; return 0;
} }
@ -970,7 +993,10 @@ static int cli_load(const char *filename, struct cl_engine **engine, unsigned in
ret = cli_loadhdb(fd, engine, signo, 1, options); ret = cli_loadhdb(fd, engine, signo, 1, options);
} else if(cli_strbcasestr(filename, ".ndb")) { } else if(cli_strbcasestr(filename, ".ndb")) {
ret = cli_loadndb(fd, engine, signo, options); ret = cli_loadndb(fd, engine, signo, 0, options);
} else if(cli_strbcasestr(filename, ".sdb")) {
ret = cli_loadndb(fd, engine, signo, 1, options);
} else if(cli_strbcasestr(filename, ".zmd")) { } else if(cli_strbcasestr(filename, ".zmd")) {
ret = cli_loadmd(fd, engine, signo, 1, options); ret = cli_loadmd(fd, engine, signo, 1, options);
@ -1033,6 +1059,7 @@ static int cli_loaddbdir(const char *dirname, struct cl_engine **engine, unsigne
cli_strbcasestr(dent->d_name, ".hdb") || cli_strbcasestr(dent->d_name, ".hdb") ||
cli_strbcasestr(dent->d_name, ".fp") || cli_strbcasestr(dent->d_name, ".fp") ||
cli_strbcasestr(dent->d_name, ".ndb") || cli_strbcasestr(dent->d_name, ".ndb") ||
cli_strbcasestr(dent->d_name, ".sdb") ||
cli_strbcasestr(dent->d_name, ".zmd") || cli_strbcasestr(dent->d_name, ".zmd") ||
cli_strbcasestr(dent->d_name, ".rmd") || cli_strbcasestr(dent->d_name, ".rmd") ||
cli_strbcasestr(dent->d_name, ".cvd"))) { cli_strbcasestr(dent->d_name, ".cvd"))) {
@ -1153,6 +1180,7 @@ int cl_statinidir(const char *dirname, struct cl_stat *dbstat)
cli_strbcasestr(dent->d_name, ".hdb") || cli_strbcasestr(dent->d_name, ".hdb") ||
cli_strbcasestr(dent->d_name, ".fp") || cli_strbcasestr(dent->d_name, ".fp") ||
cli_strbcasestr(dent->d_name, ".ndb") || cli_strbcasestr(dent->d_name, ".ndb") ||
cli_strbcasestr(dent->d_name, ".sdb") ||
cli_strbcasestr(dent->d_name, ".zmd") || cli_strbcasestr(dent->d_name, ".zmd") ||
cli_strbcasestr(dent->d_name, ".rmd") || cli_strbcasestr(dent->d_name, ".rmd") ||
cli_strbcasestr(dent->d_name, ".cvd"))) { cli_strbcasestr(dent->d_name, ".cvd"))) {
@ -1224,6 +1252,7 @@ int cl_statchkdir(const struct cl_stat *dbstat)
cli_strbcasestr(dent->d_name, ".hdb") || cli_strbcasestr(dent->d_name, ".hdb") ||
cli_strbcasestr(dent->d_name, ".fp") || cli_strbcasestr(dent->d_name, ".fp") ||
cli_strbcasestr(dent->d_name, ".ndb") || cli_strbcasestr(dent->d_name, ".ndb") ||
cli_strbcasestr(dent->d_name, ".sdb") ||
cli_strbcasestr(dent->d_name, ".zmd") || cli_strbcasestr(dent->d_name, ".zmd") ||
cli_strbcasestr(dent->d_name, ".rmd") || cli_strbcasestr(dent->d_name, ".rmd") ||
cli_strbcasestr(dent->d_name, ".cvd"))) { cli_strbcasestr(dent->d_name, ".cvd"))) {

@ -1438,8 +1438,7 @@ static int cli_scantnef(int desc, const char **virname, unsigned long int *scann
return ret; return ret;
} }
static int static int cli_scanuuencoded(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
cli_scanuuencoded(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
{ {
int ret; int ret;
char *dir = cli_gentemp(NULL); char *dir = cli_gentemp(NULL);
@ -1497,6 +1496,90 @@ static int cli_scanmail(int desc, const char **virname, unsigned long int *scann
return ret; return ret;
} }
static int cli_scanraw(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec, cli_file_t type)
{
int ret = CL_CLEAN;
unsigned short ftrec;
struct cli_matched_type *ftoffset = NULL, *fpt;
switch(type) {
case CL_TYPE_UNKNOWN_TEXT:
case CL_TYPE_MSEXE:
ftrec = 1;
break;
default:
ftrec = 0;
}
if(lseek(desc, 0, SEEK_SET) < 0) {
cli_errmsg("cli_scanraw: lseek() failed\n");
return CL_EIO;
}
if((ret = cli_scandesc(desc, virname, scanned, engine, ftrec, type, &ftoffset)) == CL_VIRUS) {
cli_dbgmsg("%s found in descriptor %d.\n", *virname, desc);
return CL_VIRUS;
} else if(ret < 0) {
return ret;
} else if(ret >= CL_TYPENO) {
lseek(desc, 0, SEEK_SET);
ret == CL_TYPE_MAIL ? mrec++ : arec++;
switch(ret) {
case CL_TYPE_HTML:
if(SCAN_HTML && type == CL_TYPE_UNKNOWN_TEXT)
if(cli_scanhtml(desc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS)
return CL_VIRUS;
break;
case CL_TYPE_MAIL:
if(SCAN_MAIL && type == CL_TYPE_UNKNOWN_TEXT)
if(cli_scanmail(desc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS)
return CL_VIRUS;
break;
case CL_TYPE_RARSFX:
case CL_TYPE_ZIPSFX:
if(type == CL_TYPE_MSEXE) {
if(SCAN_ARCHIVE) {
fpt = ftoffset;
while(fpt) {
if(fpt->type == CL_TYPE_RARSFX) {
cli_dbgmsg("RAR-SFX signature found at %d\n", fpt->offset);
if((ret = cli_scanrar(desc, virname, scanned, engine, limits, options, arec, mrec, fpt->offset) == CL_VIRUS))
break;
} else if(fpt->type == CL_TYPE_ZIPSFX) {
cli_dbgmsg("ZIP-SFX signature found at %d\n", fpt->offset);
if((ret = cli_scanzip(desc, virname, scanned, engine, limits, options, arec, mrec, fpt->offset) == CL_VIRUS))
break;
}
fpt = fpt->next;
}
}
while(ftoffset) {
fpt = ftoffset;
ftoffset = ftoffset->next;
free(fpt);
}
if(ret == CL_VIRUS)
return ret;
}
break;
default:
break;
}
ret == CL_TYPE_MAIL ? mrec-- : arec--;
}
return ret;
}
int cli_magic_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec) int cli_magic_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
{ {
int ret = CL_CLEAN, nret; int ret = CL_CLEAN, nret;
@ -1548,6 +1631,12 @@ int cli_magic_scandesc(int desc, const char **virname, unsigned long int *scanne
type = cli_filetype2(desc); type = cli_filetype2(desc);
lseek(desc, 0, SEEK_SET); lseek(desc, 0, SEEK_SET);
if(type != CL_TYPE_DATA && engine->sdb) {
if((ret = cli_scanraw(desc, virname, scanned, engine, limits, options, arec, mrec, type) == CL_VIRUS))
return CL_VIRUS;
lseek(desc, 0, SEEK_SET);
}
type == CL_TYPE_MAIL ? mrec++ : arec++; type == CL_TYPE_MAIL ? mrec++ : arec++;
switch(type) { switch(type) {
@ -1671,81 +1760,9 @@ int cli_magic_scandesc(int desc, const char **virname, unsigned long int *scanne
type == CL_TYPE_MAIL ? mrec-- : arec--; type == CL_TYPE_MAIL ? mrec-- : arec--;
if(type != CL_TYPE_DATA && ret != CL_VIRUS) { /* scan the raw file */ if(type != CL_TYPE_DATA && ret != CL_VIRUS && !engine->sdb) {
int ftrec; if((ret = cli_scanraw(desc, virname, scanned, engine, limits, options, arec, mrec, type) == CL_VIRUS))
struct cli_matched_type *ftoffset = NULL, *fpt;
switch(type) {
case CL_TYPE_UNKNOWN_TEXT:
case CL_TYPE_MSEXE:
ftrec = 1;
break;
default:
ftrec = 0;
}
if(lseek(desc, 0, SEEK_SET) < 0)
cli_errmsg("lseek() failed, trying to continue anyway...\n");
if((nret = cli_scandesc(desc, virname, scanned, engine, ftrec, type, &ftoffset)) == CL_VIRUS) {
cli_dbgmsg("%s found in descriptor %d.\n", *virname, desc);
return CL_VIRUS; return CL_VIRUS;
} else if(nret < 0) {
return nret;
} else if(nret >= CL_TYPENO) {
lseek(desc, 0, SEEK_SET);
nret == CL_TYPE_MAIL ? mrec++ : arec++;
switch(nret) {
case CL_TYPE_HTML:
if(SCAN_HTML && type == CL_TYPE_UNKNOWN_TEXT)
if(cli_scanhtml(desc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS)
return CL_VIRUS;
break;
case CL_TYPE_MAIL:
if(SCAN_MAIL && type == CL_TYPE_UNKNOWN_TEXT)
if(cli_scanmail(desc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS)
return CL_VIRUS;
break;
case CL_TYPE_RARSFX:
case CL_TYPE_ZIPSFX:
if(type == CL_TYPE_MSEXE) {
if(SCAN_ARCHIVE) {
fpt = ftoffset;
while(fpt) {
if(fpt->type == CL_TYPE_RARSFX) {
cli_dbgmsg("RAR-SFX signature found at %d\n", fpt->offset);
if((ret = cli_scanrar(desc, virname, scanned, engine, limits, options, arec, mrec, fpt->offset) == CL_VIRUS))
break;
} else if(fpt->type == CL_TYPE_ZIPSFX) {
cli_dbgmsg("ZIP-SFX signature found at %d\n", fpt->offset);
if((ret = cli_scanzip(desc, virname, scanned, engine, limits, options, arec, mrec, fpt->offset) == CL_VIRUS))
break;
}
fpt = fpt->next;
}
}
while(ftoffset) {
fpt = ftoffset;
ftoffset = ftoffset->next;
free(fpt);
}
if(ret == CL_VIRUS)
return ret;
}
break;
default:
break;
}
nret == CL_TYPE_MAIL ? mrec-- : arec--;
}
} }
arec++; arec++;

Loading…
Cancel
Save