| ... | ... |
@@ -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) |