... | ... |
@@ -2983,6 +2983,9 @@ void cli_bytecode_describe(const struct cli_bc *bc) |
2983 | 2983 |
case BC_PRECLASS: |
2984 | 2984 |
puts("preclass hook"); |
2985 | 2985 |
break; |
2986 |
+ case BC_ELF_UNPACKER: |
|
2987 |
+ puts("ELF unpacker hook"); |
|
2988 |
+ break; |
|
2986 | 2989 |
default: |
2987 | 2990 |
printf("Unknown (type %u)", bc->kind); |
2988 | 2991 |
break; |
... | ... |
@@ -3024,6 +3027,12 @@ void cli_bytecode_describe(const struct cli_bc *bc) |
3024 | 3024 |
else |
3025 | 3025 |
puts("all PRECLASS files!"); |
3026 | 3026 |
break; |
3027 |
+ case BC_ELF_UNPACKER: |
|
3028 |
+ if (bc->lsig) |
|
3029 |
+ puts("ELF files matching logical signature (unpacked)"); |
|
3030 |
+ else |
|
3031 |
+ puts("all ELF files! (unpacked)"); |
|
3032 |
+ break; |
|
3027 | 3033 |
default: |
3028 | 3034 |
puts("N/A (unknown type)\n"); |
3029 | 3035 |
break; |
... | ... |
@@ -70,6 +70,8 @@ enum BytecodeKind { |
70 | 70 |
/** specifies a PRECLASS hook, executes at the end of file property collection and |
71 | 71 |
* operates on the original file targeted for property collection */ |
72 | 72 |
BC_PRECLASS, |
73 |
+ /** specifies an ELF unpacker, executed on ELF files on a logical trigger */ |
|
74 |
+ BC_ELF_UNPACKER, |
|
73 | 75 |
_BC_LAST_HOOK |
74 | 76 |
}; |
75 | 77 |
|
... | ... |
@@ -42,11 +42,21 @@ |
42 | 42 |
#include "clamav.h" |
43 | 43 |
#include "execs.h" |
44 | 44 |
#include "matcher.h" |
45 |
+#include "scanners.h" |
|
45 | 46 |
|
46 | 47 |
#define EC16(v, conv) (conv ? cbswap16(v) : v) |
47 | 48 |
#define EC32(v, conv) (conv ? cbswap32(v) : v) |
48 | 49 |
#define EC64(v, conv) (conv ? cbswap64(v) : v) |
49 | 50 |
|
51 |
+ |
|
52 |
+#define CLI_TMPUNLK() \ |
|
53 |
+ if (!ctx->engine->keeptmp) { \ |
|
54 |
+ if (cli_unlink(tempfile)) { \ |
|
55 |
+ free(tempfile); \ |
|
56 |
+ return CL_EUNLINK; \ |
|
57 |
+ } \ |
|
58 |
+ } |
|
59 |
+ |
|
50 | 60 |
static void cli_elf_sectionlog(uint32_t sh_type, uint32_t sh_flags); |
51 | 61 |
|
52 | 62 |
static uint32_t cli_rawaddr32(uint32_t vaddr, struct elf_program_hdr32 *ph, uint16_t phnum, uint8_t conv, uint8_t *err) |
... | ... |
@@ -834,3 +844,60 @@ int cli_elfheader(fmap_t *map, struct cli_exe_info *elfinfo) |
834 | 834 |
|
835 | 835 |
return 0; |
836 | 836 |
} |
837 |
+ |
|
838 |
+/* |
|
839 |
+ * ELF file unpacking. |
|
840 |
+ */ |
|
841 |
+int cli_unpackelf(cli_ctx *ctx) |
|
842 |
+{ |
|
843 |
+ char *tempfile; |
|
844 |
+ int ndesc; |
|
845 |
+ struct cli_bc_ctx *bc_ctx; |
|
846 |
+ int ret; |
|
847 |
+ fmap_t *map = *ctx->fmap; |
|
848 |
+ |
|
849 |
+ /* Bytecode BC_ELF_UNPACKER hook */ |
|
850 |
+ bc_ctx = cli_bytecode_context_alloc(); |
|
851 |
+ if (!bc_ctx) { |
|
852 |
+ cli_errmsg("cli_scanelf: can't allocate memory for bc_ctx\n"); |
|
853 |
+ return CL_EMEM; |
|
854 |
+ } |
|
855 |
+ |
|
856 |
+ cli_bytecode_context_setctx(bc_ctx, ctx); |
|
857 |
+ |
|
858 |
+ cli_dbgmsg("Running bytecode hook\n"); |
|
859 |
+ ret = cli_bytecode_runhook(ctx, ctx->engine, bc_ctx, BC_ELF_UNPACKER, map); |
|
860 |
+ cli_dbgmsg("Finished running bytecode hook\n"); |
|
861 |
+ switch (ret) { |
|
862 |
+ case CL_VIRUS: |
|
863 |
+ cli_bytecode_context_destroy(bc_ctx); |
|
864 |
+ return CL_VIRUS; |
|
865 |
+ case CL_SUCCESS: |
|
866 |
+ ndesc = cli_bytecode_context_getresult_file(bc_ctx, &tempfile); |
|
867 |
+ cli_bytecode_context_destroy(bc_ctx); |
|
868 |
+ if (ndesc != -1 && tempfile) { |
|
869 |
+ if (ctx->engine->keeptmp) |
|
870 |
+ cli_dbgmsg("cli_scanelf: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
871 |
+ else |
|
872 |
+ cli_dbgmsg("cli_scanelf: Unpacked and rebuilt executable\n"); |
|
873 |
+ lseek(ndesc, 0, SEEK_SET); |
|
874 |
+ cli_dbgmsg("***** Scanning rebuilt ELF file *****\n"); |
|
875 |
+ if (cli_magic_scandesc(ndesc, tempfile, ctx) == CL_VIRUS) { |
|
876 |
+ close(ndesc); |
|
877 |
+ CLI_TMPUNLK(); |
|
878 |
+ free(tempfile); |
|
879 |
+ return CL_VIRUS; |
|
880 |
+ } |
|
881 |
+ close(ndesc); |
|
882 |
+ CLI_TMPUNLK(); |
|
883 |
+ free(tempfile); |
|
884 |
+ return CL_CLEAN; |
|
885 |
+ } |
|
886 |
+ break; |
|
887 |
+ default: |
|
888 |
+ cli_bytecode_context_destroy(bc_ctx); |
|
889 |
+ } |
|
890 |
+ |
|
891 |
+ return CL_CLEAN; |
|
892 |
+} |
|
893 |
+ |
... | ... |
@@ -3520,6 +3520,11 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
3520 | 3520 |
} |
3521 | 3521 |
perf_nested_stop(ctx, PERFT_PE, PERFT_SCAN); |
3522 | 3522 |
break; |
3523 |
+ case CL_TYPE_ELF: |
|
3524 |
+ perf_nested_start(ctx, PERFT_ELF, PERFT_SCAN); |
|
3525 |
+ ret = cli_unpackelf(ctx); |
|
3526 |
+ perf_nested_stop(ctx, PERFT_ELF, PERFT_SCAN); |
|
3527 |
+ break; |
|
3523 | 3528 |
case CL_TYPE_BINARY_DATA: |
3524 | 3529 |
ret = cli_fmap_scandesc(ctx, CL_TYPE_OTHER, 0, NULL, AC_SCAN_VIR, NULL, NULL); |
3525 | 3530 |
break; |