... | ... |
@@ -2986,6 +2986,9 @@ void cli_bytecode_describe(const struct cli_bc *bc) |
2986 | 2986 |
case BC_ELF_UNPACKER: |
2987 | 2987 |
puts("ELF unpacker hook"); |
2988 | 2988 |
break; |
2989 |
+ case BC_MACHO_UNPACKER: |
|
2990 |
+ puts("Mach-O unpacker hook"); |
|
2991 |
+ break; |
|
2989 | 2992 |
default: |
2990 | 2993 |
printf("Unknown (type %u)", bc->kind); |
2991 | 2994 |
break; |
... | ... |
@@ -3033,6 +3036,12 @@ void cli_bytecode_describe(const struct cli_bc *bc) |
3033 | 3033 |
else |
3034 | 3034 |
puts("all ELF files! (unpacked)"); |
3035 | 3035 |
break; |
3036 |
+ case BC_MACHO_UNPACKER: |
|
3037 |
+ if (bc->lsig) |
|
3038 |
+ puts("Mach-O files matching logical signature (unpacked)"); |
|
3039 |
+ else |
|
3040 |
+ puts("all Mach-O files! (unpacked)"); |
|
3041 |
+ break; |
|
3036 | 3042 |
default: |
3037 | 3043 |
puts("N/A (unknown type)\n"); |
3038 | 3044 |
break; |
... | ... |
@@ -72,6 +72,8 @@ enum BytecodeKind { |
72 | 72 |
BC_PRECLASS, |
73 | 73 |
/** specifies an ELF unpacker, executed on ELF files on a logical trigger */ |
74 | 74 |
BC_ELF_UNPACKER, |
75 |
+ /** specifies an Mach-O unpacker, executed on Mach-O files on a logical trigger */ |
|
76 |
+ BC_MACHO_UNPACKER, |
|
75 | 77 |
_BC_LAST_HOOK |
76 | 78 |
}; |
77 | 79 |
|
... | ... |
@@ -35,6 +35,14 @@ |
35 | 35 |
#include "execs.h" |
36 | 36 |
#include "scanners.h" |
37 | 37 |
|
38 |
+#define CLI_TMPUNLK() \ |
|
39 |
+ if (!ctx->engine->keeptmp) { \ |
|
40 |
+ if (cli_unlink(tempfile)) { \ |
|
41 |
+ free(tempfile); \ |
|
42 |
+ return CL_EUNLINK; \ |
|
43 |
+ } \ |
|
44 |
+ } |
|
45 |
+ |
|
38 | 46 |
#define EC32(v, conv) (conv ? cbswap32(v) : v) |
39 | 47 |
#define EC64(v, conv) (conv ? cbswap64(v) : v) |
40 | 48 |
|
... | ... |
@@ -556,3 +564,55 @@ int cli_scanmacho_unibin(cli_ctx *ctx) |
556 | 556 |
|
557 | 557 |
return ret; /* result from the last binary */ |
558 | 558 |
} |
559 |
+ |
|
560 |
+int cli_unpackmacho(cli_ctx *ctx) |
|
561 |
+{ |
|
562 |
+ char *tempfile; |
|
563 |
+ int ndesc; |
|
564 |
+ struct cli_bc_ctx *bc_ctx; |
|
565 |
+ int ret; |
|
566 |
+ fmap_t *map = *ctx->fmap; |
|
567 |
+ |
|
568 |
+ /* Bytecode BC_MACHO_UNPACKER hook */ |
|
569 |
+ bc_ctx = cli_bytecode_context_alloc(); |
|
570 |
+ if (!bc_ctx) { |
|
571 |
+ cli_errmsg("cli_scanelf: can't allocate memory for bc_ctx\n"); |
|
572 |
+ return CL_EMEM; |
|
573 |
+ } |
|
574 |
+ |
|
575 |
+ cli_bytecode_context_setctx(bc_ctx, ctx); |
|
576 |
+ |
|
577 |
+ ret = cli_bytecode_runhook(ctx, ctx->engine, bc_ctx, BC_MACHO_UNPACKER, map); |
|
578 |
+ switch (ret) { |
|
579 |
+ case CL_VIRUS: |
|
580 |
+ cli_bytecode_context_destroy(bc_ctx); |
|
581 |
+ return CL_VIRUS; |
|
582 |
+ case CL_SUCCESS: |
|
583 |
+ ndesc = cli_bytecode_context_getresult_file(bc_ctx, &tempfile); |
|
584 |
+ cli_bytecode_context_destroy(bc_ctx); |
|
585 |
+ if (ndesc != -1 && tempfile) { |
|
586 |
+ if (ctx->engine->keeptmp) |
|
587 |
+ cli_dbgmsg("cli_scanmacho: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
588 |
+ else |
|
589 |
+ cli_dbgmsg("cli_scanmacho: Unpacked and rebuilt executable\n"); |
|
590 |
+ lseek(ndesc, 0, SEEK_SET); |
|
591 |
+ cli_dbgmsg("***** Scanning rebuilt Mach-O file *****\n"); |
|
592 |
+ if (cli_magic_scandesc(ndesc, tempfile, ctx) == CL_VIRUS) { |
|
593 |
+ close(ndesc); |
|
594 |
+ CLI_TMPUNLK(); |
|
595 |
+ free(tempfile); |
|
596 |
+ return CL_VIRUS; |
|
597 |
+ } |
|
598 |
+ close(ndesc); |
|
599 |
+ CLI_TMPUNLK(); |
|
600 |
+ free(tempfile); |
|
601 |
+ return CL_SUCCESS; |
|
602 |
+ } |
|
603 |
+ break; |
|
604 |
+ default: |
|
605 |
+ cli_bytecode_context_destroy(bc_ctx); |
|
606 |
+ } |
|
607 |
+ |
|
608 |
+ return CL_CLEAN; |
|
609 |
+} |
|
610 |
+ |
... | ... |
@@ -3525,6 +3525,12 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
3525 | 3525 |
ret = cli_unpackelf(ctx); |
3526 | 3526 |
perf_nested_stop(ctx, PERFT_ELF, PERFT_SCAN); |
3527 | 3527 |
break; |
3528 |
+ case CL_TYPE_MACHO: |
|
3529 |
+ case CL_TYPE_MACHO_UNIBIN: |
|
3530 |
+ perf_nested_start(ctx, PERFT_MACHO, PERFT_SCAN); |
|
3531 |
+ ret = cli_unpackmacho(ctx); |
|
3532 |
+ perf_nested_stop(ctx, PERFT_MACHO, PERFT_SCAN); |
|
3533 |
+ break; |
|
3528 | 3534 |
case CL_TYPE_BINARY_DATA: |
3529 | 3535 |
ret = cli_fmap_scandesc(ctx, CL_TYPE_OTHER, 0, NULL, AC_SCAN_VIR, NULL, NULL); |
3530 | 3536 |
break; |