[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