Browse code

Logical signature hook for bytecode.

Török Edvin authored on 2009/09/22 17:03:17
Showing 13 changed files
... ...
@@ -31,6 +31,9 @@
31 31
 #include "readdb.h"
32 32
 #include <string.h>
33 33
 
34
+/* TODO: we should make sure lsigcnt is never NULL, and has at least as many
35
+ * elements as the bytecode needs */
36
+static const uint32_t nomatch[64];
34 37
 struct cli_bc_ctx *cli_bytecode_context_alloc(void)
35 38
 {
36 39
     struct cli_bc_ctx *ctx = cli_malloc(sizeof(*ctx));
... ...
@@ -41,6 +44,8 @@ struct cli_bc_ctx *cli_bytecode_context_alloc(void)
41 41
     ctx->opsizes = NULL;
42 42
     ctx->fd = -1;
43 43
     ctx->off = 0;
44
+    ctx->lsigcnt = nomatch;
45
+    ctx->virname = NULL;
44 46
     return ctx;
45 47
 }
46 48
 
... ...
@@ -967,6 +972,8 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
967 967
 	    default:
968 968
 		numOp = operand_counts[inst.opcode];
969 969
 		switch (numOp) {
970
+		    case 0:
971
+			break;
970 972
 		    case 1:
971 973
 			inst.u.unaryop = readOperand(bcfunc, buffer, &offset, len, &ok);
972 974
 			break;
... ...
@@ -980,7 +987,7 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
980 980
 			inst.u.three[2] = readOperand(bcfunc, buffer, &offset, len, &ok);
981 981
 			break;
982 982
 		    default:
983
-			cli_errmsg("Opcode with too many operands: %u?\n", numOp);
983
+			cli_errmsg("Opcode %u with too many operands: %u?\n", inst.opcode, numOp);
984 984
 			ok = 0;
985 985
 			break;
986 986
 		}
... ...
@@ -1398,3 +1405,30 @@ int cli_bytecode_context_setfile(struct cli_bc_ctx *ctx, int fd)
1398 1398
     return 0;
1399 1399
 }
1400 1400
 
1401
+int cli_bytecode_runlsig(const struct cli_all_bc *bcs, const struct cli_bc *bc, const char **virname, const uint32_t* lsigcnt, int fd)
1402
+{
1403
+    int ret;
1404
+    struct cli_bc_ctx ctx;
1405
+    memset(&ctx, 0, sizeof(ctx));
1406
+    cli_bytecode_context_setfuncid(&ctx, bc, 0);
1407
+    ctx.lsigcnt = lsigcnt;
1408
+    cli_bytecode_context_setfile(&ctx, fd);
1409
+
1410
+    cli_dbgmsg("Running bytecode for logical signature match\n");
1411
+    ret = cli_bytecode_run(bcs, bc, &ctx);
1412
+    if (ret != CL_SUCCESS) {
1413
+	cli_warnmsg("Bytcode failed to run: %s\n", cl_strerror(ret));
1414
+	return CL_SUCCESS;
1415
+    }
1416
+    if (ctx.virname) {
1417
+	cli_dbgmsg("Bytecode found virus: %s\n", ctx.virname);
1418
+	if (virname)
1419
+	    *virname = ctx.virname;
1420
+	cli_bytecode_context_clear(&ctx);
1421
+	return CL_VIRUS;
1422
+    }
1423
+    ret = cli_bytecode_context_getresult_int(&ctx);
1424
+    cli_dbgmsg("Bytecode returned code: %u\n", ret);
1425
+    cli_bytecode_context_clear(&ctx);
1426
+    return CL_SUCCESS;
1427
+}
... ...
@@ -81,6 +81,9 @@ int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, stru
81 81
 void cli_bytecode_destroy(struct cli_bc *bc);
82 82
 int cli_bytecode_done(struct cli_all_bc *allbc);
83 83
 
84
+/* Hooks */
85
+int cli_bytecode_runlsig(const struct cli_all_bc *bcs, const struct cli_bc* bc, const char **virname, const uint32_t* lsigcnt, int fd);
86
+
84 87
 #ifdef __cplusplus
85 88
 extern "C" {
86 89
 #endif
... ...
@@ -80,3 +80,11 @@ uint32_t cli_bcapi_debug_print_uint(struct cli_bc_ctx *ctx, uint32_t a, uint32_t
80 80
 {
81 81
     cli_dbgmsg("bytecode debug: %u\n", a);
82 82
 }
83
+
84
+/*TODO: compiler should make sure that only constants are passed here, and not
85
+ * pointers to arbitrary locations that may not be valid when bytecode finishes
86
+ * executing */
87
+uint32_t cli_bcapi_setvirusname(struct cli_bc_ctx* ctx, const uint8_t *name, uint32_t len)
88
+{
89
+    ctx->virname = name;
90
+}
... ...
@@ -48,6 +48,9 @@ enum {
48 48
  * start of file */
49 49
 int32_t seek(int32_t pos, uint32_t whence);
50 50
 
51
+/* Set the name of the virus we have found */
52
+uint32_t setvirusname(const uint8_t *name, uint32_t len);
53
+
51 54
 uint32_t debug_print_str(const uint8_t *str, uint32_t len);
52 55
 uint32_t debug_print_uint(uint32_t a, uint32_t b);
53 56
 //const char *LogicalSignature;
... ...
@@ -28,6 +28,7 @@ uint32_t cli_bcapi_test0(struct cli_bc_ctx *ctx, struct foo*, uint32_t);
28 28
 uint32_t cli_bcapi_test1(struct cli_bc_ctx *ctx, uint32_t, uint32_t);
29 29
 int32_t cli_bcapi_read(struct cli_bc_ctx *ctx, uint8_t*, int32_t);
30 30
 int32_t cli_bcapi_seek(struct cli_bc_ctx *ctx, int32_t, uint32_t);
31
+uint32_t cli_bcapi_setvirusname(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
31 32
 uint32_t cli_bcapi_debug_print_str(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t);
32 33
 uint32_t cli_bcapi_debug_print_uint(struct cli_bc_ctx *ctx, uint32_t, uint32_t);
33 34
 
... ...
@@ -52,7 +53,8 @@ const struct cli_apicall cli_apicalls[]={
52 52
 	{"test1", 3, 0, 0},
53 53
 	{"read", 4, 1, 1},
54 54
 	{"seek", 3, 1, 0},
55
-	{"debug_print_str", 4, 2, 1},
55
+	{"setvirusname", 4, 2, 1},
56
+	{"debug_print_str", 4, 3, 1},
56 57
 	{"debug_print_uint", 3, 2, 0}
57 58
 /* Bytecode APIcalls END */
58 59
 };
... ...
@@ -64,6 +66,7 @@ const cli_apicall_int2 cli_apicalls0[] = {
64 64
 const cli_apicall_pointer cli_apicalls1[] = {
65 65
 	(cli_apicall_pointer)cli_bcapi_test0,
66 66
 	(cli_apicall_pointer)cli_bcapi_read,
67
+	(cli_apicall_pointer)cli_bcapi_setvirusname,
67 68
 	(cli_apicall_pointer)cli_bcapi_debug_print_str
68 69
 };
69 70
 const unsigned cli_apicall_maxapi = sizeof(cli_apicalls)/sizeof(cli_apicalls[0]);
... ...
@@ -25,5 +25,8 @@ uint32_t cli_bcapi_test1(struct cli_bc_ctx *, uint32_t, uint32_t);
25 25
 
26 26
 int32_t cli_bcapi_read(struct cli_bc_ctx*, uint8_t *data, int32_t size);
27 27
 int32_t cli_bcapi_seek(struct cli_bc_ctx*, int32_t pos, uint32_t whence);
28
+
29
+uint32_t cli_bcapi_setvirusname(struct cli_bc_ctx*, const uint8_t *name, uint32_t len);
30
+
28 31
 uint32_t cli_bcapi_debug_print_str(struct cli_bc_ctx *ctx, const uint8_t*, uint32_t);
29 32
 uint32_t cli_bcapi_debug_print_uint(struct cli_bc_ctx *ctx, uint32_t, uint32_t);
... ...
@@ -99,6 +99,7 @@ struct cli_bc_ctx {
99 99
     off_t off;
100 100
     int fd;
101 101
     const uint32_t *lsigcnt;
102
+    const char *virname;
102 103
 };
103 104
 struct cli_all_bc;
104 105
 int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct cli_bc_func *func, const struct cli_bc_inst *inst);
... ...
@@ -13,7 +13,7 @@
13 13
 #  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
14 14
 #  MA 02110-1301, USA.
15 15
 
16
-AM_CPPFLAGS = -I$(top_srcdir)/../.. -I$(top_srcdir)/..
16
+AM_CPPFLAGS = -I$(top_srcdir)/../.. -I$(top_srcdir)/.. -I$(top_builddir)/../../
17 17
 ACLOCAL_AMFLAGS=-I m4
18 18
 if DEBUG_BUILD
19 19
 LLVM_CONFIG=llvm/Debug/bin/llvm-config
... ...
@@ -933,7 +933,7 @@ target_vendor = @target_vendor@
933 933
 top_build_prefix = @top_build_prefix@
934 934
 top_builddir = @top_builddir@
935 935
 top_srcdir = @top_srcdir@
936
-AM_CPPFLAGS = -I$(top_srcdir)/../.. -I$(top_srcdir)/..
936
+AM_CPPFLAGS = -I$(top_srcdir)/../.. -I$(top_srcdir)/.. -I$(top_builddir)/../../
937 937
 ACLOCAL_AMFLAGS = -I m4
938 938
 @DEBUG_BUILD_FALSE@LLVM_CONFIG = llvm/Release/bin/llvm-config
939 939
 @DEBUG_BUILD_TRUE@LLVM_CONFIG = llvm/Debug/bin/llvm-config
... ...
@@ -57,6 +57,15 @@
57 57
 #ifndef LLVM_MULTITHREADED
58 58
 #error "Multithreading support must be available to LLVM!"
59 59
 #endif
60
+
61
+#ifdef HAVE_CONFIG_H
62
+#undef PACKAGE_BUGREPORT
63
+#undef PACKAGE_NAME
64
+#undef PACKAGE_STRING
65
+#undef PACKAGE_TARNAME
66
+#undef PACKAGE_VERSION
67
+#include "clamav-config.h"
68
+#endif
60 69
 #include "clamav.h"
61 70
 #include "clambc.h"
62 71
 #include "bytecode_priv.h"
... ...
@@ -344,7 +353,6 @@ public:
344 344
     {}
345 345
 
346 346
     bool generate() {
347
-	PrettyStackTraceString Trace(BytecodeID.str().c_str());
348 347
 	TypeMap = new LLVMTypeMapper(Context, bc->types + 4, bc->num_types - 5);
349 348
 
350 349
 	FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context),
... ...
@@ -602,6 +610,9 @@ public:
602 602
 			case OP_BC_RET:
603 603
 			    Builder.CreateRet(Op0);
604 604
 			    break;
605
+			case OP_BC_RET_VOID:
606
+			    Builder.CreateRetVoid();
607
+			    break;
605 608
 			case OP_BC_ICMP_EQ:
606 609
 			    Store(inst->dest, Builder.CreateICmpEQ(Op0, Op1));
607 610
 			    break;
... ...
@@ -651,7 +662,8 @@ public:
651 651
 			    }
652 652
 			    CallInst *CI = Builder.CreateCall(DestF, args.begin(), args.end());
653 653
 			    CI->setCallingConv(CallingConv::Fast);
654
-			    Store(inst->dest, CI);
654
+			    if (CI->getType()->getTypeID() != Type::VoidTyID)
655
+				Store(inst->dest, CI);
655 656
 			    break;
656 657
 			}
657 658
 			case OP_BC_CALL_API:
... ...
@@ -904,6 +916,8 @@ int bytecode_init(void)
904 904
     llvm_install_error_handler(llvm_error_handler);
905 905
 #ifdef CL_DEBUG
906 906
     sys::PrintStackTraceOnErrorSignal();
907
+#else
908
+    llvm::DisablePrettyStackTrace = true;
907 909
 #endif
908 910
     atexit(do_shutdown);
909 911
 
... ...
@@ -318,7 +318,7 @@ int cli_checkfp(int fd, cli_ctx *ctx)
318 318
 
319 319
 int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode)
320 320
 {
321
- 	unsigned char *buffer, *buff, *endbl, *upt;
321
+        unsigned char *buffer, *buff, *endbl, *upt;
322 322
 	int ret = CL_CLEAN, type = CL_CLEAN, bytes;
323 323
 	unsigned int i, evalcnt;
324 324
 	uint32_t buffersize, length, maxpatlen, shift = 0, offset = 0;
... ...
@@ -459,10 +459,16 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc
459 459
 	    evalcnt = 0;
460 460
 	    evalids = 0;
461 461
 	    if(cli_ac_chklsig(troot->ac_lsigtable[i]->logic, troot->ac_lsigtable[i]->logic + strlen(troot->ac_lsigtable[i]->logic), tdata.lsigcnt[i], &evalcnt, &evalids, 0) == 1) {
462
-		if(ctx->virname)
463
-		    *ctx->virname = troot->ac_lsigtable[i]->virname;
464
-		ret = CL_VIRUS;
465
-		break;
462
+		if (!troot->ac_lsigtable[i]->bc) {
463
+		    if(ctx->virname)
464
+			*ctx->virname = troot->ac_lsigtable[i]->virname;
465
+		    ret = CL_VIRUS;
466
+		    break;
467
+		}
468
+		if (cli_bytecode_runlsig(&ctx->engine->bcs, troot->ac_lsigtable[i]->bc, ctx->virname, tdata.lsigcnt[i], desc) == CL_VIRUS) {
469
+		    ret = CL_VIRUS;
470
+		    break;
471
+		}
466 472
 	    }
467 473
 	}
468 474
 	cli_ac_freedata(&tdata);
... ...
@@ -473,10 +479,16 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc
473 473
 	    evalcnt = 0;
474 474
 	    evalids = 0;
475 475
 	    if(cli_ac_chklsig(groot->ac_lsigtable[i]->logic, groot->ac_lsigtable[i]->logic + strlen(groot->ac_lsigtable[i]->logic), gdata.lsigcnt[i], &evalcnt, &evalids, 0) == 1) {
476
-		if(ctx->virname)
477
-		    *ctx->virname = groot->ac_lsigtable[i]->virname;
478
-		ret = CL_VIRUS;
479
-		break;
476
+		if (!groot->ac_lsigtable[i]->bc) {
477
+		    if(ctx->virname)
478
+			*ctx->virname = groot->ac_lsigtable[i]->virname;
479
+		    ret = CL_VIRUS;
480
+		    break;
481
+		}
482
+		if (cli_bytecode_runlsig(&ctx->engine->bcs, groot->ac_lsigtable[i]->bc, ctx->virname, gdata.lsigcnt[i], desc) == CL_VIRUS) {
483
+		    ret = CL_VIRUS;
484
+		    break;
485
+		}
480 486
 	    }
481 487
 	}
482 488
 	cli_ac_freedata(&gdata);
... ...
@@ -882,6 +882,16 @@ static int load_oneldb(char *buffer, int chkpua, int chkign, struct cl_engine *e
882 882
 	cli_errmsg("cli_loadldb: Broken logical expression or too many subsignatures\n");
883 883
 	return CL_EMALFDB;
884 884
     }
885
+    if (!line) {
886
+	/* This is a logical signature from the bytecode, we need all
887
+	 * subsignatures, even if not referenced from the logical expression */
888
+	if (subsigs > tokens_count-3) {
889
+	    cli_errmsg("load_oneldb: Too many subsignatures: %u (max %u)\n",
890
+		       subsigs, tokens_count-3);
891
+	    return CL_EMALFDB;
892
+	}
893
+	subsigs = tokens_count-3;
894
+    }
885 895
 
886 896
     /* TDB */
887 897
     memset(&tdb, 0, sizeof(tdb));
... ...
@@ -937,7 +947,7 @@ static int load_oneldb(char *buffer, int chkpua, int chkign, struct cl_engine *e
937 937
     root->ac_lsigtable = newtable;
938 938
 
939 939
     for(i = 0; i < subsigs; i++) {
940
-	if(i >= tokens_count) {
940
+	if(i+3 >= tokens_count) {
941 941
 	    cli_errmsg("cli_loadldb: Missing subsignature id %u\n", i);
942 942
 	    return CL_EMALFDB;
943 943
 	}
... ...
@@ -1,7 +1,11 @@
1
-ClamBCaa`|`````|`aoaap`clamcoincidencejb
1
+ClamBCaa`|`````|`bbaabp`clamcoincidencejb
2 2
 L;Target:0;((0|1|2)=42,2);aabb;ffffffff;aaccee;f00d
3
-Tedebndebmdebldebkdebadebcddadb`bdagahdaiahdaeah
4
-E``
5
-GalbndBafBafBbfBbf@`bmdBffBffBffBffBffBffBffBff@`bndBffB`cB`cBdf@`bldBafBafBcfBcfBefBef@`bad@@`bad@Aa`bad@Ab`bad@Ac`bcdAcD```h`bcdAbD```h`bcd@D```h`bcdAaD```h`
6
-A`b`bLacb`baab`bFadaa
7
-Bb`b`gbAh`aaaaeab`b`Abdb`bab`aaaTcab`babE
3
+Tedebaeeb`eebodebndebmdebadebcdacb`bbadb`bdadb`bdakahdagahdaiahdaeah
4
+Eaeaaaebld|amcgefdgfgifbgegcgnfafmfef``
5
+GanbaeBafBafBbfBbf@`b`eBffBffBffBffBffBffBffBff@`baeBffB`cB`cBdf@`bodBafBafBcfBcfBefBef@`bndBdeBbgBofBjfBafBnfBnbBfdBodBod@`bad@@`bad@Aa`bad@Ab`bad@Ac`bad@Ad`bcdAcD```h`bcdAbD```h`bcd@D```h`bcdAaD```h`
6
+A`b`bLacb`baa`Fafac
7
+Bb`b`gbAj`aaaaeab`b`AbdTaaaaaaab
8
+B```b`abTcab`b@d
9
+BTcab`b@dE
10
+A``Laab`bFabaa
11
+Bb`b`abbaeAi`@dTdaE