... | ... |
@@ -115,8 +115,11 @@ typedef struct { |
115 | 115 |
fmap_t **fmap; |
116 | 116 |
} cli_ctx; |
117 | 117 |
|
118 |
+ |
|
119 |
+typedef struct {uint64_t v[2][4];} icon_groupset; |
|
120 |
+ |
|
118 | 121 |
struct icomtr { |
119 |
- uint32_t group[2]; |
|
122 |
+ unsigned int group[2]; |
|
120 | 123 |
unsigned int color_avg[3]; |
121 | 124 |
unsigned int color_x[3]; |
122 | 125 |
unsigned int color_y[3]; |
... | ... |
@@ -471,7 +471,7 @@ static void cli_parseres_special(uint32_t base, uint32_t rva, fmap_t *map, struc |
471 | 471 |
fmap_unneed_ptr(map, oentry, entries*8); |
472 | 472 |
} |
473 | 473 |
|
474 |
-int cli_scanpe(cli_ctx *ctx, unsigned int *icongrps1, unsigned int *icongrps2) |
|
474 |
+int cli_scanpe(cli_ctx *ctx, icon_groupset *iconset) |
|
475 | 475 |
{ |
476 | 476 |
uint16_t e_magic; /* DOS signature ("MZ") */ |
477 | 477 |
uint16_t nsections; |
... | ... |
@@ -1043,8 +1043,8 @@ int cli_scanpe(cli_ctx *ctx, unsigned int *icongrps1, unsigned int *icongrps2) |
1043 | 1043 |
|
1044 | 1044 |
cli_dbgmsg("EntryPoint offset: 0x%x (%d)\n", ep, ep); |
1045 | 1045 |
|
1046 |
- if(icongrps1 || icongrps2){ |
|
1047 |
- if(!dll && dirs[2].Size && scanicon(icongrps1, icongrps2, EC32(dirs[2].VirtualAddress), ctx, exe_sections, nsections, hdr_size) == CL_VIRUS) { |
|
1046 |
+ if(iconset){ |
|
1047 |
+ if(!dll && dirs[2].Size && cli_scanicon(iconset, EC32(dirs[2].VirtualAddress), ctx, exe_sections, nsections, hdr_size) == CL_VIRUS) { |
|
1048 | 1048 |
free(exe_sections); |
1049 | 1049 |
return CL_VIRUS; |
1050 | 1050 |
} |
... | ... |
@@ -150,7 +150,7 @@ struct cli_pe_hook_data { |
150 | 150 |
uint8_t *dummy EBOUNDS(dummyn); |
151 | 151 |
}; |
152 | 152 |
|
153 |
-int cli_scanpe(cli_ctx *ctx, unsigned int *icongrp1, unsigned int *icongrp2); |
|
153 |
+int cli_scanpe(cli_ctx *ctx, icon_groupset *set); |
|
154 | 154 |
|
155 | 155 |
int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo); |
156 | 156 |
|
... | ... |
@@ -74,9 +74,9 @@ static int icon_cb(void *ptr, uint32_t type, uint32_t name, uint32_t lang, uint3 |
74 | 74 |
} |
75 | 75 |
|
76 | 76 |
|
77 |
-static int parseicon(unsigned int *grp1, unsigned int *grp2, uint32_t rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size); |
|
77 |
+static int parseicon(icon_groupset *set, uint32_t rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size); |
|
78 | 78 |
|
79 |
-int scanicon(unsigned int *grp1, unsigned int *grp2, uint32_t resdir_rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size) { |
|
79 |
+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) { |
|
80 | 80 |
struct GICONS gicons; |
81 | 81 |
struct ICONS icons; |
82 | 82 |
unsigned int curicon, err; |
... | ... |
@@ -122,7 +122,7 @@ int scanicon(unsigned int *grp1, unsigned int *grp2, uint32_t resdir_rva, cli_ct |
122 | 122 |
} |
123 | 123 |
|
124 | 124 |
for(curicon=0; curicon<icons.cnt; curicon++) { |
125 |
- if(parseicon(grp1, grp2, icons.rvas[curicon], ctx, exe_sections, nsections, hdr_size) == CL_VIRUS) |
|
125 |
+ if(parseicon(set, icons.rvas[curicon], ctx, exe_sections, nsections, hdr_size) == CL_VIRUS) |
|
126 | 126 |
return CL_VIRUS; |
127 | 127 |
} |
128 | 128 |
return 0; |
... | ... |
@@ -1153,7 +1153,7 @@ static int getmetrics(unsigned int side, unsigned int *imagedata, struct icomtr |
1153 | 1153 |
} |
1154 | 1154 |
|
1155 | 1155 |
|
1156 |
-static int parseicon(unsigned int *grp1, unsigned int *grp2, uint32_t rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size) { |
|
1156 |
+static int parseicon(icon_groupset *set, uint32_t rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size) { |
|
1157 | 1157 |
struct { |
1158 | 1158 |
unsigned int sz; |
1159 | 1159 |
unsigned int w; |
... | ... |
@@ -1415,19 +1415,15 @@ static int parseicon(unsigned int *grp1, unsigned int *grp2, uint32_t rva, cli_c |
1415 | 1415 |
unsigned int colors, confidence, bwmatch = 0, positivematch = 64 + 4*(2-enginesize); |
1416 | 1416 |
unsigned int i, j; |
1417 | 1417 |
|
1418 |
- if(grp1) { |
|
1419 |
- unsigned int *g1 = grp1; |
|
1420 |
- while(*g1 && *g1 != matcher->icons[enginesize][x].group[0]+1) |
|
1421 |
- g1++; |
|
1422 |
- if(!*g1) continue; |
|
1423 |
- } |
|
1424 |
- if(grp2) { |
|
1425 |
- unsigned int *g2 = grp2; |
|
1426 |
- while(*g2 && *g2 != matcher->icons[enginesize][x].group[1]+1) |
|
1427 |
- g2++; |
|
1428 |
- if(!*g2) continue; |
|
1429 |
- } |
|
1430 |
- |
|
1418 |
+ i = matcher->icons[enginesize][x].group[0]; |
|
1419 |
+ j = i % 64; |
|
1420 |
+ i /= 64; |
|
1421 |
+ if(!(set->v[0][i] & (1<<j))) continue; |
|
1422 |
+ i = matcher->icons[enginesize][x].group[1]; |
|
1423 |
+ j = i % 64; |
|
1424 |
+ i /= 64; |
|
1425 |
+ if(!(set->v[1][i] & (1<<j))) continue; |
|
1426 |
+ |
|
1431 | 1427 |
if(!metrics.ccount && !matcher->icons[enginesize][x].ccount) { |
1432 | 1428 |
/* BW matching */ |
1433 | 1429 |
edge = matchbwpoint(width, metrics.edge_x, metrics.edge_y, metrics.edge_avg, metrics.color_x, metrics.color_y, metrics.color_avg, matcher->icons[enginesize][x].edge_x, matcher->icons[enginesize][x].edge_y, matcher->icons[enginesize][x].edge_avg, matcher->icons[enginesize][x].color_x, matcher->icons[enginesize][x].color_y, matcher->icons[enginesize][x].color_avg); |
... | ... |
@@ -1495,23 +1491,34 @@ static int parseicon(unsigned int *grp1, unsigned int *grp2, uint32_t rva, cli_c |
1495 | 1495 |
} |
1496 | 1496 |
|
1497 | 1497 |
|
1498 |
-int cli_match_icon(cli_ctx *ctx, unsigned int *icongrp1, unsigned int *icongrp2) { |
|
1498 |
+int cli_match_icon(icon_groupset *set, cli_ctx *ctx) { |
|
1499 | 1499 |
if(!ctx || !ctx->engine || !ctx->engine->iconcheck || !ctx->engine->iconcheck->group_counts[0] || !ctx->engine->iconcheck->group_counts[1]) |
1500 | 1500 |
return CL_CLEAN; |
1501 |
- return cli_scanpe(ctx, icongrp1, icongrp2); |
|
1501 |
+ return cli_scanpe(ctx, set); |
|
1502 | 1502 |
} |
1503 | 1503 |
|
1504 |
-int cli_icon_getgroup(const char *group, unsigned int type, cli_ctx *ctx) { |
|
1504 |
+void cli_icongroupset_add(const char *groupname, icon_groupset *set, unsigned int type, cli_ctx *ctx) { |
|
1505 | 1505 |
struct icon_matcher *matcher; |
1506 |
- unsigned int i; |
|
1506 |
+ unsigned int i, j; |
|
1507 | 1507 |
|
1508 |
- if(type>1 || !ctx || !ctx->engine || !ctx->engine->iconcheck || !ctx->engine->iconcheck->group_counts[type]) |
|
1509 |
- return 0; |
|
1508 |
+ if(type>1 || !ctx || !ctx->engine || !(matcher = ctx->engine->iconcheck) || !matcher->group_counts[type]) |
|
1509 |
+ return; |
|
1510 | 1510 |
|
1511 |
- matcher = ctx->engine->iconcheck; |
|
1512 |
- for(i=0; i<matcher->group_counts[type]; i++) { |
|
1513 |
- if(!strcmp(group, matcher->group_names[type][i])) |
|
1514 |
- return i+1; |
|
1511 |
+ j = matcher->group_counts[type]; |
|
1512 |
+ if(groupname[0] == '*' && !groupname[1]) { |
|
1513 |
+ set->v[type][0] = set->v[type][1] = set->v[type][2] = set->v[type][3] = ~0; |
|
1514 |
+ return; |
|
1515 |
+ } |
|
1516 |
+ for(i=0; i<j; i++) { |
|
1517 |
+ if(!strcmp(groupname, matcher->group_names[type][i])) |
|
1518 |
+ break; |
|
1519 |
+ } |
|
1520 |
+ if(i == j) |
|
1521 |
+ cli_dbgmsg("cli_icon_addgroup: failed to locate icon group%u %s\n", type, groupname); |
|
1522 |
+ else { |
|
1523 |
+ j = i % 64; |
|
1524 |
+ i /= 64; |
|
1525 |
+ set->v[type][i] |= 1<<j; |
|
1515 | 1526 |
} |
1516 |
- return 0; |
|
1517 | 1527 |
} |
1528 |
+ |
... | ... |
@@ -22,7 +22,20 @@ |
22 | 22 |
#define __PE_ICONS_H |
23 | 23 |
#include "pe.h" |
24 | 24 |
|
25 |
-int scanicon(unsigned int *icongrp1, unsigned int *icongrp2, uint32_t resdir_rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size); |
|
26 |
-int cli_match_icon(cli_ctx *ctx, unsigned int *icongrp1, unsigned int *icongrp2); |
|
27 |
-int cli_icon_getgroup(const char *group, unsigned int type, cli_ctx *ctx); |
|
25 |
+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); |
|
26 |
+int cli_match_icon(icon_groupset *set, cli_ctx *ctx); |
|
27 |
+ |
|
28 |
+void cli_icongroupset_add(const char *groupname, icon_groupset *set, unsigned int type, cli_ctx *ctx); |
|
29 |
+static inline void cli_icongroupset_init(icon_groupset *set) { |
|
30 |
+ set->v[0][0] = 0; |
|
31 |
+ set->v[0][1] = 0; |
|
32 |
+ set->v[0][2] = 0; |
|
33 |
+ set->v[0][3] = 0; |
|
34 |
+ set->v[1][0] = 0; |
|
35 |
+ set->v[1][1] = 0; |
|
36 |
+ set->v[1][2] = 0; |
|
37 |
+ set->v[1][3] = 0; |
|
38 |
+} |
|
39 |
+ |
|
40 |
+ |
|
28 | 41 |
#endif |
... | ... |
@@ -554,11 +554,13 @@ static int cli_loadidb(FILE *fs, struct cl_engine *engine, unsigned int *signo, |
554 | 554 |
|
555 | 555 |
tokens_count = cli_strtokenize(buffer, ':', ICO_TOKENS + 1, tokens); |
556 | 556 |
if(tokens_count != ICO_TOKENS) { |
557 |
+ cli_errmsg("cli_loadidb: Malformed hash at line %u (wrong token count)\n", line); |
|
557 | 558 |
ret = CL_EMALFDB; |
558 | 559 |
break; |
559 | 560 |
} |
560 | 561 |
|
561 | 562 |
if(strlen(tokens[3]) != 124) { |
563 |
+ cli_errmsg("cli_loadidb: Malformed hash at line %u (wrong length)\n", line); |
|
562 | 564 |
ret = CL_EMALFDB; |
563 | 565 |
break; |
564 | 566 |
} |
... | ... |
@@ -713,13 +715,19 @@ static int cli_loadidb(FILE *fs, struct cl_engine *engine, unsigned int *signo, |
713 | 713 |
if(i==matcher->group_counts[1]) { |
714 | 714 |
if(!(matcher->group_names[1] = mpool_realloc(engine->mempool, matcher->group_names[1], sizeof(char *) * (i + 1))) || |
715 | 715 |
!(matcher->group_names[1][i] = cli_mpool_strdup(engine->mempool, tokens[2]))) { |
716 |
- ret = CL_EMALFDB; |
|
716 |
+ ret = CL_EMEM; |
|
717 | 717 |
break; |
718 | 718 |
} |
719 | 719 |
matcher->group_counts[1]++; |
720 | 720 |
} |
721 | 721 |
metric->group[1] = i; |
722 | 722 |
|
723 |
+ if(matcher->group_counts[0] > 256 || matcher->group_counts[1] > 256) { |
|
724 |
+ cli_errmsg("cli_loadidb: too many icon groups!\n"); |
|
725 |
+ ret = CL_EMALFDB; |
|
726 |
+ break; |
|
727 |
+ } |
|
728 |
+ |
|
723 | 729 |
sigs++; |
724 | 730 |
} |
725 | 731 |
if(engine->ignored) |