From 60dbee52c8a21c5c3504729c50b83f7f8e45cd39 Mon Sep 17 00:00:00 2001 From: Tomasz Kojm Date: Tue, 4 May 2010 21:59:21 +0200 Subject: [PATCH] libclamav: make lsigs working in cli_scanscript() (bb#1998) --- ChangeLog | 4 ++ libclamav/matcher.c | 122 ++++++++++++++++++++++--------------------- libclamav/matcher.h | 1 + libclamav/scanners.c | 11 ++-- 4 files changed, 75 insertions(+), 63 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1536daef9..18b31a71e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Tue May 4 21:58:19 CEST 2010 (tk) +---------------------------------- + * libclamav: make lsigs working in cli_scanscript() (bb#1998) + Tue May 4 19:37:58 CEST 2010 (acab) ------------------------------------ * libclamav/fmap.c: nicely handle EINTR diff --git a/libclamav/matcher.c b/libclamav/matcher.c index cba2d506c..17cbcd9df 100644 --- a/libclamav/matcher.c +++ b/libclamav/matcher.c @@ -416,22 +416,78 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc return ret; } +int cli_lsig_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data *acdata) +{ + unsigned int i, evalcnt; + uint64_t evalids; + int (*einfo)(fmap_t *, struct cli_exe_info *) = NULL; + struct cli_exe_info exeinfo; + fmap_t *map = *ctx->fmap; + + for(i = 0; i < root->ac_lsigs; i++) { + evalcnt = 0; + evalids = 0; + cli_ac_chkmacro(root, acdata, i); + if(cli_ac_chklsig(root->ac_lsigtable[i]->logic, root->ac_lsigtable[i]->logic + strlen(root->ac_lsigtable[i]->logic), acdata->lsigcnt[i], &evalcnt, &evalids, 0) == 1) { + if(root->ac_lsigtable[i]->tdb.container && root->ac_lsigtable[i]->tdb.container[0] != ctx->container_type) + continue; + if(root->ac_lsigtable[i]->tdb.filesize && (root->ac_lsigtable[i]->tdb.filesize[0] > map->len || root->ac_lsigtable[i]->tdb.filesize[1] < map->len)) + continue; + + if(root->ac_lsigtable[i]->tdb.ep || root->ac_lsigtable[i]->tdb.nos) { + einfo = NULL; + if(root->type == 1) + einfo = cli_peheader; + else if(root->type == 6) + einfo = cli_elfheader; + else if(root->type == 9) + einfo = cli_machoheader; + if(!einfo) + continue; + memset(&exeinfo, 0, sizeof(exeinfo)); + if(einfo(map, &exeinfo)) + continue; + if(exeinfo.section) + free(exeinfo.section); + if(root->ac_lsigtable[i]->tdb.ep && (root->ac_lsigtable[i]->tdb.ep[0] > exeinfo.ep || root->ac_lsigtable[i]->tdb.ep[1] < exeinfo.ep)) + continue; + if(root->ac_lsigtable[i]->tdb.nos && (root->ac_lsigtable[i]->tdb.nos[0] > exeinfo.nsections || root->ac_lsigtable[i]->tdb.nos[1] < exeinfo.nsections)) + continue; + } + if(root->ac_lsigtable[i]->tdb.icongrp1 || root->ac_lsigtable[i]->tdb.icongrp2) { + if(matchicon(ctx, root->ac_lsigtable[i]->tdb.icongrp1, root->ac_lsigtable[i]->tdb.icongrp2) == CL_VIRUS) { + if(ctx->virname) + *ctx->virname = root->ac_lsigtable[i]->virname; + return CL_VIRUS; + } else { + continue; + } + } + if(!root->ac_lsigtable[i]->bc_idx) { + if(ctx->virname) + *ctx->virname = root->ac_lsigtable[i]->virname; + return CL_VIRUS; + } + if(cli_bytecode_runlsig(ctx, &ctx->engine->bcs, root->ac_lsigtable[i]->bc_idx, ctx->virname, acdata->lsigcnt[i], acdata->lsigsuboff[i], map) == CL_VIRUS) { + return CL_VIRUS; + } + } + } + return CL_CLEAN; +} int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, unsigned char *refhash) { unsigned char *buff; int ret = CL_CLEAN, type = CL_CLEAN, bytes; - unsigned int i, evalcnt, bm_offmode = 0; + unsigned int i, bm_offmode = 0; uint32_t maxpatlen, offset = 0; - uint64_t evalids; struct cli_ac_data gdata, tdata; struct cli_bm_off toff; cli_md5_ctx md5ctx; unsigned char digest[16]; struct cli_matcher *groot = NULL, *troot = NULL; fmap_t *map = *ctx->fmap; - int (*einfo)(fmap_t *, struct cli_exe_info *) = NULL; - struct cli_exe_info exeinfo; if(!ctx->engine) { cli_errmsg("cli_scandesc: engine == NULL\n"); @@ -531,62 +587,8 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli offset += bytes - maxpatlen; } -#define LSIGEVAL(xroot, xdata) \ - for(i = 0; i < xroot->ac_lsigs; i++) { \ - evalcnt = 0; \ - evalids = 0; \ - cli_ac_chkmacro(xroot, &xdata, i);\ - if(cli_ac_chklsig(xroot->ac_lsigtable[i]->logic, xroot->ac_lsigtable[i]->logic + strlen(xroot->ac_lsigtable[i]->logic), xdata.lsigcnt[i], &evalcnt, &evalids, 0) == 1) { \ - if(xroot->ac_lsigtable[i]->tdb.container && xroot->ac_lsigtable[i]->tdb.container[0] != ctx->container_type) \ - continue; \ - if(xroot->ac_lsigtable[i]->tdb.filesize && (xroot->ac_lsigtable[i]->tdb.filesize[0] > map->len || xroot->ac_lsigtable[i]->tdb.filesize[1] < map->len)) \ - continue; \ - \ - if(xroot->ac_lsigtable[i]->tdb.ep || xroot->ac_lsigtable[i]->tdb.nos) { \ - einfo = NULL; \ - if(xroot->type == 1) \ - einfo = cli_peheader; \ - else if(xroot->type == 6) \ - einfo = cli_elfheader; \ - else if(xroot->type == 9) \ - einfo = cli_machoheader; \ - if(!einfo) \ - continue; \ - memset(&exeinfo, 0, sizeof(exeinfo)); \ - if(einfo(map, &exeinfo)) \ - continue; \ - if(exeinfo.section) \ - free(exeinfo.section); \ - if(xroot->ac_lsigtable[i]->tdb.ep && (xroot->ac_lsigtable[i]->tdb.ep[0] > exeinfo.ep || xroot->ac_lsigtable[i]->tdb.ep[1] < exeinfo.ep)) \ - continue; \ - if(xroot->ac_lsigtable[i]->tdb.nos && (xroot->ac_lsigtable[i]->tdb.nos[0] > exeinfo.nsections || xroot->ac_lsigtable[i]->tdb.nos[1] < exeinfo.nsections)) \ - continue; \ - } \ - if(xroot->ac_lsigtable[i]->tdb.icongrp1 || xroot->ac_lsigtable[i]->tdb.icongrp2) { \ - if(matchicon(ctx, xroot->ac_lsigtable[i]->tdb.icongrp1, xroot->ac_lsigtable[i]->tdb.icongrp2) == CL_VIRUS) { \ - if(ctx->virname) \ - *ctx->virname = xroot->ac_lsigtable[i]->virname; \ - ret = CL_VIRUS; \ - break; \ - } else { \ - continue; \ - } \ - } \ - if(!xroot->ac_lsigtable[i]->bc_idx) { \ - if(ctx->virname) \ - *ctx->virname = xroot->ac_lsigtable[i]->virname; \ - ret = CL_VIRUS; \ - break; \ - } \ - if(cli_bytecode_runlsig(ctx, &ctx->engine->bcs, xroot->ac_lsigtable[i]->bc_idx, ctx->virname, xdata.lsigcnt[i], xdata.lsigsuboff[i], map) == CL_VIRUS) { \ - ret = CL_VIRUS; \ - break; \ - } \ - } \ - } - if(troot) { - LSIGEVAL(troot, tdata); + ret = cli_lsig_eval(ctx, troot, &tdata); cli_ac_freedata(&tdata); if(bm_offmode) cli_bm_freeoff(&toff); @@ -594,7 +596,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli if(groot) { if(ret != CL_VIRUS) - LSIGEVAL(groot, gdata); + ret = cli_lsig_eval(ctx, groot, &gdata); cli_ac_freedata(&gdata); } diff --git a/libclamav/matcher.h b/libclamav/matcher.h index 2d5d020bd..c2ae65125 100644 --- a/libclamav/matcher.h +++ b/libclamav/matcher.h @@ -165,6 +165,7 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode); int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, unsigned char *refhash); +int cli_lsig_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data *acdata); int cli_caloff(const char *offstr, struct cli_target_info *info, fmap_t *map, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max); int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx); diff --git a/libclamav/scanners.c b/libclamav/scanners.c index dc144fe0d..bcb2e4ec3 100644 --- a/libclamav/scanners.c +++ b/libclamav/scanners.c @@ -1023,7 +1023,7 @@ static int cli_scanscript(cli_ctx *ctx) struct text_norm_state state; char *tmpname = NULL; int ofd = -1, ret; - const struct cli_matcher *troot = ctx->engine->root[7]; + struct cli_matcher *troot = ctx->engine->root[7]; uint32_t maxpatlen = troot ? troot->maxpatlen : 0, offset = 0; struct cli_matcher *groot = ctx->engine->root[0]; struct cli_ac_data gmdata, tmdata; @@ -1096,13 +1096,18 @@ static int cli_scanscript(cli_ctx *ctx) cli_dbgmsg("cli_scanscript: short read during normalizing\n"); } } - cli_ac_freedata(&tmdata); - cli_ac_freedata(&gmdata); if(ctx->engine->keeptmp) { free(tmpname); close(ofd); } free(normalized); + if(ret != CL_VIRUS) { + ret = cli_lsig_eval(ctx, troot, &tmdata); + if(ret != CL_VIRUS) + ret = cli_lsig_eval(ctx, groot, &gmdata); + } + cli_ac_freedata(&tmdata); + cli_ac_freedata(&gmdata); return ret; }