Browse code

icon scan interface rework

aCaB authored on 2009/12/12 07:04:18
Showing 7 changed files
... ...
@@ -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)
... ...
@@ -2148,7 +2148,7 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
2148 2148
 	 */
2149 2149
 	case CL_TYPE_MSEXE:
2150 2150
 	    if(SCAN_PE && ctx->dconf->pe)
2151
-		ret = cli_scanpe(ctx, NULL, NULL);
2151
+		ret = cli_scanpe(ctx, NULL);
2152 2152
 	    break;
2153 2153
 
2154 2154
 	default: