Mach-O bytecode unpackers

This commit is contained in:
Jonas Zaddach
2019-04-17 20:30:21 +02:00
committed by Micah Snyder
parent 2b776e4b89
commit c84683f2f4
6 changed files with 79 additions and 0 deletions

View File

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

View File

@@ -72,6 +72,8 @@ enum BytecodeKind {
BC_PRECLASS,
/** specifies an ELF unpacker, executed on ELF files on a logical trigger */
BC_ELF_UNPACKER,
/** specifies an Mach-O unpacker, executed on Mach-O files on a logical trigger */
BC_MACHO_UNPACKER,
_BC_LAST_HOOK
};

View File

@@ -120,6 +120,7 @@ enum perfev {
PERFT_KTIME,
PERFT_UTIME,
PERFT_ELF,
PERFT_MACHO,
PERFT_LAST
};

View File

@@ -35,6 +35,14 @@
#include "execs.h"
#include "scanners.h"
#define CLI_TMPUNLK() \
if (!ctx->engine->keeptmp) { \
if (cli_unlink(tempfile)) { \
free(tempfile); \
return CL_EUNLINK; \
} \
}
#define EC32(v, conv) (conv ? cbswap32(v) : v)
#define EC64(v, conv) (conv ? cbswap64(v) : v)
@@ -556,3 +564,55 @@ int cli_scanmacho_unibin(cli_ctx *ctx)
return ret; /* result from the last binary */
}
int cli_unpackmacho(cli_ctx *ctx)
{
char *tempfile;
int ndesc;
struct cli_bc_ctx *bc_ctx;
int ret;
fmap_t *map = *ctx->fmap;
/* Bytecode BC_MACHO_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);
ret = cli_bytecode_runhook(ctx, ctx->engine, bc_ctx, BC_MACHO_UNPACKER, map);
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_scanmacho: Unpacked and rebuilt executable saved in %s\n", tempfile);
else
cli_dbgmsg("cli_scanmacho: Unpacked and rebuilt executable\n");
lseek(ndesc, 0, SEEK_SET);
cli_dbgmsg("***** Scanning rebuilt Mach-O 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_SUCCESS;
}
break;
default:
cli_bytecode_context_destroy(bc_ctx);
}
return CL_CLEAN;
}

View File

@@ -29,5 +29,6 @@
int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo);
int cli_machoheader(fmap_t *map, struct cli_exe_info *fileinfo);
int cli_scanmacho_unibin(cli_ctx *ctx);
int cli_unpackmacho(cli_ctx *ctx);
#endif

View File

@@ -3525,6 +3525,12 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type)
ret = cli_unpackelf(ctx);
perf_nested_stop(ctx, PERFT_ELF, PERFT_SCAN);
break;
case CL_TYPE_MACHO:
case CL_TYPE_MACHO_UNIBIN:
perf_nested_start(ctx, PERFT_MACHO, PERFT_SCAN);
ret = cli_unpackmacho(ctx);
perf_nested_stop(ctx, PERFT_MACHO, PERFT_SCAN);
break;
case CL_TYPE_BINARY_DATA:
ret = cli_fmap_scandesc(ctx, CL_TYPE_OTHER, 0, NULL, AC_SCAN_VIR, NULL, NULL);
break;