test icon scan

0.96
aCaB 16 years ago
parent e1f5c08f3c
commit a8d621cf80
  1. 29
      libclamav/others.h
  2. 82
      libclamav/pe_icons.c
  3. 25
      libclamav/pe_icons.h
  4. 50
      libclamav/readdb.c

@ -113,6 +113,32 @@ typedef struct {
fmap_t **fmap;
} cli_ctx;
struct icomtr {
unsigned int color_avg[3];
unsigned int color_x[3];
unsigned int color_y[3];
unsigned int gray_avg[3];
unsigned int gray_x[3];
unsigned int gray_y[3];
unsigned int bright_avg[3];
unsigned int bright_x[3];
unsigned int bright_y[3];
unsigned int dark_avg[3];
unsigned int dark_x[3];
unsigned int dark_y[3];
unsigned int edge_avg[3];
unsigned int edge_x[3];
unsigned int edge_y[3];
unsigned int noedge_avg[3];
unsigned int noedge_x[3];
unsigned int noedge_y[3];
unsigned int rsum;
unsigned int gsum;
unsigned int bsum;
unsigned int ccount;
char *name;
};
struct cl_engine {
uint32_t refcount; /* reference counter */
uint32_t sdb;
@ -177,6 +203,9 @@ struct cl_engine {
/* PUA categories (to be included or excluded) */
char *pua_cats;
/* Icon reference storage */
struct icomtr *icons;
/* Used for memory pools */
mpool_t *mempool;
};

@ -37,6 +37,29 @@
#define LABDIFF(x) labdiff2(x)
#endif
static const struct icomtr reference = {
{ 2923, 2746, 945 }, /* col avg */
{ 13, 0, 17 }, /* col x */
{ 3, 3, 15 }, /* col y */
{ 0, 0, 0 }, /* gray avg */
{ 22, 22, 0 }, /* gray x */
{ 0, 8, 12 }, /* gray y */
{ 255, 255, 251 }, /* bright avg */
{ 0, 0, 10 }, /* bright x */
{ 13, 21, 16 }, /* bright y */
{ 158, 184, 205 }, /* dark avg */
{ 17, 16, 0 }, /* dark x */
{ 23, 4, 5 }, /* dark y */
{ 105, 94, 73 }, /* edge avg */
{ 15, 5, 15 }, /* edge x */
{ 2, 2, 21 }, /* edge y */
{ 2, 2, 13 }, /* noedge avg */
{ 0, 0, 21 }, /* noedge x */
{ 23, 15, 12 }, /* noedge y */
99, 0, 0, 20,
"mario"
};
struct GICONS {
unsigned int cnt;
uint32_t lastg;
@ -717,11 +740,12 @@ static void hsv(unsigned int c, unsigned int *r, unsigned int *g, unsigned int *
*s = 255 * (*delta) / max;
}
static void getmetrics(unsigned int width, unsigned int height, unsigned int *imagedata, struct icomtr *res) {
static int getmetrics(unsigned int width, unsigned int height, unsigned int *imagedata, struct icomtr *res) {
unsigned int x, y, xk, yk, i, j, *tmp;
unsigned int ksize = width / 4;
tmp = malloc(width*height*4*2);
if(!(tmp = cli_malloc(width*height*4*2)))
return CL_EMEM;
memset(res, 0, sizeof(*res));
for(i=0; i<3; i++) {
@ -731,8 +755,8 @@ static void getmetrics(unsigned int width, unsigned int height, unsigned int *im
/* compute colored, gray, bright and dark areas, color presence */
for(y=0; y<height - ksize; y++) {
for(x=0; x<width - ksize; x++) {
for(y=0; y<=height - ksize; y++) {
for(x=0; x<=width - ksize; x++) {
unsigned int colsum = 0, lightsum = 0;
unsigned int r, g, b, s, v, delta;
@ -870,7 +894,8 @@ static void getmetrics(unsigned int width, unsigned int height, unsigned int *im
res->rsum /= res->ccount;
res->gsum /= res->ccount;
res->bsum /= res->ccount;
res->ccount /= width * height / 100;
cli_errmsg("res count = %u, width * height = %u\n", res->ccount, width * height);
res->ccount = res->ccount * 100 / width / height;
}
cli_dbgmsg("color areas: %u@(%u,%u) %u@(%u,%u) %u@(%u,%u)\n", res->color_avg[0], res->color_x[0], res->color_y[0], res->color_avg[1], res->color_x[1], res->color_y[1], res->color_avg[2], res->color_x[2], res->color_y[2]);
@ -884,7 +909,11 @@ static void getmetrics(unsigned int width, unsigned int height, unsigned int *im
/* Sobel 1 - gradients */
i = 0;
#ifdef USE_FLOATS
double *sobel = malloc(width * height * sizeof(double));
double *sobel = cli_malloc(width * height * sizeof(double));
if(!sobel) {
free(tmp);
return CL_EMEM;
}
#else
unsigned int *sobel = imagedata;
#endif
@ -984,8 +1013,8 @@ static void getmetrics(unsigned int width, unsigned int height, unsigned int *im
res->noedge_avg[i] = 0xffffffff;
/* calculate edges */
for(y=0; y<height - ksize; y++) {
for(x=0; x<width-1 - ksize; x++) {
for(y=0; y<=height - ksize; y++) {
for(x=0; x<=width-1 - ksize; x++) {
unsigned int sum = 0;
if(x==0 && y==0) { /* 1st windows */
@ -1052,6 +1081,8 @@ static void getmetrics(unsigned int width, unsigned int height, unsigned int *im
cli_dbgmsg("edge areas: %u@(%u,%u) %u@(%u,%u) %u@(%u,%u)\n", res->edge_avg[0], res->edge_x[0], res->edge_y[0], res->edge_avg[1], res->edge_x[1], res->edge_y[1], res->edge_avg[2], res->edge_x[2], res->edge_y[2]);
cli_dbgmsg("noedge areas: %u@(%u,%u) %u@(%u,%u) %u@(%u,%u)\n", res->noedge_avg[0], res->noedge_x[0], res->noedge_y[0], res->noedge_avg[1], res->noedge_x[1], res->noedge_y[1], res->noedge_avg[2], res->noedge_x[2], res->noedge_y[2]);
return CL_CLEAN;
}
@ -1101,6 +1132,8 @@ static int parseicon(uint32_t rva, cli_ctx *ctx, struct cli_exe_section *exe_sec
width = EC32(bmphdr.w);
height = EC32(bmphdr.h) / 2;
if(width > 256 || height > 256)
return CL_SUCCESS;
depth = EC32(bmphdr.depth);
cli_dbgmsg("Bitmap - %ux%ux%u\n", width, height, depth);
@ -1275,25 +1308,25 @@ static int parseicon(uint32_t rva, cli_ctx *ctx, struct cli_exe_section *exe_sec
getmetrics(width, height, imagedata, &metrics);
{
#define ref metrics
unsigned int color = matchpoint(width, height, metrics.color_x, metrics.color_y, metrics.color_avg, ref.color_x, ref.color_y, ref.color_avg, 4072);
unsigned int gray = matchpoint(width, height, metrics.gray_x, metrics.gray_y, metrics.gray_avg, ref.gray_x, ref.gray_y, ref.gray_avg, 4072);
unsigned int bright = matchpoint(width, height, metrics.bright_x, metrics.bright_y, metrics.bright_avg, ref.bright_x, ref.bright_y, ref.bright_avg, 255);
unsigned int dark = matchpoint(width, height, metrics.dark_x, metrics.dark_y, metrics.dark_avg, ref.dark_x, ref.dark_y, ref.dark_avg, 255);
unsigned int edge = matchpoint(width, height, metrics.edge_x, metrics.edge_y, metrics.edge_avg, ref.edge_x, ref.edge_y, ref.edge_avg, 255);
unsigned int noedge = matchpoint(width, height, metrics.noedge_x, metrics.noedge_y, metrics.noedge_avg, ref.noedge_x, ref.noedge_y, ref.noedge_avg, 255);
unsigned int reds = abs((int)metrics.rsum - (int)ref.rsum) * 10;
unsigned int color = matchpoint(width, height, metrics.color_x, metrics.color_y, metrics.color_avg, reference.color_x, reference.color_y, reference.color_avg, 4072);
unsigned int gray = matchpoint(width, height, metrics.gray_x, metrics.gray_y, metrics.gray_avg, reference.gray_x, reference.gray_y, reference.gray_avg, 4072);
unsigned int bright = matchpoint(width, height, metrics.bright_x, metrics.bright_y, metrics.bright_avg, reference.bright_x, reference.bright_y, reference.bright_avg, 255);
unsigned int dark = matchpoint(width, height, metrics.dark_x, metrics.dark_y, metrics.dark_avg, reference.dark_x, reference.dark_y, reference.dark_avg, 255);
unsigned int edge = matchpoint(width, height, metrics.edge_x, metrics.edge_y, metrics.edge_avg, reference.edge_x, reference.edge_y, reference.edge_avg, 255);
unsigned int noedge = matchpoint(width, height, metrics.noedge_x, metrics.noedge_y, metrics.noedge_avg, reference.noedge_x, reference.noedge_y, reference.noedge_avg, 255);
unsigned int reds = abs((int)metrics.rsum - (int)reference.rsum) * 10;
reds = (reds < 100) * (100 - reds);
unsigned int greens = abs((int)metrics.gsum - (int)ref.gsum) * 10;
unsigned int greens = abs((int)metrics.gsum - (int)reference.gsum) * 10;
greens = (greens < 100) * (100 - greens);
unsigned int blues = abs((int)metrics.bsum - (int)ref.bsum) * 10;
unsigned int blues = abs((int)metrics.bsum - (int)reference.bsum) * 10;
blues = (blues < 100) * (100 - blues);
unsigned int ccount = abs((int)metrics.ccount - (int)ref.ccount) * 10;
unsigned int ccount = abs((int)metrics.ccount - (int)reference.ccount) * 10;
ccount = (ccount < 100) * (100 - ccount);
unsigned int colors = (reds + greens + blues + ccount) / 4;
unsigned int used = 6;
unsigned int confidence;
if(!metrics.ccount && !ref.ccount) {
if(!metrics.ccount && !reference.ccount) {
colors = 0;
used--;
}
@ -1306,7 +1339,14 @@ static int parseicon(uint32_t rva, cli_ctx *ctx, struct cli_exe_section *exe_sec
cli_warnmsg("noedge confidence: %u%%\n", noedge);
cli_warnmsg("spread confidence: red %u%%, green %u%%, blue %u%% - colors %u%%\n", reds, greens, blues, ccount);
cli_warnmsg("confidence: %u\n", (color + gray*2/3 + bright*2/3 + dark + edge + noedge*2/3 + colors) / used);
confidence = (color + gray*2/3 + bright*2/3 + dark + edge + noedge*2/3 + colors) / used;
cli_warnmsg("confidence: %u\n", confidence);
if(confidence > 60) {
if(ctx->virname)
*ctx->virname = "PDF.ICON";
return CL_VIRUS;
}
/* CURRENTLY >=60% IS A MATCH */
}

@ -22,31 +22,6 @@
#define __PE_ICONS_H
#include "pe.h"
struct icomtr {
unsigned int color_avg[3];
unsigned int color_x[3];
unsigned int color_y[3];
unsigned int gray_avg[3];
unsigned int gray_x[3];
unsigned int gray_y[3];
unsigned int bright_avg[3];
unsigned int bright_x[3];
unsigned int bright_y[3];
unsigned int dark_avg[3];
unsigned int dark_x[3];
unsigned int dark_y[3];
unsigned int edge_avg[3];
unsigned int edge_x[3];
unsigned int edge_y[3];
unsigned int noedge_avg[3];
unsigned int noedge_x[3];
unsigned int noedge_y[3];
unsigned int rsum;
unsigned int gsum;
unsigned int bsum;
unsigned int ccount;
};
int scanicon(uint32_t resdir_rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size);
#endif

@ -521,6 +521,53 @@ static int cli_loaddb(FILE *fs, struct cl_engine *engine, unsigned int *signo, u
return CL_SUCCESS;
}
#define ICO_TOKENS 9
/* static int cli_loadico(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int mode, unsigned int options, struct cli_dbio *dbio, const char *dbname) */
/* { */
/* const char *tokens[ICO_TOKENS + 1]; */
/* char buffer[FILEBUFF], *buffer_cpy; */
/* const char *pt; */
/* int ret = CL_SUCCESS; */
/* unsigned int size_field = 1, md5_field = 0, line = 0, sigs = 0, tokens_count; */
/* if(engine->ignored) */
/* if(!(buffer_cpy = cli_malloc(FILEBUFF))) */
/* return CL_EMEM; */
/* while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) { */
/* line++; */
/* cli_chomp(buffer); */
/* if(engine->ignored) */
/* strcpy(buffer_cpy, buffer); */
/* tokens_count = cli_strtokenize(buffer, ':', ICO_TOKENS + 1, tokens); */
/* if(tokens_count != ICO_TOKENS) { */
/* ret = CL_EMALFDB; */
/* break; */
/* } */
/* sigs++; */
/* } */
/* if(engine->ignored) */
/* free(buffer_cpy); */
/* if(!line) { */
/* cli_errmsg("cli_loadmd5: Empty database file\n"); */
/* return CL_EMALFDB; */
/* } */
/* if(ret) { */
/* cli_errmsg("cli_loadmd5: Problem parsing database at line %u\n", line); */
/* return ret; */
/* } */
/* if(signo) */
/* *signo += sigs; */
/* return CL_SUCCESS; */
/* } */
static int cli_loadwdb(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio)
{
int ret = 0;
@ -1656,6 +1703,9 @@ int cli_load(const char *filename, struct cl_engine *engine, unsigned int *signo
} else if(cli_strbcasestr(dbname, ".ign") || cli_strbcasestr(dbname, ".ign2")) {
ret = cli_loadign(fs, engine, options, dbio);
/* } else if(cli_strbcasestr(dbname, ".idb")) { */
/* ret = cli_loadico(fs, engine, options, dbio); */
} else {
cli_dbgmsg("cli_load: unknown extension - assuming old database format\n");
ret = cli_loaddb(fs, engine, signo, options, dbio, dbname);

Loading…
Cancel
Save