Linux bytecode unpackers

This commit is contained in:
Jonas Zaddach 2019-03-19 15:28:49 +01:00 committed by Micah Snyder
parent ddc1c9bb11
commit 2b776e4b89
6 changed files with 86 additions and 0 deletions

View file

@ -2983,6 +2983,9 @@ void cli_bytecode_describe(const struct cli_bc *bc)
case BC_PRECLASS:
puts("preclass hook");
break;
case BC_ELF_UNPACKER:
puts("ELF unpacker hook");
break;
default:
printf("Unknown (type %u)", bc->kind);
break;
@ -3024,6 +3027,12 @@ void cli_bytecode_describe(const struct cli_bc *bc)
else
puts("all PRECLASS files!");
break;
case BC_ELF_UNPACKER:
if (bc->lsig)
puts("ELF files matching logical signature (unpacked)");
else
puts("all ELF files! (unpacked)");
break;
default:
puts("N/A (unknown type)\n");
break;

View file

@ -70,6 +70,8 @@ enum BytecodeKind {
/** specifies a PRECLASS hook, executes at the end of file property collection and
* operates on the original file targeted for property collection */
BC_PRECLASS,
/** specifies an ELF unpacker, executed on ELF files on a logical trigger */
BC_ELF_UNPACKER,
_BC_LAST_HOOK
};

View file

@ -42,11 +42,21 @@
#include "clamav.h"
#include "execs.h"
#include "matcher.h"
#include "scanners.h"
#define EC16(v, conv) (conv ? cbswap16(v) : v)
#define EC32(v, conv) (conv ? cbswap32(v) : v)
#define EC64(v, conv) (conv ? cbswap64(v) : v)
#define CLI_TMPUNLK() \
if (!ctx->engine->keeptmp) { \
if (cli_unlink(tempfile)) { \
free(tempfile); \
return CL_EUNLINK; \
} \
}
static void cli_elf_sectionlog(uint32_t sh_type, uint32_t sh_flags);
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)
return 0;
}
/*
* ELF file unpacking.
*/
int cli_unpackelf(cli_ctx *ctx)
{
char *tempfile;
int ndesc;
struct cli_bc_ctx *bc_ctx;
int ret;
fmap_t *map = *ctx->fmap;
/* Bytecode BC_ELF_UNPACKER hook */
bc_ctx = cli_bytecode_context_alloc();
if (!bc_ctx) {
cli_errmsg("cli_scanelf: can't allocate memory for bc_ctx\n");
return CL_EMEM;
}
cli_bytecode_context_setctx(bc_ctx, ctx);
cli_dbgmsg("Running bytecode hook\n");
ret = cli_bytecode_runhook(ctx, ctx->engine, bc_ctx, BC_ELF_UNPACKER, map);
cli_dbgmsg("Finished running bytecode hook\n");
switch (ret) {
case CL_VIRUS:
cli_bytecode_context_destroy(bc_ctx);
return CL_VIRUS;
case CL_SUCCESS:
ndesc = cli_bytecode_context_getresult_file(bc_ctx, &tempfile);
cli_bytecode_context_destroy(bc_ctx);
if (ndesc != -1 && tempfile) {
if (ctx->engine->keeptmp)
cli_dbgmsg("cli_scanelf: Unpacked and rebuilt executable saved in %s\n", tempfile);
else
cli_dbgmsg("cli_scanelf: Unpacked and rebuilt executable\n");
lseek(ndesc, 0, SEEK_SET);
cli_dbgmsg("***** Scanning rebuilt ELF file *****\n");
if (cli_magic_scandesc(ndesc, tempfile, ctx) == CL_VIRUS) {
close(ndesc);
CLI_TMPUNLK();
free(tempfile);
return CL_VIRUS;
}
close(ndesc);
CLI_TMPUNLK();
free(tempfile);
return CL_CLEAN;
}
break;
default:
cli_bytecode_context_destroy(bc_ctx);
}
return CL_CLEAN;
}

View file

@ -147,4 +147,6 @@ int cli_scanelf(cli_ctx *ctx);
int cli_elfheader(fmap_t *map, struct cli_exe_info *elfinfo);
int cli_unpackelf(cli_ctx *ctx);
#endif

View file

@ -119,6 +119,7 @@ enum perfev {
PERFT_BYTECODE,
PERFT_KTIME,
PERFT_UTIME,
PERFT_ELF,
PERFT_LAST
};

View file

@ -3520,6 +3520,11 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type)
}
perf_nested_stop(ctx, PERFT_PE, PERFT_SCAN);
break;
case CL_TYPE_ELF:
perf_nested_start(ctx, PERFT_ELF, PERFT_SCAN);
ret = cli_unpackelf(ctx);
perf_nested_stop(ctx, PERFT_ELF, PERFT_SCAN);
break;
case CL_TYPE_BINARY_DATA:
ret = cli_fmap_scandesc(ctx, CL_TYPE_OTHER, 0, NULL, AC_SCAN_VIR, NULL, NULL);
break;