diff --git a/ChangeLog b/ChangeLog index ed450beb6..4e8541e9b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Fri Mar 23 14:19:42 CET 2007 (tk) +--------------------------------- + * libclamav: better handling of embedded stuff + Wed Mar 21 01:15:51 CET 2007 (tk) --------------------------------- * docs/man: use actual version and user names in man pages (bb#408), diff --git a/libclamav/matcher-ac.c b/libclamav/matcher-ac.c index 6d496caa0..d375b76ca 100644 --- a/libclamav/matcher-ac.c +++ b/libclamav/matcher-ac.c @@ -425,7 +425,7 @@ int cli_ac_scanbuff(const unsigned char *buffer, unsigned int length, const char int type = CL_CLEAN, j; unsigned int i, position, curroff; uint8_t offnum, found; - struct cli_matched_type *tnode; + struct cli_matched_type *tnode, *tnode_last = NULL; struct cli_target_info info; @@ -510,6 +510,11 @@ int cli_ac_scanbuff(const unsigned char *buffer, unsigned int length, const char if(otfrec) { if(pt->type > type || pt->type >= CL_TYPE_SFX || pt->type == CL_TYPE_MSEXE) { cli_dbgmsg("Matched signature for file type %s at %u\n", pt->virname, (unsigned int) mdata->inioff[pt->sigid - 1]); + mdata->offcnt[pt->sigid - 1] = 0; + mdata->offidx[pt->sigid - 1] = 0; + mdata->partcnt[pt->sigid - 1] = 0; + mdata->maxshift[pt->sigid - 1] = -1; + type = pt->type; if(ftoffset && (!*ftoffset || (*ftoffset)->cnt < MAX_EMBEDDED_OBJ) && ((ftype == CL_TYPE_MSEXE && type >= CL_TYPE_SFX) || ((ftype == CL_TYPE_MSEXE || ftype == CL_TYPE_ZIP) && type == CL_TYPE_MSEXE))) { if(!(tnode = cli_calloc(1, sizeof(struct cli_matched_type)))) { @@ -522,13 +527,21 @@ int cli_ac_scanbuff(const unsigned char *buffer, unsigned int length, const char tnode->type = type; tnode->offset = mdata->inioff[pt->sigid - 1]; - if(*ftoffset) - tnode->cnt = (*ftoffset)->cnt + 1; - else - tnode->cnt = 1; + if(*ftoffset && !tnode_last) { + tnode_last = *ftoffset; + while(tnode_last->next) + tnode_last = tnode_last->next; + } - tnode->next = *ftoffset; - *ftoffset = tnode; + if(tnode_last) { + tnode_last->next = tnode; + tnode_last = tnode; + } else { + *ftoffset = tnode; + tnode_last = tnode; + } + + (*ftoffset)->cnt++; } } } @@ -560,13 +573,21 @@ int cli_ac_scanbuff(const unsigned char *buffer, unsigned int length, const char tnode->type = type; tnode->offset = curroff; - if(*ftoffset) - tnode->cnt = (*ftoffset)->cnt + 1; - else - tnode->cnt = 1; + if(*ftoffset && !tnode_last) { + tnode_last = *ftoffset; + while(tnode_last->next) + tnode_last = tnode_last->next; + } - tnode->next = *ftoffset; - *ftoffset = tnode; + if(tnode_last) { + tnode_last->next = tnode; + tnode_last = tnode; + } else { + *ftoffset = tnode; + tnode_last = tnode; + } + + (*ftoffset)->cnt++; } } } diff --git a/libclamav/scanners.c b/libclamav/scanners.c index b02397ef3..90b456675 100644 --- a/libclamav/scanners.c +++ b/libclamav/scanners.c @@ -1748,7 +1748,7 @@ static int cli_scanembpe(int desc, cli_ctx *ctx) static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type) { int ret = CL_CLEAN, nret = CL_CLEAN; - unsigned short ftrec; + unsigned short ftrec, break_loop = 0; struct cli_matched_type *ftoffset = NULL, *fpt; uint32_t lastzip, lastrar; struct cli_exe_info peinfo; @@ -1773,7 +1773,7 @@ static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type) if(ret >= CL_TYPENO) { - if(ret < CL_TYPE_SFX && ret != CL_TYPE_MSEXE) { + if(type == CL_TYPE_UNKNOWN_TEXT) { lseek(desc, 0, SEEK_SET); nret = cli_scandesc(desc, ctx, 0, ret, 1, NULL); @@ -1781,6 +1781,65 @@ static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type) cli_dbgmsg("%s found in descriptor %d when scanning file type %u\n", *ctx->virname, desc, ret); } + if(nret != CL_VIRUS && (type == CL_TYPE_MSEXE || type == CL_TYPE_ZIP)) { + lastzip = lastrar = 0xdeadbeef; + fpt = ftoffset; + while(fpt) { + switch(fpt->type) { + case CL_TYPE_RARSFX: + if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_RAR)) { + cli_dbgmsg("RAR-SFX signature found at %u\n", (unsigned int) fpt->offset); + nret = cli_scanrar(desc, ctx, fpt->offset, &lastrar); + } + break; + + case CL_TYPE_ZIPSFX: + if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_ZIP)) { + cli_dbgmsg("ZIP-SFX signature found at %u\n", (unsigned int) fpt->offset); + nret = cli_scanzip(desc, ctx, fpt->offset, &lastzip); + } + break; + + case CL_TYPE_CABSFX: + if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_CAB)) { + cli_dbgmsg("CAB-SFX signature found at %u\n", (unsigned int) fpt->offset); + nret = cli_scanmscab(desc, ctx, fpt->offset); + } + break; + + case CL_TYPE_MSEXE: + if(SCAN_PE && ctx->dconf->pe && fpt->offset) { + cli_dbgmsg("PE signature found at %u\n", (unsigned int) fpt->offset); + memset(&peinfo, 0, sizeof(struct cli_exe_info)); + peinfo.offset = fpt->offset; + lseek(desc, fpt->offset, SEEK_SET); + if(cli_peheader(desc, &peinfo) == 0) { + cli_dbgmsg("*** Detected embedded PE file ***\n"); + if(peinfo.section) + free(peinfo.section); + + lseek(desc, fpt->offset, SEEK_SET); + nret = cli_scanembpe(desc, ctx); + break_loop = 1; /* we can stop here and other + * embedded executables will + * be found recursively + * through the above call + */ + } + } + break; + + default: + cli_warnmsg("cli_scanraw: Type %u not handled in fpt loop\n", fpt->type); + } + + if(nret == CL_VIRUS || break_loop) + break; + + fpt = fpt->next; + } + } + ret == CL_TYPE_MAIL ? ctx->mrec++ : ctx->arec++; if(nret != CL_VIRUS) switch(ret) { @@ -1794,61 +1853,6 @@ static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type) nret = cli_scanmail(desc, ctx); break; - case CL_TYPE_RARSFX: - case CL_TYPE_ZIPSFX: - case CL_TYPE_CABSFX: - if(type == CL_TYPE_MSEXE) { - if(SCAN_ARCHIVE) { - lastzip = lastrar = 0xdeadbeef; - fpt = ftoffset; - while(fpt) { - if(fpt->type == CL_TYPE_RARSFX && (DCONF_ARCH & ARCH_CONF_RAR)) { - cli_dbgmsg("RAR-SFX signature found at %u\n", (unsigned int) fpt->offset); - if((nret = cli_scanrar(desc, ctx, fpt->offset, &lastrar)) == CL_VIRUS) - break; - } else if(fpt->type == CL_TYPE_ZIPSFX && (DCONF_ARCH & ARCH_CONF_ZIP)) { - cli_dbgmsg("ZIP-SFX signature found at %u\n", (unsigned int) fpt->offset); - if((nret = cli_scanzip(desc, ctx, fpt->offset, &lastzip)) == CL_VIRUS) - break; - } else if(fpt->type == CL_TYPE_CABSFX && (DCONF_ARCH & ARCH_CONF_CAB)) { - cli_dbgmsg("CAB-SFX signature found at %u\n", (unsigned int) fpt->offset); - if((nret = cli_scanmscab(desc, ctx, fpt->offset)) == CL_VIRUS) - break; - } - - fpt = fpt->next; - } - } - } - break; - - case CL_TYPE_MSEXE: - if(SCAN_PE && ctx->dconf->pe) { - fpt = ftoffset; - while(fpt) { - if(fpt->type == CL_TYPE_MSEXE && fpt->offset) { - cli_dbgmsg("PE signature found at %u\n", (unsigned int) fpt->offset); - memset(&peinfo, 0, sizeof(struct cli_exe_info)); - peinfo.offset = fpt->offset; - lseek(desc, fpt->offset, SEEK_SET); - if(cli_peheader(desc, &peinfo) == 0) { - cli_dbgmsg("*** Detected embedded PE file ***\n"); - if(peinfo.section) - free(peinfo.section); - - lseek(desc, fpt->offset, SEEK_SET); - nret = cli_scanembpe(desc, ctx); - break; /* we can stop here, other embedded - * executables will be found recursively - * through the above call - */ - } - } - fpt = fpt->next; - } - } - break; - default: break; }