Browse code

icon matching functions

aCaB authored on 2009/12/11 08:52:16
Showing 7 changed files
... ...
@@ -114,6 +114,7 @@ typedef struct {
114 114
 } cli_ctx;
115 115
 
116 116
 struct icomtr {
117
+    uint32_t group[2];
117 118
     unsigned int color_avg[3];
118 119
     unsigned int color_x[3];
119 120
     unsigned int color_y[3];
... ...
@@ -139,6 +140,13 @@ struct icomtr {
139 139
     char *name;
140 140
 };
141 141
 
142
+struct icon_matcher {
143
+    char **group_names[2];
144
+    unsigned int group_counts[2];
145
+    struct icomtr *icons[3];
146
+    unsigned int icon_counts[3];
147
+};
148
+
142 149
 struct cl_engine {
143 150
     uint32_t refcount; /* reference counter */
144 151
     uint32_t sdb;
... ...
@@ -204,8 +212,7 @@ struct cl_engine {
204 204
     char *pua_cats;
205 205
 
206 206
     /* Icon reference storage */
207
-    struct icomtr *icons[3];
208
-    unsigned int icon_counts[3];
207
+    struct icon_matcher *iconcheck;
209 208
 
210 209
     /* Used for memory pools */
211 210
     mpool_t *mempool;
... ...
@@ -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)
474
+int cli_scanpe(cli_ctx *ctx, unsigned int *icongrps1, unsigned int *icongrps2)
475 475
 {
476 476
 	uint16_t e_magic; /* DOS signature ("MZ") */
477 477
 	uint16_t nsections;
... ...
@@ -1042,11 +1042,13 @@ int cli_scanpe(cli_ctx *ctx)
1042 1042
 
1043 1043
     cli_dbgmsg("EntryPoint offset: 0x%x (%d)\n", ep, ep);
1044 1044
 
1045
-    if(!dll && dirs[2].Size) { /* RES */
1046
-       if(scanicon(EC32(dirs[2].VirtualAddress), ctx, exe_sections, nsections, hdr_size) == CL_VIRUS) {
1047
-	   free(exe_sections);
1048
-	   return CL_VIRUS;
1049
-       }
1045
+    if(icongrps1 || icongrps2){
1046
+	if(!dll && dirs[2].Size && scanicon(icongrps1, icongrps2, EC32(dirs[2].VirtualAddress), ctx, exe_sections, nsections, hdr_size) == CL_VIRUS) {
1047
+	    free(exe_sections);
1048
+	    return CL_VIRUS;
1049
+	}
1050
+	free(exe_sections);
1051
+	return CL_CLEAN;
1050 1052
     }
1051 1053
 
1052 1054
     if(pe_plus) { /* Do not continue for PE32+ files */
... ...
@@ -129,7 +129,7 @@ struct pe_image_section_hdr {
129 129
     uint32_t Characteristics;
130 130
 };
131 131
 
132
-int cli_scanpe(cli_ctx *ctx);
132
+int cli_scanpe(cli_ctx *ctx, unsigned int *icongrp1, unsigned int *icongrp2);
133 133
 
134 134
 int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo);
135 135
 
... ...
@@ -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(uint32_t rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size);
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);
78 78
 
79
-int scanicon(uint32_t resdir_rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size) {
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) {
80 80
     struct GICONS gicons;
81 81
     struct ICONS icons;
82 82
     unsigned int curicon, err;
... ...
@@ -122,7 +122,7 @@ int scanicon(uint32_t resdir_rva, cli_ctx *ctx, struct cli_exe_section *exe_sect
122 122
     }
123 123
 
124 124
     for(curicon=0; curicon<icons.cnt; curicon++) {
125
-	if(parseicon(icons.rvas[curicon], ctx, exe_sections, nsections, hdr_size) == CL_VIRUS)
125
+	if(parseicon(grp1, grp2, icons.rvas[curicon], ctx, exe_sections, nsections, hdr_size) == CL_VIRUS)
126 126
 	    return CL_VIRUS;
127 127
     }
128 128
     return 0;
... ...
@@ -747,6 +747,7 @@ static int getmetrics(unsigned int side, unsigned int *imagedata, struct icomtr
747 747
     unsigned int x, y, xk, yk, i, j, *tmp;
748 748
     unsigned int ksize = side / 4, bwonly = 0;
749 749
     unsigned int edge_avg[6], edge_x[6], edge_y[6], noedge_avg[6], noedge_x[6], noedge_y[6];
750
+    double *sobel;
750 751
 
751 752
     if(!(tmp = cli_malloc(side*side*4*2)))
752 753
 	return CL_EMEM;
... ...
@@ -909,13 +910,13 @@ static int getmetrics(unsigned int side, unsigned int *imagedata, struct icomtr
909 909
     /* Sobel 1 - gradients */
910 910
     i = 0;
911 911
 #ifdef USE_FLOATS
912
-    double *sobel = cli_malloc(side * side * sizeof(double));
912
+    sobel = cli_malloc(side * side * sizeof(double));
913 913
     if(!sobel) {
914 914
 	free(tmp);
915 915
 	return CL_EMEM;
916 916
     }
917 917
 #else
918
-    unsigned int *sobel = imagedata;
918
+#define sobel imagedata
919 919
 #endif
920 920
     for(y=0; y<side; y++) {
921 921
 	for(x=0; x<side; x++) {
... ...
@@ -1098,7 +1099,7 @@ static int getmetrics(unsigned int side, unsigned int *imagedata, struct icomtr
1098 1098
     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]);
1099 1099
     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]);
1100 1100
     cli_dbgmsg("%s areas: %u@(%u,%u) %u@(%u,%u) %u@(%u,%u)\n", bwonly?"edge(2nd)":"color", 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]);
1101
-    cli_dbgmsg("%s areas: %u@(%u,%u) %u@(%u,%u) %u@(%u,%u)\n", bwonly?"noedge":"gray", res->gray_avg[0], res->gray_x[0], res->gray_y[0], res->gray_avg[1], res->gray_x[1], res->gray_y[1], res->gray_avg[2], res->gray_x[2], res->gray_y[2]);
1101
+    cli_dbgmsg("%s areas: %u@(%u,%u) %u@(%u,%u) %u@(%u,%u)\n", bwonly?"noedge(2nd)":"gray", res->gray_avg[0], res->gray_x[0], res->gray_y[0], res->gray_avg[1], res->gray_x[1], res->gray_y[1], res->gray_avg[2], res->gray_x[2], res->gray_y[2]);
1102 1102
     cli_dbgmsg("bright areas: %u@(%u,%u) %u@(%u,%u) %u@(%u,%u)\n", res->bright_avg[0], res->bright_x[0], res->bright_y[0], res->bright_avg[1], res->bright_x[1], res->bright_y[1], res->bright_avg[2], res->bright_x[2], res->bright_y[2]);
1103 1103
     cli_dbgmsg("dark areas: %u@(%u,%u) %u@(%u,%u) %u@(%u,%u)\n", res->dark_avg[0], res->dark_x[0], res->dark_y[0], res->dark_avg[1], res->dark_x[1], res->dark_y[1], res->dark_avg[2], res->dark_x[2], res->dark_y[2]);
1104 1104
     if(!bwonly)
... ...
@@ -1152,7 +1153,7 @@ static int getmetrics(unsigned int side, unsigned int *imagedata, struct icomtr
1152 1152
 }
1153 1153
 
1154 1154
 
1155
-static int parseicon(uint32_t rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size) {
1155
+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 1156
     struct {
1157 1157
 	unsigned int sz;
1158 1158
 	unsigned int w;
... ...
@@ -1174,6 +1175,10 @@ static int parseicon(uint32_t rva, cli_ctx *ctx, struct cli_exe_section *exe_sec
1174 1174
     unsigned int err, scalemode = 2, enginesize;
1175 1175
     fmap_t *map = *ctx->fmap;
1176 1176
     uint32_t icoff = cli_rawaddr(rva, exe_sections, nsections, &err, map->len, hdr_size);
1177
+    struct icon_matcher *matcher;
1178
+
1179
+    if(!ctx || !ctx->engine || !(matcher=ctx->engine->iconcheck))
1180
+	return CL_SUCCESS;
1177 1181
 
1178 1182
     /* read the bitmap header */
1179 1183
     if(err || !(imagedata = fmap_need_off_once(map, icoff, 4))) {
... ...
@@ -1405,35 +1410,49 @@ static int parseicon(uint32_t rva, cli_ctx *ctx, struct cli_exe_section *exe_sec
1405 1405
     free(imagedata);
1406 1406
 
1407 1407
     enginesize = (width >> 3) - 2;
1408
-    for(x=0; x<ctx->engine->icon_counts[enginesize]; x++) {
1408
+    for(x=0; x<matcher->icon_counts[enginesize]; x++) {
1409 1409
 	unsigned int color = 0, gray = 0, bright, dark, edge, noedge, reds, greens, blues, ccount;
1410 1410
 	unsigned int colors, confidence, bwmatch = 0, positivematch = 64 + 4*(2-enginesize);
1411
+	unsigned int i, j;
1411 1412
 
1412
-	if(!metrics.ccount && !ctx->engine->icons[enginesize][x].ccount) {
1413
+	if(grp1) {
1414
+	    unsigned int *g1 = grp1;
1415
+	    while(*g1 && *g1 != matcher->icons[enginesize][x].group[0]+1)
1416
+		g1++;
1417
+	    if(!*g1) continue;
1418
+	}
1419
+	if(grp2) {
1420
+	    unsigned int *g2 = grp2;
1421
+	    while(*g2 && *g2 != matcher->icons[enginesize][x].group[1]+1)
1422
+		g2++;
1423
+	    if(!*g2) continue;
1424
+	}
1425
+
1426
+	if(!metrics.ccount && !matcher->icons[enginesize][x].ccount) {
1413 1427
 	    /* BW matching */
1414
-	    edge = matchbwpoint(width, metrics.edge_x, metrics.edge_y, metrics.edge_avg, metrics.color_x, metrics.color_y, metrics.color_avg, ctx->engine->icons[enginesize][x].edge_x, ctx->engine->icons[enginesize][x].edge_y, ctx->engine->icons[enginesize][x].edge_avg, ctx->engine->icons[enginesize][x].color_x, ctx->engine->icons[enginesize][x].color_y, ctx->engine->icons[enginesize][x].color_avg);
1415
-	    noedge = matchbwpoint(width, metrics.noedge_x, metrics.noedge_y, metrics.noedge_avg, metrics.gray_x, metrics.gray_y, metrics.gray_avg, ctx->engine->icons[enginesize][x].noedge_x, ctx->engine->icons[enginesize][x].noedge_y, ctx->engine->icons[enginesize][x].noedge_avg, ctx->engine->icons[enginesize][x].gray_x, ctx->engine->icons[enginesize][x].gray_y, ctx->engine->icons[enginesize][x].gray_avg);
1428
+	    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);
1429
+	    noedge = matchbwpoint(width, metrics.noedge_x, metrics.noedge_y, metrics.noedge_avg, metrics.gray_x, metrics.gray_y, metrics.gray_avg, matcher->icons[enginesize][x].noedge_x, matcher->icons[enginesize][x].noedge_y, matcher->icons[enginesize][x].noedge_avg, matcher->icons[enginesize][x].gray_x, matcher->icons[enginesize][x].gray_y, matcher->icons[enginesize][x].gray_avg);
1416 1430
 	    bwmatch = 1;
1417 1431
 	} else {
1418
-	    edge = matchpoint(width, metrics.edge_x, metrics.edge_y, metrics.edge_avg, ctx->engine->icons[enginesize][x].edge_x, ctx->engine->icons[enginesize][x].edge_y, ctx->engine->icons[enginesize][x].edge_avg, 255);
1419
-	    noedge = matchpoint(width, metrics.noedge_x, metrics.noedge_y, metrics.noedge_avg, ctx->engine->icons[enginesize][x].noedge_x, ctx->engine->icons[enginesize][x].noedge_y, ctx->engine->icons[enginesize][x].noedge_avg, 255);
1420
-	    if(metrics.ccount && ctx->engine->icons[enginesize][x].ccount) {
1432
+	    edge = matchpoint(width, metrics.edge_x, metrics.edge_y, metrics.edge_avg, matcher->icons[enginesize][x].edge_x, matcher->icons[enginesize][x].edge_y, matcher->icons[enginesize][x].edge_avg, 255);
1433
+	    noedge = matchpoint(width, metrics.noedge_x, metrics.noedge_y, metrics.noedge_avg, matcher->icons[enginesize][x].noedge_x, matcher->icons[enginesize][x].noedge_y, matcher->icons[enginesize][x].noedge_avg, 255);
1434
+	    if(metrics.ccount && matcher->icons[enginesize][x].ccount) {
1421 1435
 		/* color matching */
1422
-		color = matchpoint(width, metrics.color_x, metrics.color_y, metrics.color_avg, ctx->engine->icons[enginesize][x].color_x, ctx->engine->icons[enginesize][x].color_y, ctx->engine->icons[enginesize][x].color_avg, 4072);
1423
-		gray = matchpoint(width, metrics.gray_x, metrics.gray_y, metrics.gray_avg, ctx->engine->icons[enginesize][x].gray_x, ctx->engine->icons[enginesize][x].gray_y, ctx->engine->icons[enginesize][x].gray_avg, 4072);
1436
+		color = matchpoint(width, metrics.color_x, metrics.color_y, metrics.color_avg, matcher->icons[enginesize][x].color_x, matcher->icons[enginesize][x].color_y, matcher->icons[enginesize][x].color_avg, 4072);
1437
+		gray = matchpoint(width, metrics.gray_x, metrics.gray_y, metrics.gray_avg, matcher->icons[enginesize][x].gray_x, matcher->icons[enginesize][x].gray_y, matcher->icons[enginesize][x].gray_avg, 4072);
1424 1438
 	    }
1425 1439
 	}
1426 1440
 
1427
-	bright = matchpoint(width, metrics.bright_x, metrics.bright_y, metrics.bright_avg, ctx->engine->icons[enginesize][x].bright_x, ctx->engine->icons[enginesize][x].bright_y, ctx->engine->icons[enginesize][x].bright_avg, 255);
1428
-	dark = matchpoint(width, metrics.dark_x, metrics.dark_y, metrics.dark_avg, ctx->engine->icons[enginesize][x].dark_x, ctx->engine->icons[enginesize][x].dark_y, ctx->engine->icons[enginesize][x].dark_avg, 255);
1441
+	bright = matchpoint(width, metrics.bright_x, metrics.bright_y, metrics.bright_avg, matcher->icons[enginesize][x].bright_x, matcher->icons[enginesize][x].bright_y, matcher->icons[enginesize][x].bright_avg, 255);
1442
+	dark = matchpoint(width, metrics.dark_x, metrics.dark_y, metrics.dark_avg, matcher->icons[enginesize][x].dark_x, matcher->icons[enginesize][x].dark_y, matcher->icons[enginesize][x].dark_avg, 255);
1429 1443
 
1430
-	reds = abs((int)metrics.rsum - (int)ctx->engine->icons[enginesize][x].rsum) * 10;
1444
+	reds = abs((int)metrics.rsum - (int)matcher->icons[enginesize][x].rsum) * 10;
1431 1445
 	reds = (reds < 100) * (100 - reds);
1432
-	greens = abs((int)metrics.gsum - (int)ctx->engine->icons[enginesize][x].gsum) * 10;
1446
+	greens = abs((int)metrics.gsum - (int)matcher->icons[enginesize][x].gsum) * 10;
1433 1447
 	greens = (greens < 100) * (100 - greens);
1434
-	blues = abs((int)metrics.bsum - (int)ctx->engine->icons[enginesize][x].bsum) * 10;
1448
+	blues = abs((int)metrics.bsum - (int)matcher->icons[enginesize][x].bsum) * 10;
1435 1449
 	blues = (blues < 100) * (100 - blues);
1436
-	ccount = abs((int)metrics.ccount - (int)ctx->engine->icons[enginesize][x].ccount) * 10;
1450
+	ccount = abs((int)metrics.ccount - (int)matcher->icons[enginesize][x].ccount) * 10;
1437 1451
 	ccount = (ccount < 100) * (100 - ccount);
1438 1452
 	colors = (reds + greens + blues + ccount) / 4;
1439 1453
 
... ...
@@ -1459,7 +1478,7 @@ static int parseicon(uint32_t rva, cli_ctx *ctx, struct cli_exe_section *exe_sec
1459 1459
 	    cli_warnmsg("confidence: %u\n", confidence);
1460 1460
 
1461 1461
 	    if(ctx->virname) 
1462
-		*ctx->virname = ctx->engine->icons[enginesize][x].name;
1462
+		*ctx->virname = matcher->icons[enginesize][x].name;
1463 1463
 #ifdef DUMPMATCHING
1464 1464
 	    snprintf(name, sizeof(name), "match-%s-%u%%", *ctx->virname, confidence);
1465 1465
 	    makebmp(name, width, height, imagedata2);
... ...
@@ -1474,3 +1493,25 @@ static int parseicon(uint32_t rva, cli_ctx *ctx, struct cli_exe_section *exe_sec
1474 1474
 #endif
1475 1475
     return CL_SUCCESS;
1476 1476
 }
1477
+
1478
+
1479
+int cli_match_icon(cli_ctx *ctx, unsigned int *icongrp1, unsigned int *icongrp2) {
1480
+    if(!ctx || !ctx->engine || !ctx->engine->iconcheck || !ctx->engine->iconcheck->group_counts[0] || !ctx->engine->iconcheck->group_counts[1])
1481
+	return CL_CLEAN;
1482
+    return cli_scanpe(ctx, icongrp1, icongrp2);
1483
+}
1484
+
1485
+int cli_icon_getgroup(const char *group, unsigned int type, cli_ctx *ctx) {
1486
+    struct icon_matcher *matcher;
1487
+    unsigned int i;
1488
+
1489
+    if(type>1 || !ctx || !ctx->engine || !ctx->engine->iconcheck || !ctx->engine->iconcheck->group_counts[type])
1490
+	return 0;
1491
+
1492
+    matcher = ctx->engine->iconcheck;
1493
+    for(i=0; i<matcher->group_counts[type]; i++) {
1494
+	if(!strcmp(group, matcher->group_names[type][i]))
1495
+	    return i+1;
1496
+    }
1497
+    return 0;
1498
+}
... ...
@@ -22,6 +22,7 @@
22 22
 #define __PE_ICONS_H
23 23
 #include "pe.h"
24 24
 
25
-int scanicon(uint32_t resdir_rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size);
26
-
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);
27 28
 #endif
... ...
@@ -521,7 +521,7 @@ static int cli_loaddb(FILE *fs, struct cl_engine *engine, unsigned int *signo, u
521 521
     return CL_SUCCESS;
522 522
 }
523 523
 
524
-#define ICO_TOKENS 2
524
+#define ICO_TOKENS 4
525 525
 static int cli_loadidb(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int options, struct cli_dbio *dbio)
526 526
 {
527 527
         const char *tokens[ICO_TOKENS + 1];
... ...
@@ -530,7 +530,12 @@ static int cli_loadidb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
530 530
 	int ret = CL_SUCCESS;
531 531
 	unsigned int line = 0, sigs = 0, tokens_count, i, size, enginesize;
532 532
 	struct icomtr *metric;
533
+	struct icon_matcher *matcher;
533 534
 
535
+
536
+    if(!(matcher = (struct icon_matcher *)mpool_calloc(engine->mempool, sizeof(*matcher),1))) 
537
+	return CL_EMEM;
538
+    
534 539
     if(engine->ignored)
535 540
 	if(!(buffer_cpy = cli_malloc(FILEBUFF)))
536 541
 	    return CL_EMEM;
... ...
@@ -550,7 +555,7 @@ static int cli_loadidb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
550 550
 	    break;
551 551
 	}
552 552
 
553
-	if(strlen(tokens[1]) != 124) {
553
+	if(strlen(tokens[3]) != 124) {
554 554
 	    ret = CL_EMALFDB;
555 555
 	    break;
556 556
 	}
... ...
@@ -558,7 +563,7 @@ static int cli_loadidb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
558 558
 	if(engine->ignored && cli_chkign(engine->ignored, tokens[0], buffer_cpy))
559 559
 	    continue;
560 560
 
561
-	hash = (uint8_t *)tokens[1];
561
+	hash = (uint8_t *)tokens[3];
562 562
 	if(cli_hexnibbles((char *)hash, 124)) {
563 563
 	    cli_errmsg("cli_loadidb: Malformed hash at line %u (bad chars)\n", line);
564 564
 	    ret = CL_EMALFDB;
... ...
@@ -573,15 +578,15 @@ static int cli_loadidb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
573 573
 	enginesize = (size >> 3) - 2;
574 574
 	hash+=2;
575 575
 
576
-	metric = (struct icomtr *) mpool_realloc(engine->mempool, engine->icons[enginesize], sizeof(struct icomtr) * (engine->icon_counts[enginesize] + 1));
576
+	metric = (struct icomtr *)mpool_realloc(engine->mempool, matcher->icons[enginesize], sizeof(struct icomtr) * (matcher->icon_counts[enginesize] + 1));
577 577
 	if(!metric) {
578 578
 	    ret = CL_EMEM;
579 579
 	    break;
580 580
 	}
581 581
 
582
-	engine->icons[enginesize] = metric;
583
-	metric += engine->icon_counts[enginesize];
584
-	engine->icon_counts[enginesize]++;
582
+	matcher->icons[enginesize] = metric;
583
+	metric += matcher->icon_counts[enginesize];
584
+	matcher->icon_counts[enginesize]++;
585 585
 
586 586
 	for(i=0; i<3; i++) {
587 587
 	    if((metric->color_avg[i] = (hash[0] << 8) | (hash[1] << 4) | hash[2]) > 4072)
... ...
@@ -684,6 +689,34 @@ static int cli_loadidb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
684 684
 	    break;
685 685
 	}
686 686
 
687
+	for(i=0; i<matcher->group_counts[0]; i++) {
688
+	    if(!strcmp(tokens[1], matcher->group_names[0][i]))
689
+		break;
690
+	}
691
+	if(i==matcher->group_counts[0]) {
692
+	    if(!(matcher->group_names[0] = mpool_realloc(engine->mempool, matcher->group_names[0], sizeof(char *) * (i + 1))) ||
693
+	       !(matcher->group_names[0][i] = cli_mpool_strdup(engine->mempool, tokens[1]))) {
694
+		ret = CL_EMEM;
695
+		break;
696
+	    }
697
+	    matcher->group_counts[0]++;
698
+	}
699
+	metric->group[0] = i;
700
+
701
+	for(i=0; i<matcher->group_counts[1]; i++) {
702
+	    if(!strcmp(tokens[2], matcher->group_names[1][i]))
703
+		break;
704
+	}
705
+	if(i==matcher->group_counts[1]) {
706
+	    if(!(matcher->group_names[1] = mpool_realloc(engine->mempool, matcher->group_names[1], sizeof(char *) * (i + 1))) ||
707
+	       !(matcher->group_names[1][i] = cli_mpool_strdup(engine->mempool, tokens[2]))) {
708
+		ret = CL_EMALFDB;
709
+		break;
710
+	    }
711
+	    matcher->group_counts[1]++;
712
+	}
713
+	metric->group[1] = i;
714
+
687 715
 	sigs++;
688 716
     }
689 717
     if(engine->ignored)
... ...
@@ -702,6 +735,7 @@ static int cli_loadidb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
702 702
     if(signo)
703 703
 	*signo += sigs;
704 704
 
705
+    engine->iconcheck = matcher;
705 706
     return CL_SUCCESS;
706 707
 }
707 708
 
... ...
@@ -2358,12 +2392,26 @@ int cl_engine_free(struct cl_engine *engine)
2358 2358
     if(engine->pua_cats)
2359 2359
 	mpool_free(engine->mempool, engine->pua_cats);
2360 2360
 
2361
-    for(i=0; i<3; i++) {
2362
-	if(engine->icons[i]) {
2363
-	    mpool_free(engine->mempool, engine->icons[i]->name);
2364
-	    mpool_free(engine->mempool, engine->icons[i]);
2361
+    if(engine->iconcheck) {
2362
+	struct icon_matcher *iconcheck = engine->iconcheck;
2363
+	for(i=0; i<3; i++) {
2364
+	    if(iconcheck->icons[i]) {
2365
+		mpool_free(engine->mempool, iconcheck->icons[i]->name);
2366
+		mpool_free(engine->mempool, iconcheck->icons[i]);
2367
+	    }
2365 2368
 	}
2366
-    }
2369
+	if(iconcheck->group_names[0]) {
2370
+	    for(i=0; i<iconcheck->group_counts[0]; i++)
2371
+		mpool_free(engine->mempool, iconcheck->group_names[0][i]);
2372
+	    mpool_free(engine->mempool, iconcheck->group_names[0]);
2373
+	}
2374
+	if(iconcheck->group_names[1]) {
2375
+	    for(i=0; i<iconcheck->group_counts[1]; i++)
2376
+		mpool_free(engine->mempool, iconcheck->group_names[1][i]);
2377
+	    mpool_free(engine->mempool, iconcheck->group_names[1]);
2378
+	}
2379
+	mpool_free(engine->mempool, iconcheck);
2380
+    }	
2367 2381
 
2368 2382
     if(engine->tmpdir)
2369 2383
 	mpool_free(engine->mempool, engine->tmpdir);
... ...
@@ -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);
2151
+		ret = cli_scanpe(ctx, NULL, NULL);
2152 2152
 	    break;
2153 2153
 
2154 2154
 	default: