Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 40 additions & 39 deletions dumpdecrypted.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,48 +29,49 @@ DISCLAIMER: This tool is only meant for security research purposes, not for appl
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <mach-o/fat.h>
#include <mach-o/loader.h>

struct ProgramVars {
struct mach_header* mh;
int* NXArgcPtr;
const char*** NXArgvPtr;
const char*** environPtr;
const char** __prognamePtr;
};
#include <mach-o/dyld.h>

#define swap32(value) (((value & 0xFF000000) >> 24) | ((value & 0x00FF0000) >> 8) | ((value & 0x0000FF00) << 8) | ((value & 0x000000FF) << 24) )

__attribute__((constructor))
void dumptofile(int argc, const char **argv, const char **envp, const char **apple, struct ProgramVars *pvars)
{
void dumptofile(const char *path, const struct mach_header *mh) {
struct load_command *lc;
struct encryption_info_command *eic;
struct fat_header *fh;
struct fat_arch *arch;
struct mach_header *mh;
char buffer[1024];
char rpath[4096],npath[4096]; /* should be big enough for PATH_MAX */
unsigned int fileoffs = 0, off_cryptid = 0, restsize;
int i,fd,outfd,r,n,toread;
char *tmp;

printf("mach-o decryption dumper\n\n");

printf("DISCLAIMER: This tool is only meant for security research purposes, not for application crackers.\n\n");


if (realpath(path, rpath) == NULL) {
strlcpy(rpath, path, sizeof(rpath));
}

/* extract basename */
tmp = strrchr(rpath, '/');
printf("\n\n");
if (tmp == NULL) {
printf("[-] Unexpected error with filename.\n");
_exit(1);
} else {
printf("[+] Dumping %s\n", tmp+1);
}

/* detect if this is a arm64 binary */
if (pvars->mh->magic == MH_MAGIC_64) {
lc = (struct load_command *)((unsigned char *)pvars->mh + sizeof(struct mach_header_64));
if (mh->magic == MH_MAGIC_64) {
lc = (struct load_command *)((unsigned char *)mh + sizeof(struct mach_header_64));
printf("[+] detected 64bit ARM binary in memory.\n");
} else { /* we might want to check for other errors here, too */
lc = (struct load_command *)((unsigned char *)pvars->mh + sizeof(struct mach_header));
lc = (struct load_command *)((unsigned char *)mh + sizeof(struct mach_header));
printf("[+] detected 32bit ARM binary in memory.\n");
}

/* searching all load commands for an LC_ENCRYPTION_INFO load command */
for (i=0; i<pvars->mh->ncmds; i++) {
for (i=0; i<mh->ncmds; i++) {
/*printf("Load Command (%d): %08x\n", i, lc->cmd);*/

if (lc->cmd == LC_ENCRYPTION_INFO || lc->cmd == LC_ENCRYPTION_INFO_64) {
Expand All @@ -80,15 +81,11 @@ void dumptofile(int argc, const char **argv, const char **envp, const char **app
if (eic->cryptid == 0) {
break;
}
off_cryptid=(off_t)((void*)&eic->cryptid - (void*)pvars->mh);
printf("[+] offset to cryptid found: @%p(from %p) = %x\n", &eic->cryptid, pvars->mh, off_cryptid);
off_cryptid=(off_t)((void*)&eic->cryptid - (void*)mh);
printf("[+] offset to cryptid found: @%p(from %p) = %x\n", &eic->cryptid, mh, off_cryptid);

printf("[+] Found encrypted data at address %08x of length %u bytes - type %u.\n", eic->cryptoff, eic->cryptsize, eic->cryptid);

if (realpath(argv[0], rpath) == NULL) {
strlcpy(rpath, argv[0], sizeof(rpath));
}


printf("[+] Opening %s for reading.\n", rpath);
fd = open(rpath, O_RDONLY);
if (fd == -1) {
Expand All @@ -110,7 +107,7 @@ void dumptofile(int argc, const char **argv, const char **envp, const char **app
printf("[+] Executable is a FAT image - searching for right architecture\n");
arch = (struct fat_arch *)&fh[1];
for (i=0; i<swap32(fh->nfat_arch); i++) {
if ((pvars->mh->cputype == swap32(arch->cputype)) && (pvars->mh->cpusubtype == swap32(arch->cpusubtype))) {
if ((mh->cputype == swap32(arch->cputype)) && (mh->cpusubtype == swap32(arch->cpusubtype))) {
fileoffs = swap32(arch->offset);
printf("[+] Correct arch is at offset %u in the file\n", fileoffs);
break;
Expand All @@ -128,12 +125,6 @@ void dumptofile(int argc, const char **argv, const char **envp, const char **app
_exit(1);
}

/* extract basename */
tmp = strrchr(rpath, '/');
if (tmp == NULL) {
printf("[-] Unexpected error with filename.\n");
_exit(1);
}
strlcpy(npath, tmp+1, sizeof(npath));
strlcat(npath, ".decrypted", sizeof(npath));
strlcpy(buffer, npath, sizeof(buffer));
Expand Down Expand Up @@ -192,7 +183,7 @@ void dumptofile(int argc, const char **argv, const char **envp, const char **app

/* now write the previously encrypted data */
printf("[+] Dumping the decrypted data into the file\n");
r = write(outfd, (unsigned char *)pvars->mh + eic->cryptoff, eic->cryptsize);
r = write(outfd, (unsigned char *)mh + eic->cryptoff, eic->cryptsize);
if (r != eic->cryptsize) {
printf("[-] Error writing file\n");
_exit(1);
Expand Down Expand Up @@ -231,12 +222,22 @@ void dumptofile(int argc, const char **argv, const char **envp, const char **app
close(fd);
printf("[+] Closing dump file\n");
close(outfd);

_exit(1);
}

lc = (struct load_command *)((unsigned char *)lc+lc->cmdsize);
}
printf("[-] This mach-o file is not encrypted. Nothing was decrypted.\n");
_exit(1);
}

static void image_added(const struct mach_header *mh, intptr_t slide) {
Dl_info image_info;
int result = dladdr(mh, &image_info);
dumptofile(image_info.dli_fname, mh);
}

__attribute__((constructor))
static void dumpexecutable() {
printf("mach-o decryption dumper\n\n");
printf("DISCLAIMER: This tool is only meant for security research purposes, not for application crackers.");
_dyld_register_func_for_add_image(&image_added);
}