use cached metadata in icon parser, add icon unit tests

This commit is contained in:
aCaB 2010-07-30 15:54:15 +02:00
parent 3f82dac01f
commit 453d818022
9 changed files with 55 additions and 33 deletions

View file

@ -1,3 +1,9 @@
Fri Jul 30 15:51:06 CEST 2010 (acab)
------------------------------------
* libclamav, unit_tests: use cached PE metadata when matching icons (better fix for
bb#2064, partially reverts d932a6d)
add some unit tests for ign2, ldb, idb
Fri Jul 30 15:15:35 CEST 2010 (tk)
----------------------------------
* freshclam: fix parsing of extended log entries

View file

@ -50,6 +50,10 @@ struct cli_exe_info {
uint32_t ep;
/** Number of sections*/
uint16_t nsections;
/** Resrources RVA - PE ONLY */
uint32_t res_addr;
/** Address size - PE ONLY */
uint32_t hdr_size;
/** Hashset for versioninfo matching */
struct cli_hashset *vinfo;
};

View file

@ -429,16 +429,25 @@ int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx)
return CL_VIRUS;
}
static int matchicon(cli_ctx *ctx, const char *grp1, const char *grp2)
static int matchicon(cli_ctx *ctx, struct cli_exe_info *exeinfo, const char *grp1, const char *grp2)
{
icon_groupset iconset;
if(!ctx ||
!ctx->engine ||
!ctx->engine->iconcheck ||
!ctx->engine->iconcheck->group_counts[0] ||
!ctx->engine->iconcheck->group_counts[1] ||
!exeinfo->res_addr
) return CL_CLEAN;
cli_icongroupset_init(&iconset);
cli_icongroupset_add(grp1 ? grp1 : "*", &iconset, 0, ctx);
cli_icongroupset_add(grp2 ? grp2 : "*", &iconset, 1, ctx);
return cli_match_icon(&iconset, ctx);
return cli_scanicon(&iconset, exeinfo->res_addr, ctx, exeinfo->section, exeinfo->nsections, exeinfo->hdr_size);
}
int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, struct cli_ac_result **acres)
{
int ret = CL_EMEM, empty;
@ -483,7 +492,7 @@ int cli_lsig_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data *ac
if(root->ac_lsigtable[i]->tdb.icongrp1 || root->ac_lsigtable[i]->tdb.icongrp2) {
if(!target_info || target_info->status != 1)
continue;
if(matchicon(ctx, root->ac_lsigtable[i]->tdb.icongrp1, root->ac_lsigtable[i]->tdb.icongrp2) == CL_VIRUS) {
if(matchicon(ctx, &target_info->exeinfo, 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;

View file

@ -58,7 +58,6 @@
#include "disasm.h"
#include "special.h"
#include "ishield.h"
#include "pe_icons.h"
#define DCONF ctx->dconf->pe
@ -501,7 +500,7 @@ static void cli_parseres_special(uint32_t base, uint32_t rva, fmap_t *map, struc
fmap_unneed_ptr(map, oentry, entries*8);
}
int cli_scanpe(cli_ctx *ctx, icon_groupset *iconset)
int cli_scanpe(cli_ctx *ctx)
{
uint16_t e_magic; /* DOS signature ("MZ") */
uint16_t nsections;
@ -1002,7 +1001,7 @@ int cli_scanpe(cli_ctx *ctx, icon_groupset *iconset)
/* check MD5 section sigs */
md5_sect = ctx->engine->md5_mdb;
if((DCONF & PE_CONF_MD5SECT) && md5_sect && !iconset) {
if((DCONF & PE_CONF_MD5SECT) && md5_sect) {
found = 0;
for(j = 0; j < md5_sect->soff_len && md5_sect->soff[j] <= exe_sections[i].rsz; j++) {
if(md5_sect->soff[j] == exe_sections[i].rsz) {
@ -1078,15 +1077,6 @@ int cli_scanpe(cli_ctx *ctx, icon_groupset *iconset)
cli_dbgmsg("EntryPoint offset: 0x%x (%d)\n", ep, ep);
if(iconset){
if(!dll && dirs[2].Size && cli_scanicon(iconset, EC32(dirs[2].VirtualAddress), ctx, exe_sections, nsections, hdr_size) == CL_VIRUS) {
free(exe_sections);
return CL_VIRUS;
}
free(exe_sections);
return CL_CLEAN;
}
if(pe_plus) { /* Do not continue for PE32+ files */
free(exe_sections);
return CL_CLEAN;
@ -2383,7 +2373,7 @@ int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo)
valign = (pe_plus)?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment);
falign = (pe_plus)?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment);
hdr_size = PESALIGN(hdr_size, valign);
peinfo->hdr_size = hdr_size = PESALIGN(hdr_size, valign);
peinfo->section = (struct cli_exe_section *) cli_calloc(peinfo->nsections, sizeof(struct cli_exe_section));
@ -2447,6 +2437,11 @@ int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo)
return -1;
}
if(EC16(file_hdr.Characteristics) & 0x2000 || !dirs[2].Size)
peinfo->res_addr = 0;
else
peinfo->res_addr = EC32(dirs[2].VirtualAddress);
while(dirs[2].Size && peinfo->vinfo) {
struct vinfo_list vlist;
uint8_t *vptr, *baseptr;

View file

@ -152,7 +152,7 @@ struct cli_pe_hook_data {
uint32_t hdr_size;/**< internally needed by rawaddr */
};
int cli_scanpe(cli_ctx *ctx, icon_groupset *set);
int cli_scanpe(cli_ctx *ctx);
int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo);

View file

@ -1503,20 +1503,6 @@ static int parseicon(icon_groupset *set, uint32_t rva, cli_ctx *ctx, struct cli_
return CL_SUCCESS;
}
int cli_match_icon(icon_groupset *set, cli_ctx *ctx) {
if(!ctx || !ctx->engine || !ctx->engine->iconcheck || !ctx->engine->iconcheck->group_counts[0] || !ctx->engine->iconcheck->group_counts[1])
return CL_CLEAN;
else {
unsigned int ctx_opts = ctx->options;
int ret;
ctx->options &= ~CL_SCAN_BLOCKBROKEN;
ret = cli_scanpe(ctx, set);
ctx->options = ctx_opts;
return ret;
}
}
void cli_icongroupset_add(const char *groupname, icon_groupset *set, unsigned int type, cli_ctx *ctx) {
struct icon_matcher *matcher;
unsigned int i, j;

View file

@ -23,7 +23,6 @@
#include "pe.h"
int cli_scanicon(icon_groupset *set, uint32_t resdir_rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size);
int cli_match_icon(icon_groupset *set, cli_ctx *ctx);
void cli_icongroupset_add(const char *groupname, icon_groupset *set, unsigned int type, cli_ctx *ctx);
static inline void cli_icongroupset_init(icon_groupset *set) {

View file

@ -2356,7 +2356,7 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
*/
case CL_TYPE_MSEXE:
if(SCAN_PE && ctx->dconf->pe)
ret = cli_scanpe(ctx, NULL);
ret = cli_scanpe(ctx);
break;
default:
break;

View file

@ -171,6 +171,29 @@ EOF
grep "phish-test-ssl: Heuristics.Phishing.Email.SSL-Spoof FOUND" clamscan3.log >/dev/null || die "phish-test1 failed";
grep "phish-test-cloak: Heuristics.Phishing.Email.Cloaked.Null FOUND" clamscan3.log >/dev/null || die "phish-test2 failed";
cat <<EOF >test-db/test.ign2
ClamAV-Test-File
EOF
cat <<EOF >test-db/test.idb
EA0X-32x32x8:ea0x-grp1:ea0x-grp2:2046f030a42a07153f4120a0031600007000005e1617ef0000d21100cb090674150f880313970b0e7716116d01136216022500002f0a173700081a004a0e
IScab-16x16x8:iscab-grp1:iscab-grp2:107b3000168306015c20a0105b07060be0a0b11c050bea0706cb0a0bbb060b6f00017c06018301068109086b03046705081b000a270a002a000039002b17
EOF
cat <<EOF >test-db/test.ldb
ClamAV-Test-Icon-EA0X;Engine:52-1000,Target:1,IconGroup1:ea0x-grp1,IconGroup2:*;(0);0:4d5a
ClamAV-Test-Icon-IScab;Engine:52-1000,Target:1,IconGroup2:iscab-grp2;(0);0:4d5a
EOF
if test_run 1 $CLAMSCAN --quiet -dtest-db $TESTFILES --log=clamscan4.log; then
scan_failed clamscan4.log "clamscan didn't detect icons correctly"
fi
grep "clam.ea05.exe: ClamAV-Test-Icon-EA0X.UNOFFICIAL FOUND" clamscan4.log || die "icon-test1 failed"
grep "clam.ea06.exe: ClamAV-Test-Icon-EA0X.UNOFFICIAL FOUND" clamscan4.log || die "icon-test2 failed"
grep "clam_IScab_ext.exe: ClamAV-Test-Icon-IScab.UNOFFICIAL FOUND" clamscan4.log || die "icon-test3 failed"
grep "clam_IScab_int.exe: ClamAV-Test-Icon-IScab.UNOFFICIAL FOUND" clamscan4.log || die "icon-test4 failed"
NINFECTED=`grep "Infected files" clamscan4.log | cut -f2 -d: | sed -e 's/ //g'`
if test "x$NINFECTED" -ne x4; then
scan_failed clamscan4.log "clamscan has detected spurious icons or whitlisting was not applier properly"
fi
test_end $1
}