[Pkg-clamav-commits] [SCM] Debian repository for ClamAV branch, debian/unstable, updated. debian/0.95+dfsg-1-6156-g094ec9b

aCaB acab at clamav.net
Sun Apr 4 01:13:21 UTC 2010


The following commit has been merged in the debian/unstable branch:
commit d2ba6f98bbb030edb0b2f2060990257bc119f77a
Author: aCaB <acab at clamav.net>
Date:   Mon Jan 4 14:56:04 2010 +0100

    matching complete

diff --git a/libclamav/execs.h b/libclamav/execs.h
index 7a90b44..e73791f 100644
--- a/libclamav/execs.h
+++ b/libclamav/execs.h
@@ -22,8 +22,9 @@
 #define __EXECS_H
 
 #include "cltypes.h"
+#include "hashtab.h"
 #include "bcfeatures.h"
-#include <sys/types.h>
+
 /** @file */
 /** Section of executable file */
 struct cli_exe_section {
@@ -49,6 +50,8 @@ struct cli_exe_info {
     uint32_t ep;
     /** Number of sections*/
     uint16_t nsections;
+    /** Hashset for versioninfo matching */
+    struct cli_hashset *vinfo;
 };
 
 #endif
diff --git a/libclamav/hashtab.h b/libclamav/hashtab.h
index d06858d..bf72ed4 100644
--- a/libclamav/hashtab.h
+++ b/libclamav/hashtab.h
@@ -24,6 +24,7 @@
 #define _HASHTAB_H
 #include <stdio.h>
 #include <stddef.h>
+#include <sys/types.h>
 #include "cltypes.h"
 typedef long cli_element_data;
 
diff --git a/libclamav/matcher-ac.c b/libclamav/matcher-ac.c
index efe859e..896b042 100644
--- a/libclamav/matcher-ac.c
+++ b/libclamav/matcher-ac.c
@@ -872,6 +872,11 @@ int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs,
 	return CL_ENULLARG;
     }
 
+    if(cli_hashset_init(&data->vinfo, 32, 80)) {
+	cli_errmsg("cli_ac_init: Can't allocate vinfo hashtab\n");
+	return CL_EMEM;
+    }
+
     data->reloffsigs = reloffsigs;
     if(reloffsigs) {
 	data->offset = (uint32_t *) cli_malloc(reloffsigs * 2 * sizeof(uint32_t));
@@ -934,6 +939,8 @@ int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, fmap
 	info.fsize = map->len;
     }
 
+    info.exeinfo.vinfo = &data->vinfo;
+
     for(i = 0; i < root->ac_reloff_num; i++) {
 	patt = root->ac_reloff[i];
 	if(!map) {
@@ -957,6 +964,7 @@ void cli_ac_freedata(struct cli_ac_data *data)
 {
 	uint32_t i;
 
+    cli_hashset_destroy(&data->vinfo);
 
     if(data && data->partsigs) {
 	for(i = 0; i < data->partsigs; i++) {
@@ -1045,7 +1053,7 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
 	    patt = current->list;
 	    while(patt) {
 		bp = i + 1 - patt->depth;
-		if(!patt->next_same && (patt->offset_min != CLI_OFF_ANY) && (!patt->sigid || patt->partno == 1)) {
+		if(patt->offdata[0] != CLI_OFF_VERSION && !patt->next_same && (patt->offset_min != CLI_OFF_ANY) && (!patt->sigid || patt->partno == 1)) {
 		    if(patt->offset_min == CLI_OFF_NONE) {
 			patt = patt->next;
 			continue;
@@ -1071,7 +1079,13 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
 			    continue;
 			}
 			realoff = offset + bp - pt->prefix_length;
-			if(pt->offset_min != CLI_OFF_ANY && (!pt->sigid || pt->partno == 1)) {
+			if(patt->offdata[0] == CLI_OFF_VERSION) {
+			    cli_errmsg("CHECK: %x\n", realoff);
+			    if(!cli_hashset_contains(&mdata->vinfo, realoff)) {
+				pt = pt->next_same;
+				continue;
+			    }
+			} else if(pt->offset_min != CLI_OFF_ANY && (!pt->sigid || pt->partno == 1)) {
 			    if(pt->offset_min == CLI_OFF_NONE) {
 				pt = pt->next_same;
 				continue;
diff --git a/libclamav/matcher-ac.h b/libclamav/matcher-ac.h
index c69a701..5d7bd2d 100644
--- a/libclamav/matcher-ac.h
+++ b/libclamav/matcher-ac.h
@@ -26,6 +26,7 @@
 #include "filetypes.h"
 #include "cltypes.h"
 #include "fmap.h"
+#include "hashtab.h"
 
 #define AC_CH_MAXDIST 32
 
@@ -37,6 +38,8 @@ struct cli_ac_data {
     uint32_t partsigs, lsigs, reloffsigs;
     uint32_t **lsigcnt;
     uint32_t *offset;
+    /** Hashset for versioninfo matching */
+    struct cli_hashset vinfo;
 };
 
 struct cli_ac_special {
diff --git a/libclamav/matcher.c b/libclamav/matcher.c
index 3126107..84bcbed 100644
--- a/libclamav/matcher.c
+++ b/libclamav/matcher.c
@@ -180,6 +180,9 @@ int cli_caloff(const char *offstr, struct cli_target_info *info, fmap_t *map, un
 		return CL_EMALFDB;
 	    }
 	    offdata[1] = atoi(&offcpy[4]);
+	} else if(!strncmp(offcpy, "VI", 2)) {
+	    /* versioninfo */
+	    offdata[0] = CLI_OFF_VERSION;
 	} else {
 	    offdata[0] = CLI_OFF_ABSOLUTE;
 	    if(!cli_isnumber(offcpy)) {
@@ -256,7 +259,9 @@ int cli_caloff(const char *offstr, struct cli_target_info *info, fmap_t *map, un
 		else
 		    *offset_min = info->exeinfo.section[offdata[3]].raw + offdata[1];
 		break;
-
+	    case CLI_OFF_VERSION:
+		*offset_min = *offset_max = CLI_OFF_ANY;
+		break;
 	    default:
 		cli_errmsg("cli_caloff: Not a relative offset (type: %u)\n", offdata[0]);
 		return CL_EARG;
diff --git a/libclamav/matcher.h b/libclamav/matcher.h
index e95ff56..d3b30f3 100644
--- a/libclamav/matcher.h
+++ b/libclamav/matcher.h
@@ -141,6 +141,7 @@ struct cli_target_info {
 #define CLI_OFF_EP_MINUS    4
 #define CLI_OFF_SL_PLUS     5
 #define CLI_OFF_SX_PLUS     6
+#define CLI_OFF_VERSION     7
 
 int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata);
 
diff --git a/libclamav/pe.c b/libclamav/pe.c
index 619fd1a..e24ed85 100644
--- a/libclamav/pe.c
+++ b/libclamav/pe.c
@@ -302,12 +302,11 @@ static int cli_ddump(int desc, int offset, int size, const char *file) {
    int pe_res_cballback (void *opaque, uint32_t type, uint32_t name, uint32_t lang, uint32_t rva);
    the callback shall return 0 to continue the lookup or 1 to abort
 */
-void findres(uint32_t by_type, uint32_t by_name, uint32_t res_rva, cli_ctx *ctx, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size, int (*cb)(void *, uint32_t, uint32_t, uint32_t, uint32_t), void *opaque) {
+void findres(uint32_t by_type, uint32_t by_name, uint32_t res_rva, fmap_t *map, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size, int (*cb)(void *, uint32_t, uint32_t, uint32_t, uint32_t), void *opaque) {
     unsigned int err = 0;
     uint32_t type, type_offs, name, name_offs, lang, lang_offs;
     uint8_t *resdir, *type_entry, *name_entry, *lang_entry ;
     uint16_t type_cnt, name_cnt, lang_cnt;
-    fmap_t *map = *ctx->fmap;
 
     if (!(resdir = fmap_need_off_once(map, cli_rawaddr(res_rva, exe_sections, nsections, &err, map->len, hdr_size), 16)) || err)
 	return;
@@ -1051,119 +1050,6 @@ int cli_scanpe(cli_ctx *ctx, icon_groupset *iconset)
 
     cli_dbgmsg("EntryPoint offset: 0x%x (%d)\n", ep, ep);
 
-    if(dirs[2].Size) {
-    	uint32_t rvas, res_sz;
-	uint8_t *vptr;
-    	findres(0x10, 0xffffffff, EC32(dirs[2].VirtualAddress), ctx, exe_sections, nsections, hdr_size, versioninfo, &rvas);
-	rvas = cli_rawaddr(rvas, exe_sections, nsections, &err, fsize, hdr_size); /* FIXME: this shall be an array */
-	vptr = fmap_need_off_once(map, rvas, 16); /* FIXME: check for failure */
-	rvas = cli_readint32(vptr);
-	res_sz = cli_readint32(vptr+4);
-	rvas = cli_rawaddr(rvas, exe_sections, nsections, &err, fsize, hdr_size); /* FIXME: check for failure */
-	vptr = fmap_need_off_once(map, rvas, res_sz); /* FIXME: check for failure */
-
-	while(res_sz>4) { /* look for versioninfo */
-	    uint32_t vinfo_sz, vinfo_val_sz;
-
-	    vinfo_sz = vinfo_val_sz = cli_readint32(vptr);
-	    vinfo_sz &= 0xffff;
-	    if(vinfo_sz > res_sz) {
-		/* the content is larger than the container */
-		break; /* this is a hard fail */
-	    }
-	    vinfo_val_sz >>= 16;
-	    if(vinfo_sz <= 6 + 0x22 + 0x34 ||
-	       vinfo_val_sz != 0x34 || 
-	       memcmp(vptr+6, "V\0S\0_\0V\0E\0R\0S\0I\0O\0N\0_\0I\0N\0F\0O\0\0\0", 0x20) ||
-	       cli_readint32(vptr + 0x28) != 0xfeef04bd) {
-		/* - there should be enough room for the header(6), the key "VS_VERSION_INFO"(20), the padding(2) and the value(34)
-		 * - the value should be sizeof(fixedfileinfo)
-		 * - the key should match
-		 * - there should be some proper magic for fixedfileinfo */
-		vptr += vinfo_sz;
-		res_sz -= vinfo_sz;
-		continue; /* this is a soft fail - FIXME: is there anything else we can find here? */
-	    }
-
-	    /* move to the end of fixedfileinfo where the child elements are located */
-	    vptr += 6 + 0x20 + 2 + 0x34;
-	    vinfo_sz -= 6 + 0x20 + 2 + 0x34;
-
-	    while(vinfo_sz > 6) { /* look for stringfileinfo */
-		uint32_t sfi_sz = cli_readint32(vptr) & 0xffff;
-
-		if(sfi_sz > vinfo_sz) {
-		    res_sz = 0;
-		    break; /* this is a hard fail */
-		}
-		if(sfi_sz <= 6 + 0x1e || memcmp(vptr+6, "S\0t\0r\0i\0n\0g\0F\0i\0l\0e\0I\0n\0f\0o\0\0\0", 0x1e)) {
-		    /* - there should be enough room for the header(6) and the key "StringFileInfo"(1e)
-		     * - the key should match */
-		    vptr += sfi_sz;
-		    vinfo_sz -= sfi_sz;
-		    continue; /* this is a soft fail - FIXME: we might only find VarFileInfo, and at most ONCE */
-		}
-
-		/* move to the end of stringfileinfo where the child elements are located */
-		vptr += 6 + 0x1e;
-		sfi_sz -= 6 + 0x1e;
-
-		while(sfi_sz > 6) { /* look for stringtable */
-		    uint32_t st_sz = cli_readint32(vptr) & 0xffff;
-
-		    if(st_sz > sfi_sz || st_sz <= 24) {
-			/* - the content is larger than the container
-			   - there's no room for a stringtables (headers(6) + key(16) + padding(2)) */
-			res_sz = 0;
-			vinfo_sz = 0;
-			break; /* this is a hard fail */
-		    }
-
-		    /* move to the end of stringtable where the child elements are located */
-		    vptr += 24;
-		    st_sz -= 24;
-
-		    while(st_sz > 6) {  /* look for string */
-			uint32_t s_sz, s_key_sz, s_val_sz;
-			char *k, *v;
-
-			s_sz = s_val_sz = cli_readint32(vptr);
-			s_sz &= 0xffff;
-			s_val_sz = (s_val_sz & 0xffff0000)>>15;
-			if(s_sz > st_sz || s_sz <= 6 + 2 + 2 + 2 || s_val_sz > s_sz - 6 - 2 - 2) {
-			    /* - the content is larger than the container
-			     * - there's no room for a minimal string (headers(6) + key(2) + padding(2) + value(2))
-			     * - there's no room for the value */
-			    res_sz = 0;
-			    vinfo_sz = 0;
-			    sfi_sz = 0;
-			    break; /* this is a hard fail */
-			}
-			for(s_key_sz = 0; s_key_sz < s_sz - 6 - s_val_sz; s_key_sz += 2) {
-			    if(vptr[6+s_key_sz] || vptr[6+s_key_sz+1]) continue;
-			    s_key_sz += 2;
-			    break;
-			}
-			if(s_key_sz >= s_sz - 6 - s_val_sz) {
-			    /* key overflow */
-			    vptr += s_sz;
-			    st_sz -= s_sz;
-			    continue;
-			}
-			k = cli_utf16toascii(vptr + 6, s_key_sz);
-			s_key_sz += 6 + 3;
-			s_key_sz &= ~3;
-			v = cli_utf16toascii(vptr + s_key_sz, s_val_sz);
-			cli_errmsg("%x - %s=%s\n", s_key_sz, k, v);
-			vptr += s_sz;
-			st_sz -= s_sz;
-		    }
-		    /* FIXME: resmue here */
-		}
-	    }
-	}
-    }
-
     if(iconset){
 	if(!dll && dirs[2].Size && cli_scanicon(iconset, EC32(dirs[2].VirtualAddress), ctx, exe_sections, nsections, hdr_size) == CL_VIRUS) {
 	    free(exe_sections);
@@ -2381,6 +2267,7 @@ int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo)
 	uint32_t valign, falign, hdr_size;
 	size_t fsize;
 	ssize_t at;
+	struct pe_image_data_dir *dirs;
 
     cli_dbgmsg("in cli_peheader\n");
 
@@ -2502,10 +2389,13 @@ int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo)
 	    peinfo->section[i].rsz = (fsize - peinfo->section[i].raw)*(fsize>peinfo->section[i].raw);
     }
 
-    if(pe_plus)
+    if(pe_plus) {
 	peinfo->ep = EC32(optional_hdr64.AddressOfEntryPoint);
-    else
+	dirs = optional_hdr64.DataDirectory;
+    } else {
 	peinfo->ep = EC32(optional_hdr32.AddressOfEntryPoint);
+	dirs = optional_hdr32.DataDirectory;
+    }
 
     if(!(peinfo->ep = cli_rawaddr(peinfo->ep, peinfo->section, peinfo->nsections, &err, fsize, hdr_size)) && err) {
 	cli_dbgmsg("Broken PE file\n");
@@ -2515,6 +2405,135 @@ int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo)
 	return -1;
     }
 
+    
+    if(dirs[2].Size) {
+    	uint32_t rvas, res_sz;
+	uint8_t *vptr, *baseptr;
+
+    	findres(0x10, 0xffffffff, EC32(dirs[2].VirtualAddress), map, peinfo->section, peinfo->nsections, hdr_size, versioninfo, &rvas);
+	rvas = cli_rawaddr(rvas, peinfo->section, peinfo->nsections, &err, fsize, hdr_size); /* FIXME: this shall be an array */
+	vptr = fmap_need_off_once(map, rvas, 16); /* FIXME: check for failure */
+	baseptr = vptr - rvas;
+	rvas = cli_readint32(vptr);
+	res_sz = cli_readint32(vptr+4);
+	rvas = cli_rawaddr(rvas, peinfo->section, peinfo->nsections, &err, fsize, hdr_size); /* FIXME: check for failure */
+	vptr = fmap_need_off_once(map, rvas, res_sz); /* FIXME: check for failure */
+
+	while(res_sz>4) { /* look for versioninfo */
+	    uint32_t vinfo_sz, vinfo_val_sz;
+
+	    vinfo_sz = vinfo_val_sz = cli_readint32(vptr);
+	    vinfo_sz &= 0xffff;
+	    if(vinfo_sz > res_sz) {
+		/* the content is larger than the container */
+		break; /* this is a hard fail */
+	    }
+	    vinfo_val_sz >>= 16;
+	    if(vinfo_sz <= 6 + 0x22 + 0x34 ||
+	       vinfo_val_sz != 0x34 || 
+	       memcmp(vptr+6, "V\0S\0_\0V\0E\0R\0S\0I\0O\0N\0_\0I\0N\0F\0O\0\0\0", 0x20) ||
+	       cli_readint32(vptr + 0x28) != 0xfeef04bd) {
+		/* - there should be enough room for the header(6), the key "VS_VERSION_INFO"(20), the padding(2) and the value(34)
+		 * - the value should be sizeof(fixedfileinfo)
+		 * - the key should match
+		 * - there should be some proper magic for fixedfileinfo */
+		vptr += vinfo_sz;
+		res_sz -= vinfo_sz;
+		continue; /* this is a soft fail - FIXME: is there anything else we can find here? */
+	    }
+
+	    /* move to the end of fixedfileinfo where the child elements are located */
+	    vptr += 6 + 0x20 + 2 + 0x34;
+	    vinfo_sz -= 6 + 0x20 + 2 + 0x34;
+
+	    while(vinfo_sz > 6) { /* look for stringfileinfo */
+		uint32_t sfi_sz = cli_readint32(vptr) & 0xffff;
+
+		if(sfi_sz > vinfo_sz) {
+		    res_sz = 0;
+		    break; /* this is a hard fail */
+		}
+		if(sfi_sz <= 6 + 0x1e || memcmp(vptr+6, "S\0t\0r\0i\0n\0g\0F\0i\0l\0e\0I\0n\0f\0o\0\0\0", 0x1e)) {
+		    /* - there should be enough room for the header(6) and the key "StringFileInfo"(1e)
+		     * - the key should match */
+		    vptr += sfi_sz;
+		    vinfo_sz -= sfi_sz;
+		    continue; /* this is a soft fail - FIXME: we might only find VarFileInfo, and at most ONCE */
+		}
+
+		/* move to the end of stringfileinfo where the child elements are located */
+		vptr += 6 + 0x1e;
+		sfi_sz -= 6 + 0x1e;
+
+		while(sfi_sz > 6) { /* look for stringtable */
+		    uint32_t st_sz = cli_readint32(vptr) & 0xffff;
+
+		    if(st_sz > sfi_sz || st_sz <= 24) {
+			/* - the content is larger than the container
+			   - there's no room for a stringtables (headers(6) + key(16) + padding(2)) */
+			res_sz = 0;
+			vinfo_sz = 0;
+			break; /* this is a hard fail */
+		    }
+
+		    /* move to the end of stringtable where the child elements are located */
+		    vptr += 24;
+		    st_sz -= 24;
+
+		    while(st_sz > 6) {  /* look for string */
+			uint32_t s_sz, s_key_sz, s_val_sz;
+			char *k, *v;
+
+			s_sz = s_val_sz = cli_readint32(vptr);
+			s_sz &= 0xffff;
+			s_val_sz = (s_val_sz & 0xffff0000)>>15;
+			if(s_sz > st_sz || s_sz <= 6 + 2 + 2 || s_val_sz > s_sz - 6 - 2 - 2) {
+			    /* - the content is larger than the container
+			     * - there's no room for a minimal string (headers(6) + key(2) + padding(2))
+			     * - there's no room for the value */
+			    res_sz = 0;
+			    vinfo_sz = 0;
+			    sfi_sz = 0;
+			    break; /* this is a hard fail */
+			}
+
+			if(!s_val_sz) {
+			    /* value unset */
+			    vptr += s_sz;
+			    st_sz -= s_sz;
+			    continue;
+			}
+			for(s_key_sz = 0; s_key_sz < s_sz - 6 - s_val_sz; s_key_sz += 2) {
+			    if(vptr[6+s_key_sz] || vptr[6+s_key_sz+1]) continue;
+			    s_key_sz += 2;
+			    break;
+			}
+			if(s_key_sz >= s_sz - 6 - s_val_sz) {
+			    /* key overflow */
+			    vptr += s_sz;
+			    st_sz -= s_sz;
+			    continue;
+			}
+			cli_hashset_addkey(peinfo->vinfo, (uint32_t)(vptr - baseptr + 6));
+			cli_errmsg("ADD %x\n", (uint32_t)(vptr - baseptr + 6));
+			k = cli_utf16toascii(vptr + 6, s_key_sz);
+			s_key_sz += 6 + 3;
+			s_key_sz &= ~3;
+			v = cli_utf16toascii(vptr + s_key_sz, s_val_sz);
+			if(v) {
+			    cli_errmsg("%x - %s=%s\n", s_key_sz, k, v);
+			    free(v);
+			}
+			vptr += s_sz;
+			st_sz -= s_sz;
+		    }
+		    /* FIXME: resmue here */
+		}
+	    }
+	}
+    }
+
+
     free(section_hdr);
     return 0;
 }
diff --git a/libclamav/pe.h b/libclamav/pe.h
index 774d755..6726615 100644
--- a/libclamav/pe.h
+++ b/libclamav/pe.h
@@ -155,6 +155,6 @@ int cli_scanpe(cli_ctx *ctx, icon_groupset *set);
 int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo);
 
 uint32_t cli_rawaddr(uint32_t, struct cli_exe_section *, uint16_t, unsigned int *, size_t, uint32_t);
-void findres(uint32_t, uint32_t, uint32_t, cli_ctx *, struct cli_exe_section *, uint16_t, uint32_t, int (*)(void *, uint32_t, uint32_t, uint32_t, uint32_t), void *);
+void findres(uint32_t, uint32_t, uint32_t, fmap_t *map, struct cli_exe_section *, uint16_t, uint32_t, int (*)(void *, uint32_t, uint32_t, uint32_t, uint32_t), void *);
 
 #endif
diff --git a/libclamav/pe_icons.c b/libclamav/pe_icons.c
index 73c71a2..a0ac330 100644
--- a/libclamav/pe_icons.c
+++ b/libclamav/pe_icons.c
@@ -84,7 +84,7 @@ int cli_scanicon(icon_groupset *set, uint32_t resdir_rva, cli_ctx *ctx, struct c
 
     gicons.cnt = 0;
     icons.cnt = 0;
-    findres(14, 0xffffffff, resdir_rva, ctx, exe_sections, nsections, hdr_size, groupicon_cb, &gicons);
+    findres(14, 0xffffffff, resdir_rva, map, exe_sections, nsections, hdr_size, groupicon_cb, &gicons);
 	
     for(curicon=0; curicon<gicons.cnt; curicon++) {
 	uint8_t *grp = fmap_need_off_once(map, cli_rawaddr(gicons.rvas[curicon], exe_sections, nsections, &err, map->len, hdr_size), 16);
@@ -112,7 +112,7 @@ int cli_scanicon(icon_groupset *set, uint32_t resdir_rva, cli_ctx *ctx, struct c
 		    while(icnt && gsz >= 14) {
 			dir = (struct icondir *)grp;
 			cli_dbgmsg("Icongrp @%x - %ux%ux%u - (id=%x, rsvd=%u, planes=%u, palcnt=%u, sz=%x)\n", gicons.rvas[curicon], dir->w, dir->h, dir->depth, dir->id, dir->planes, dir->palcnt, dir->rsvd, dir->sz);
-			findres(3, dir->id, resdir_rva, ctx, exe_sections, nsections, hdr_size, icon_cb, &icons);
+			findres(3, dir->id, resdir_rva, map, exe_sections, nsections, hdr_size, icon_cb, &icons);
 			grp += 14;
 			gsz -= 14;
 		    }

-- 
Debian repository for ClamAV



More information about the Pkg-clamav-commits mailing list