From 555c5390cc6339a05512b6071932dd9c1302265c Mon Sep 17 00:00:00 2001 From: Tomasz Kojm Date: Wed, 25 Jan 2006 12:11:31 +0000 Subject: [PATCH] add support for signature based self-protection mode git-svn: trunk@1831 --- clamav-devel/ChangeLog | 4 + clamav-devel/libclamav/clamav.h | 1 + clamav-devel/libclamav/matcher-ac.c | 2 +- clamav-devel/libclamav/matcher-ac.h | 2 +- clamav-devel/libclamav/matcher.c | 2 +- clamav-devel/libclamav/matcher.h | 2 +- clamav-devel/libclamav/others.c | 2 +- clamav-devel/libclamav/readdb.c | 35 +++++- clamav-devel/libclamav/scanners.c | 169 +++++++++++++++------------- 9 files changed, 135 insertions(+), 84 deletions(-) diff --git a/clamav-devel/ChangeLog b/clamav-devel/ChangeLog index c61690342..cc92fb84c 100644 --- a/clamav-devel/ChangeLog +++ b/clamav-devel/ChangeLog @@ -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) --------------------------------- * libclamav/unrar: fix compilation error on old linux systems diff --git a/clamav-devel/libclamav/clamav.h b/clamav-devel/libclamav/clamav.h index fd7d5eee7..290815289 100644 --- a/clamav-devel/libclamav/clamav.h +++ b/clamav-devel/libclamav/clamav.h @@ -150,6 +150,7 @@ struct cli_matcher { struct cl_engine { unsigned int refcount; /* reference counter */ unsigned short hwaccel; + unsigned short sdb; /* Roots table */ struct cli_matcher **root; diff --git a/clamav-devel/libclamav/matcher-ac.c b/clamav-devel/libclamav/matcher-ac.c index bee3f71a8..7db34a6e4 100644 --- a/clamav-devel/libclamav/matcher-ac.c +++ b/clamav-devel/libclamav/matcher-ac.c @@ -260,7 +260,7 @@ inline static int cli_findpos(const char *buffer, unsigned int depth, unsigned i 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_patt *pt; diff --git a/clamav-devel/libclamav/matcher-ac.h b/clamav-devel/libclamav/matcher-ac.h index 9d1e26056..fcd80f52d 100644 --- a/clamav-devel/libclamav/matcher-ac.h +++ b/clamav-devel/libclamav/matcher-ac.h @@ -26,7 +26,7 @@ #define AC_DEFAULT_DEPTH 2 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); void cli_ac_free(struct cli_matcher *root); void cli_ac_setdepth(unsigned int depth); diff --git a/clamav-devel/libclamav/matcher.c b/clamav-devel/libclamav/matcher.c index 8298f7776..ab33ac7ad 100644 --- a/clamav-devel/libclamav/matcher.c +++ b/clamav-devel/libclamav/matcher.c @@ -274,7 +274,7 @@ int cli_validatesig(unsigned short target, unsigned short ftype, const char *off 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; int bytes, buffsize, length, ret, *gpartcnt, *tpartcnt; diff --git a/clamav-devel/libclamav/matcher.h b/clamav-devel/libclamav/matcher.h index 8d7d17e6d..2e6bad5ab 100644 --- a/clamav-devel/libclamav/matcher.h +++ b/clamav-devel/libclamav/matcher.h @@ -24,7 +24,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); diff --git a/clamav-devel/libclamav/others.c b/clamav-devel/libclamav/others.c index 8317017b3..c3612188a 100644 --- a/clamav-devel/libclamav/others.c +++ b/clamav-devel/libclamav/others.c @@ -72,7 +72,7 @@ static pthread_mutex_t cli_gentempname_mutex = PTHREAD_MUTEX_INITIALIZER; #define O_BINARY 0 #endif -#define CL_FLEVEL 6 /* don't touch it */ +#define CL_FLEVEL 7 /* don't touch it */ #define MAX_ALLOCATION 134217728 diff --git a/clamav-devel/libclamav/readdb.c b/clamav-devel/libclamav/readdb.c index 3b70052ad..8f323fa16 100644 --- a/clamav-devel/libclamav/readdb.c +++ b/clamav-devel/libclamav/readdb.c @@ -557,7 +557,7 @@ static int cli_loaddb(FILE *fd, struct cl_engine **engine, unsigned int *signo, 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; struct cli_matcher *root; @@ -594,7 +594,7 @@ static int cli_loadndb(FILE *fd, struct cl_engine **engine, unsigned int *signo, break; } - if((pt = cli_strtok(buffer, 4, ":"))) { + if((pt = cli_strtok(buffer, 4, ":"))) { /* min version */ if(!isdigit(*pt)) { free(virname); free(pt); @@ -611,6 +611,24 @@ static int cli_loadndb(FILE *fd, struct cl_engine **engine, unsigned int *signo, } 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)) { @@ -677,6 +695,11 @@ static int cli_loadndb(FILE *fd, struct cl_engine **engine, unsigned int *signo, if(signo) *signo += sigs; + if(sdb && sigs && !(*engine)->sdb) { + (*engine)->sdb = 1; + cli_dbgmsg("*** Self protection mechanism activated.\n"); + } + 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); } 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")) { 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, ".fp") || cli_strbcasestr(dent->d_name, ".ndb") || + cli_strbcasestr(dent->d_name, ".sdb") || cli_strbcasestr(dent->d_name, ".zmd") || cli_strbcasestr(dent->d_name, ".rmd") || 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, ".fp") || cli_strbcasestr(dent->d_name, ".ndb") || + cli_strbcasestr(dent->d_name, ".sdb") || cli_strbcasestr(dent->d_name, ".zmd") || cli_strbcasestr(dent->d_name, ".rmd") || 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, ".fp") || cli_strbcasestr(dent->d_name, ".ndb") || + cli_strbcasestr(dent->d_name, ".sdb") || cli_strbcasestr(dent->d_name, ".zmd") || cli_strbcasestr(dent->d_name, ".rmd") || cli_strbcasestr(dent->d_name, ".cvd"))) { diff --git a/clamav-devel/libclamav/scanners.c b/clamav-devel/libclamav/scanners.c index c06cca69e..3b26ddd6c 100644 --- a/clamav-devel/libclamav/scanners.c +++ b/clamav-devel/libclamav/scanners.c @@ -1438,8 +1438,7 @@ static int cli_scantnef(int desc, const char **virname, unsigned long int *scann return ret; } -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) +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) { int ret; char *dir = cli_gentemp(NULL); @@ -1497,6 +1496,90 @@ static int cli_scanmail(int desc, const char **virname, unsigned long int *scann 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 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); 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++; 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--; - if(type != CL_TYPE_DATA && ret != CL_VIRUS) { /* scan the raw file */ - int 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("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); + if(type != CL_TYPE_DATA && ret != CL_VIRUS && !engine->sdb) { + if((ret = cli_scanraw(desc, virname, scanned, engine, limits, options, arec, mrec, type) == 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++;