| ... | ... |
@@ -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 |