mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2025-10-19 18:33:16 +00:00
Linux bytecode unpackers
This commit is contained in:
parent
ddc1c9bb11
commit
2b776e4b89
6 changed files with 86 additions and 0 deletions
|
@ -2983,6 +2983,9 @@ void cli_bytecode_describe(const struct cli_bc *bc)
|
||||||
case BC_PRECLASS:
|
case BC_PRECLASS:
|
||||||
puts("preclass hook");
|
puts("preclass hook");
|
||||||
break;
|
break;
|
||||||
|
case BC_ELF_UNPACKER:
|
||||||
|
puts("ELF unpacker hook");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Unknown (type %u)", bc->kind);
|
printf("Unknown (type %u)", bc->kind);
|
||||||
break;
|
break;
|
||||||
|
@ -3024,6 +3027,12 @@ void cli_bytecode_describe(const struct cli_bc *bc)
|
||||||
else
|
else
|
||||||
puts("all PRECLASS files!");
|
puts("all PRECLASS files!");
|
||||||
break;
|
break;
|
||||||
|
case BC_ELF_UNPACKER:
|
||||||
|
if (bc->lsig)
|
||||||
|
puts("ELF files matching logical signature (unpacked)");
|
||||||
|
else
|
||||||
|
puts("all ELF files! (unpacked)");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
puts("N/A (unknown type)\n");
|
puts("N/A (unknown type)\n");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -70,6 +70,8 @@ enum BytecodeKind {
|
||||||
/** specifies a PRECLASS hook, executes at the end of file property collection and
|
/** specifies a PRECLASS hook, executes at the end of file property collection and
|
||||||
* operates on the original file targeted for property collection */
|
* operates on the original file targeted for property collection */
|
||||||
BC_PRECLASS,
|
BC_PRECLASS,
|
||||||
|
/** specifies an ELF unpacker, executed on ELF files on a logical trigger */
|
||||||
|
BC_ELF_UNPACKER,
|
||||||
_BC_LAST_HOOK
|
_BC_LAST_HOOK
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -42,11 +42,21 @@
|
||||||
#include "clamav.h"
|
#include "clamav.h"
|
||||||
#include "execs.h"
|
#include "execs.h"
|
||||||
#include "matcher.h"
|
#include "matcher.h"
|
||||||
|
#include "scanners.h"
|
||||||
|
|
||||||
#define EC16(v, conv) (conv ? cbswap16(v) : v)
|
#define EC16(v, conv) (conv ? cbswap16(v) : v)
|
||||||
#define EC32(v, conv) (conv ? cbswap32(v) : v)
|
#define EC32(v, conv) (conv ? cbswap32(v) : v)
|
||||||
#define EC64(v, conv) (conv ? cbswap64(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 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)
|
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;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,4 +147,6 @@ int cli_scanelf(cli_ctx *ctx);
|
||||||
|
|
||||||
int cli_elfheader(fmap_t *map, struct cli_exe_info *elfinfo);
|
int cli_elfheader(fmap_t *map, struct cli_exe_info *elfinfo);
|
||||||
|
|
||||||
|
int cli_unpackelf(cli_ctx *ctx);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -119,6 +119,7 @@ enum perfev {
|
||||||
PERFT_BYTECODE,
|
PERFT_BYTECODE,
|
||||||
PERFT_KTIME,
|
PERFT_KTIME,
|
||||||
PERFT_UTIME,
|
PERFT_UTIME,
|
||||||
|
PERFT_ELF,
|
||||||
PERFT_LAST
|
PERFT_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3520,6 +3520,11 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type)
|
||||||
}
|
}
|
||||||
perf_nested_stop(ctx, PERFT_PE, PERFT_SCAN);
|
perf_nested_stop(ctx, PERFT_PE, PERFT_SCAN);
|
||||||
break;
|
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:
|
case CL_TYPE_BINARY_DATA:
|
||||||
ret = cli_fmap_scandesc(ctx, CL_TYPE_OTHER, 0, NULL, AC_SCAN_VIR, NULL, NULL);
|
ret = cli_fmap_scandesc(ctx, CL_TYPE_OTHER, 0, NULL, AC_SCAN_VIR, NULL, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue