mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2025-10-19 10:23:17 +00:00
test icon scan
This commit is contained in:
parent
e1f5c08f3c
commit
a8d621cf80
4 changed files with 140 additions and 46 deletions
|
@ -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…
Add table
Add a link
Reference in a new issue