Browse code

Fix bytecode virusname reporting (bb #2255).

Also adds possibility to stop a hook from executing, and set
a virus as heuristic (by using BC.Heuristic* name)

Török Edvin authored on 2010/09/11 04:11:32
Showing 6 changed files
... ...
@@ -1,3 +1,7 @@
1
+Fri Sep 10 22:10:33 EEST 2010 (edwin)
2
+-------------------------------------
3
+ * libclamav/pdf.c, pe.c, bytecode*: Fix bytecode virusname reporting (bb #2255)
4
+
1 5
 Fri Sep 10 10:52:45 CEST 2010 (acab)
2 6
 ------------------------------------
3 7
  * clamav-milter/netcode.c: fix error path fd leak when connection succeeds
... ...
@@ -130,7 +130,6 @@ static int cli_bytecode_context_reset(struct cli_bc_ctx *ctx)
130 130
 
131 131
     if (ctx->outfd) {
132 132
 	cli_ctx *cctx = ctx->ctx;
133
-	cli_bcapi_extract_new(ctx, -1);
134 133
 	if (ctx->outfd)
135 134
 	    close(ctx->outfd);
136 135
 	if (ctx->tempfile && (!cctx || !cctx->engine->keeptmp)) {
... ...
@@ -1560,6 +1559,7 @@ int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio, int tru
1560 1560
 
1561 1561
 int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, struct cli_bc_ctx *ctx)
1562 1562
 {
1563
+    int ret;
1563 1564
     struct cli_bc_inst inst;
1564 1565
     struct cli_bc_func func;
1565 1566
     if (!ctx || !ctx->bc || !ctx->func)
... ...
@@ -1593,10 +1593,16 @@ int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, stru
1593 1593
 	inst.u.ops.ops = ctx->operands;
1594 1594
 	inst.u.ops.opsizes = ctx->opsizes;
1595 1595
 	cli_dbgmsg("Bytecode: executing in interpeter mode\n");
1596
-	return cli_vm_execute(ctx->bc, ctx, &func, &inst);
1596
+	ret = cli_vm_execute(ctx->bc, ctx, &func, &inst);
1597
+    } else {
1598
+	cli_dbgmsg("Bytecode: executing in JIT mode\n");
1599
+	ret = cli_vm_execute_jit(bcs, ctx, &bc->funcs[ctx->funcid]);
1597 1600
     }
1598
-    cli_dbgmsg("Bytecode: executing in JIT mode\n");
1599
-    return cli_vm_execute_jit(bcs, ctx, &bc->funcs[ctx->funcid]);
1601
+    /* need to be called here to catch any extracted but not yet scanned files
1602
+     */
1603
+    if (ctx->outfd)
1604
+	cli_bcapi_extract_new(ctx, -1);
1605
+    return ret;
1600 1606
 }
1601 1607
 
1602 1608
 uint64_t cli_bytecode_context_getresult_int(struct cli_bc_ctx *ctx)
... ...
@@ -2463,11 +2469,16 @@ int cli_bytecode_runlsig(cli_ctx *cctx, struct cli_target_info *tinfo,
2463 2463
 	return CL_SUCCESS;
2464 2464
     }
2465 2465
     if (ctx.virname) {
2466
+	int rc;
2466 2467
 	cli_dbgmsg("Bytecode found virus: %s\n", ctx.virname);
2467 2468
 	if (virname)
2468 2469
 	    *virname = ctx.virname;
2470
+	if (!strncmp(*virname, "BC.Heuristics", 13))
2471
+	    rc = cli_found_possibly_unwanted(cctx);
2472
+	else
2473
+	    rc = CL_VIRUS;
2469 2474
 	cli_bytecode_context_clear(&ctx);
2470
-	return CL_VIRUS;
2475
+	return rc;
2471 2476
     }
2472 2477
     ret = cli_bytecode_context_getresult_int(&ctx);
2473 2478
     cli_dbgmsg("Bytecode %u returned code: %u\n", bc->id, ret);
... ...
@@ -2481,7 +2492,7 @@ int cli_bytecode_runhook(cli_ctx *cctx, const struct cl_engine *engine, struct c
2481 2481
     const unsigned *hooks = engine->hooks[id - _BC_START_HOOKS];
2482 2482
     unsigned i, hooks_cnt = engine->hooks_cnt[id - _BC_START_HOOKS];
2483 2483
     int ret;
2484
-    unsigned executed = 0;
2484
+    unsigned executed = 0, breakflag = 0;
2485 2485
 
2486 2486
     cli_bytecode_context_setfile(ctx, map);
2487 2487
     cli_dbgmsg("Bytecode executing hook id %u (%u hooks)\n", id, hooks_cnt);
... ...
@@ -2513,6 +2524,10 @@ int cli_bytecode_runhook(cli_ctx *cctx, const struct cl_engine *engine, struct c
2513 2513
 	ret = cli_bytecode_context_getresult_int(ctx);
2514 2514
 	/* TODO: use prefix here */
2515 2515
 	cli_dbgmsg("Bytecode %u returned %u\n", bc->id, ret);
2516
+	if (ret == 0xcea5e) {
2517
+	    cli_dbgmsg("Bytecode set BREAK flag in hook!\n");
2518
+	    breakflag = 1;
2519
+	}
2516 2520
 	if (!ret) {
2517 2521
 	    char *tempfile;
2518 2522
 	    int fd = cli_bytecode_context_getresult_file(ctx, &tempfile);
... ...
@@ -2550,7 +2565,7 @@ int cli_bytecode_runhook(cli_ctx *cctx, const struct cl_engine *engine, struct c
2550 2550
 	cli_dbgmsg("Bytecode: executed %u bytecodes for this hook\n", executed);
2551 2551
     else
2552 2552
 	cli_dbgmsg("Bytecode: no logical signature matched, no bytecode executed\n");
2553
-    return CL_CLEAN;
2553
+    return breakflag ? CL_BREAK : CL_CLEAN;
2554 2554
 }
2555 2555
 
2556 2556
 int cli_bytecode_context_setpe(struct cli_bc_ctx *ctx, const struct cli_pe_hook_data *data, const struct cli_exe_section *sections)
... ...
@@ -460,8 +460,11 @@ int32_t cli_bcapi_extract_new(struct cli_bc_ctx *ctx, int32_t id)
460 460
 	    cctx->container_type = ctx->containertype;
461 461
 	res = cli_magic_scandesc(ctx->outfd, cctx);
462 462
 	cctx->container_type = current;
463
-	if (res == CL_VIRUS)
463
+	if (res == CL_VIRUS) {
464
+	    if (cctx->virname)
465
+		ctx->virname = *cctx->virname;
464 466
 	    ctx->found = 1;
467
+	}
465 468
     }
466 469
     if ((cctx && cctx->engine->keeptmp) ||
467 470
 	(ftruncate(ctx->outfd, 0) == -1)) {
... ...
@@ -77,7 +77,8 @@ enum pdf_phase {
77 77
     PDF_PHASE_NONE /* not a PDF */,
78 78
     PDF_PHASE_PARSED, /* after parsing a PDF, object flags can be set etc. */
79 79
     PDF_PHASE_POSTDUMP, /* after an obj was dumped and scanned */
80
-    PDF_PHASE_END /* after the pdf scan finished */
80
+    PDF_PHASE_END, /* after the pdf scan finished */
81
+    PDF_PHASE_PRE /* before pdf is parsed at all */
81 82
 };
82 83
 
83 84
 /** PDF flags */
... ...
@@ -1082,6 +1082,11 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset)
1082 1082
 	cli_errmsg("cli_pdf: mmap() failed (3)\n");
1083 1083
 	return CL_EMAP;
1084 1084
     }
1085
+    rc = run_pdf_hooks(&pdf, PDF_PHASE_PRE, -1, -1);
1086
+    if (rc) {
1087
+	cli_dbgmsg("cli_pdf: returning %d\n", rc);
1088
+	return rc;
1089
+    }
1085 1090
     /* parse PDF and find obj offsets */
1086 1091
     while ((rc = pdf_findobj(&pdf)) > 0) {
1087 1092
 	struct pdf_obj *obj = &pdf.objs[pdf.nobjs-1];
... ...
@@ -1130,10 +1130,10 @@ int cli_scanpe(cli_ctx *ctx)
1130 1130
     cli_bytecode_context_setpe(bc_ctx, &pedata, exe_sections);
1131 1131
     cli_bytecode_context_setctx(bc_ctx, ctx);
1132 1132
     ret = cli_bytecode_runhook(ctx, ctx->engine, bc_ctx, BC_PE_ALL, map, ctx->virname);
1133
-    if (ret == CL_VIRUS) {
1133
+    if (ret == CL_VIRUS || ret == CL_BREAK) {
1134 1134
 	free(exe_sections);
1135 1135
 	cli_bytecode_context_destroy(bc_ctx);
1136
-	return CL_VIRUS;
1136
+	return ret == CL_VIRUS ? CL_VIRUS : CL_CLEAN;
1137 1137
     }
1138 1138
     cli_bytecode_context_destroy(bc_ctx);
1139 1139