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

Török Edvin edwin at clamav.net
Sun Apr 4 01:06:52 UTC 2010


The following commit has been merged in the debian/unstable branch:
commit ab63657088ee8db1bb9c7824320afa69d56a067b
Author: Török Edvin <edwin at clamav.net>
Date:   Fri Oct 2 17:33:11 2009 +0300

    Add generic and PE hooks.

diff --git a/libclamav/bytecode.c b/libclamav/bytecode.c
index d686998..71484b7 100644
--- a/libclamav/bytecode.c
+++ b/libclamav/bytecode.c
@@ -26,6 +26,7 @@
 
 #include "clamav.h"
 #include "others.h"
+#include "pe.h"
 #include "bytecode.h"
 #include "bytecode_priv.h"
 #include "readdb.h"
@@ -45,6 +46,7 @@ struct cli_bc_ctx *cli_bytecode_context_alloc(void)
     ctx->fd = -1;
     ctx->off = 0;
     ctx->hooks.match_counts = nomatch;
+    /* TODO: init all hooks with safe values */
     ctx->virname = NULL;
     return ctx;
 }
@@ -55,11 +57,18 @@ void cli_bytecode_context_destroy(struct cli_bc_ctx *ctx)
    free(ctx);
 }
 
-int cli_bytecode_context_clear(struct cli_bc_ctx *ctx)
+/* resets bytecode state, so you can run another bytecode with same ctx */
+int cli_bytecode_context_reset(struct cli_bc_ctx *ctx)
 {
     free(ctx->opsizes);
     free(ctx->values);
     free(ctx->operands);
+    return CL_SUCCESS;
+}
+
+int cli_bytecode_context_clear(struct cli_bc_ctx *ctx)
+{
+    cli_bytecode_context_reset(ctx);
     memset(ctx, 0, sizeof(ctx));
     return CL_SUCCESS;
 }
@@ -1435,7 +1444,46 @@ int cli_bytecode_runlsig(const struct cli_all_bc *bcs, const struct cli_bc *bc,
 	return CL_VIRUS;
     }
     ret = cli_bytecode_context_getresult_int(&ctx);
-    cli_dbgmsg("Bytecode returned code: %u\n", ret);
+    cli_dbgmsg("Bytecode %u returned code: %u\n", bc->id, ret);
     cli_bytecode_context_clear(&ctx);
     return CL_SUCCESS;
 }
+
+int cli_bytecode_runhook(const struct cl_engine *engine, struct cli_bc_ctx *ctx,
+			 unsigned id, int fd, const char **virname)
+{
+    const unsigned *hooks = engine->hooks[id - _BC_START_HOOKS];
+    unsigned i, hooks_cnt = engine->hooks_cnt[id - _BC_START_HOOKS];
+    int ret;
+
+    cli_bytecode_context_setfile(ctx, fd);
+    cli_dbgmsg("Bytecode executing hook id %u (%u hooks)\n", id, hooks_cnt);
+    for (i=0;i < hooks_cnt;i++) {
+	const struct cli_bc *bc = &engine->bcs.all_bcs[hooks[i]];
+	cli_bytecode_context_setfuncid(ctx, bc, 0);
+	ret = cli_bytecode_run(&engine->bcs, bc, ctx);
+	if (ret != CL_SUCCESS) {
+	    cli_warnmsg("Bytecode failed to run: %s\n", cl_strerror(ret));
+	    return CL_SUCCESS;
+	}
+	if (ctx->virname) {
+	    cli_dbgmsg("Bytecode found virus: %s\n", ctx->virname);
+	    if (virname)
+		*virname = ctx->virname;
+	    cli_bytecode_context_clear(ctx);
+	    return CL_VIRUS;
+	}
+	ret = cli_bytecode_context_getresult_int(ctx);
+	/* TODO: use prefix here */
+	cli_dbgmsg("Bytecode %u returned %u\n", bc->id, ret);
+	cli_bytecode_context_reset(ctx);
+    }
+    return CL_CLEAN;
+}
+
+int cli_bytecode_context_setpe(struct cli_bc_ctx *ctx, const struct cli_pe_hook_data *data)
+{
+    ctx->hooks.exeinfo = &data->exe_info;
+    ctx->hooks.pedata = data;
+    return 0;
+}
diff --git a/libclamav/bytecode.h b/libclamav/bytecode.h
index 1cf9d98..a10a133 100644
--- a/libclamav/bytecode.h
+++ b/libclamav/bytecode.h
@@ -32,6 +32,7 @@ struct cli_bc_inst;
 struct cli_bc_type;
 struct cli_bc_engine;
 struct bitset_tag;
+struct cl_engine;
 
 enum bc_state {
     bc_skip,
@@ -65,11 +66,13 @@ struct cli_all_bc {
     struct cli_bcengine *engine;
 };
 
+struct cli_pe_hook_data;
 struct cli_bc_ctx *cli_bytecode_context_alloc(void);
 int cli_bytecode_context_setfuncid(struct cli_bc_ctx *ctx, const struct cli_bc *bc, unsigned funcid);
 int cli_bytecode_context_setparam_int(struct cli_bc_ctx *ctx, unsigned i, uint64_t c);
 int cli_bytecode_context_setparam_ptr(struct cli_bc_ctx *ctx, unsigned i, void *data, unsigned datalen);
 int cli_bytecode_context_setfile(struct cli_bc_ctx *ctx, int fd);
+int cli_bytecode_context_setpe(struct cli_bc_ctx *ctx, const struct cli_pe_hook_data *data);
 int cli_bytecode_context_clear(struct cli_bc_ctx *ctx);
 uint64_t cli_bytecode_context_getresult_int(struct cli_bc_ctx *ctx);
 void cli_bytecode_context_destroy(struct cli_bc_ctx *ctx);
@@ -83,7 +86,9 @@ void cli_bytecode_destroy(struct cli_bc *bc);
 int cli_bytecode_done(struct cli_all_bc *allbc);
 
 /* Hooks */
+struct cli_exe_info;
 int cli_bytecode_runlsig(const struct cli_all_bc *bcs, const struct cli_bc* bc, const char **virname, const uint32_t* lsigcnt, int fd);
+int cli_bytecode_runhook(const struct cl_engine *engine, struct cli_bc_ctx *ctx, unsigned id, int fd, const char **virname);
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/libclamav/bytecode_api.h b/libclamav/bytecode_api.h
index ae736a3..88c44ad 100644
--- a/libclamav/bytecode_api.h
+++ b/libclamav/bytecode_api.h
@@ -19,6 +19,8 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  *  MA 02110-1301, USA.
  */
+#ifndef BYTECODE_API_H
+#define BYTECODE_API_H
 
 #ifdef __CLAMBC__
 #include "bytecode_execs.h"
@@ -32,16 +34,19 @@ struct foo {
     struct foo *nxt;
 };
 
+enum BytecodeKind {
+    BC_GENERIC=0,/* generic bytecode, not tied to a specific hook */
+    _BC_START_HOOKS=256,
+    BC_LOGICAL=256,/* triggered by a logical signature */
+    BC_PE_UNPACKER,/* a PE unpacker */
+    _BC_LAST_HOOK
+};
+
 #ifdef __CLAMBC__
 
 extern const uint32_t __clambc_match_counts[64];
 extern const struct cli_exe_info __clambc_exeinfo;
 
-enum BytecodeKind {
-    BC_GENERIC=0,/* generic bytecode, not tied to a specific hook */
-    BC_LOGICAL,/* triggered by a logical signature */
-    BC_PE_UNPACKER,/* a PE unpacker */
-};
 const uint8_t __clambc_kind;
 
 uint32_t test0(struct foo*, uint32_t);
@@ -68,3 +73,4 @@ uint32_t debug_print_uint(uint32_t a, uint32_t b);
 //const char *LogicalSignature;
 
 #endif
+#endif
diff --git a/libclamav/bytecode_hooks.h b/libclamav/bytecode_hooks.h
index 47305f5..a068dc2 100644
--- a/libclamav/bytecode_hooks.h
+++ b/libclamav/bytecode_hooks.h
@@ -24,7 +24,8 @@
 
 struct cli_bc_hooks {
 	 const uint32_t* match_counts;
-	 const struct cli_exe_info exeinfo;
+	 const struct cli_exe_info *exeinfo;
+	 const struct cli_pe_hook_data *pedata;
 	 const uint8_t kind;
 };
 #endif
diff --git a/libclamav/others.h b/libclamav/others.h
index e74038b..b1dd94f 100644
--- a/libclamav/others.h
+++ b/libclamav/others.h
@@ -41,6 +41,7 @@
 #include "libclamunrar_iface/unrar_iface.h"
 #include "regex/regex.h"
 #include "bytecode.h"
+#include "bytecode_api.h"
 
 /*
  * CL_FLEVEL is the signature f-level specific to the current code and
@@ -181,6 +182,8 @@ struct cl_engine {
 
     /* Used for bytecode */
     struct cli_all_bc bcs;
+    unsigned *hooks[_BC_LAST_HOOK - _BC_START_HOOKS];
+    unsigned hooks_cnt[_BC_LAST_HOOK - _BC_START_HOOKS];
 };
 
 struct cl_settings {
diff --git a/libclamav/pe.c b/libclamav/pe.c
index c8b1029..ae3285f 100644
--- a/libclamav/pe.c
+++ b/libclamav/pe.c
@@ -439,18 +439,20 @@ int cli_scanpe(int desc, cli_ctx *ctx)
 	char *src = NULL, *dest = NULL;
 	int ndesc, ret = CL_CLEAN, upack = 0, native=0;
 	size_t fsize;
-	uint32_t valign, falign, hdr_size, j;
+	uint32_t valign, falign, hdr_size, j, offset;
 	struct cli_exe_section *exe_sections;
 	struct cli_matcher *md5_sect;
 	char timestr[32];
 	struct pe_image_data_dir *dirs;
+	struct cli_bc_ctx *bc_ctx;
+	struct cli_pe_hook_data pedata;
 
 
     if(!ctx) {
 	cli_errmsg("cli_scanpe: ctx == NULL\n");
 	return CL_ENULLARG;
     }
-
+    offset = lseek(desc, 0, SEEK_CUR);
     if(cli_readn(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) {
 	cli_dbgmsg("Can't read DOS signature\n");
 	return CL_CLEAN;
@@ -2252,6 +2254,27 @@ int cli_scanpe(int desc, cli_ctx *ctx)
 
     /* to be continued ... */
 
+    /* Bytecode */
+    bc_ctx = cli_bytecode_context_alloc();
+    if (!bc_ctx) {
+	cli_errmsg("cli_scanpe: can't allocate memory for bc_ctx\n");
+	return CL_EMEM;
+    }
+    pedata.exe_info.section = exe_sections;
+    pedata.exe_info.nsections = nsections;
+    pedata.exe_info.ep = ep;
+    pedata.exe_info.offset = offset;
+    pedata.file_hdr = &file_hdr;
+    pedata.opt32 = &pe_opt.opt32;
+    pedata.opt64 = &pe_opt.opt64;
+    pedata.dirs = dirs;
+    pedata.overlays = overlays;
+    pedata.overlays_sz = fsize - overlays;
+    cli_bytecode_context_setpe(bc_ctx, &pedata);
+    if (cli_bytecode_runhook(ctx->engine, bc_ctx, BC_PE_UNPACKER, desc, ctx->virname) == CL_VIRUS)
+	return CL_VIRUS;
+    cli_bytecode_context_destroy(bc_ctx);
+
     free(exe_sections);
     return CL_CLEAN;
 }
diff --git a/libclamav/pe.h b/libclamav/pe.h
index a8ad47a..35cab9e 100644
--- a/libclamav/pe.h
+++ b/libclamav/pe.h
@@ -128,6 +128,16 @@ struct pe_image_section_hdr {
     uint32_t Characteristics;
 };
 
+struct cli_pe_hook_data {
+    struct cli_exe_info exe_info;
+    struct pe_image_file_hdr *file_hdr;
+    struct pe_image_optional_hdr32 *opt32;
+    struct pe_image_optional_hdr64 *opt64;
+    struct pe_image_data_dir *dirs;
+    uint32_t overlays;
+    int32_t overlays_sz;
+};
+
 int cli_scanpe(int desc, cli_ctx *ctx);
 
 int cli_peheader(int desc, struct cli_exe_info *peinfo);
diff --git a/libclamav/readdb.c b/libclamav/readdb.c
index 4251d75..cf4e15e 100644
--- a/libclamav/readdb.c
+++ b/libclamav/readdb.c
@@ -70,6 +70,7 @@
 
 #include "mpool.h"
 #include "bytecode.h"
+#include "bytecode_api.h"
 #include "bytecode_priv.h"
 #ifdef CL_THREAD_SAFE
 #  include <pthread.h>
@@ -1044,6 +1045,7 @@ static int cli_loadcbc(FILE *fs, struct cl_engine *engine, unsigned int *signo,
     struct cli_bc *bc;
     unsigned sigs = 0;
 
+    /* TODO: virusname have a common prefix, and whitelist by that */
     if((rc = cli_initroots(engine, options)))
 	return rc;
 
@@ -1059,18 +1061,42 @@ static int cli_loadcbc(FILE *fs, struct cl_engine *engine, unsigned int *signo,
     bc = &bcs->all_bcs[bcs->count-1];
     rc = cli_bytecode_load(bc, fs, dbio);
     if (rc != CL_SUCCESS) {
-	fprintf(stderr,"Unable to load %s bytecode: %s\n", dbname, cl_strerror(rc));
+	cli_errmsg("Unable to load %s bytecode: %s\n", dbname, cl_strerror(rc));
 	return rc;
     }
     sigs += 2;/* the bytecode itself and the logical sig */
-    if (bc->lsig) {
+    if (bc->kind == BC_LOGICAL) {
+	if (!bc->lsig) {
+	    cli_errmsg("Bytecode %s has logical kind, but missing logical signature!\n", dbname);
+	    return CL_EMALFDB;
+	}
 	cli_dbgmsg("Bytecode %s has logical signature: %s\n", dbname, bc->lsig);
 	rc = load_oneldb(bc->lsig, 0, 0, engine, options, dbname, 0, &sigs, bc, NULL);
 	if (rc != CL_SUCCESS) {
-	    fprintf(stderr,"Problem parsing logical signature %s for bytecode %s: %s\n",
-		    bc->lsig, dbname, cl_strerror(rc));
+	    cli_errmsg("Problem parsing logical signature %s for bytecode %s: %s\n",
+		       bc->lsig, dbname, cl_strerror(rc));
 	    return rc;
 	}
+    } else {
+	if (bc->lsig) {
+	    cli_errmsg("Bytecode %s has logical signature but is not logical kind!\n", dbname);
+	    return CL_EMALFDB;
+	}
+	if (bc->kind >= _BC_START_HOOKS && bc->kind < _BC_LAST_HOOK) {
+	    unsigned hook = bc->kind - _BC_START_HOOKS;
+	    unsigned cnt = ++engine->hooks_cnt[hook];
+	    engine->hooks[hook] = cli_realloc2(engine->hooks[hook],
+					       sizeof(*engine->hooks[0])*cnt);
+	    if (!engine->hooks[hook]) {
+		cli_errmsg("Out of memory allocating memory for hook %u", hook);
+		return CL_EMEM;
+	    }
+	    engine->hooks[hook][cnt-1] = bcs->count-1;
+	} else switch (bc->kind) {
+	    default:
+		cli_errmsg("Bytecode: unhandled bytecode kind %u\n", bc->kind);
+		return CL_EMALFDB;
+	}
     }
     if (signo)
 	*signo += sigs;
@@ -2199,6 +2225,9 @@ int cl_engine_free(struct cl_engine *engine)
 		cli_bytecode_destroy(&engine->bcs.all_bcs[i]);
 	cli_bytecode_done(&engine->bcs);
 	free(engine->bcs.all_bcs);
+	for (i=0;i<_BC_LAST_HOOK - _BC_START_HOOKS;i++) {
+	    free (engine->hooks[i]);
+	}
     }
     if(engine->dconf->phishing & PHISHING_CONF_ENGINE)
 	phishing_done(engine);
@@ -2286,7 +2315,7 @@ int cl_engine_compile(struct cl_engine *engine)
 
     /* Compile bytecode */
     if((ret = cli_bytecode_prepare(&engine->bcs))) {
-	fprintf(stderr,"Unable to compile/load bytecode: %s\n", cl_strerror(ret));
+	cli_errmsg("Unable to compile/load bytecode: %s\n", cl_strerror(ret));
 	return ret;
     }
 

-- 
Debian repository for ClamAV



More information about the Pkg-clamav-commits mailing list