From f1599f64ec1acd580b83b068e493d49155499377 Mon Sep 17 00:00:00 2001 From: Terence Tan Date: Sun, 14 Jun 2015 09:09:35 +0800 Subject: [PATCH] Added support for 64bit architectures --- main.m | 154 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 130 insertions(+), 24 deletions(-) diff --git a/main.m b/main.m index cf3c47a..c97ed4c 100644 --- a/main.m +++ b/main.m @@ -1,8 +1,8 @@ -/* +/* yololib Inject dylibs into existing Mach-O binaries - - + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE Version 2, December 2004 @@ -17,7 +17,7 @@ 0. You just DO WHAT THE FUCK YOU WANT TO. -*/ + */ #include #include @@ -25,6 +25,8 @@ #include #import +#define CPU_TYPE_ARM64 16777228 + NSString* DYLIB_PATH; //#define DYLIB_PATH "@executable_path/crack.dylib" @@ -36,6 +38,16 @@ #define ARMV7 9 #define ARMV6 6 +unsigned long b_round( + unsigned long v, + unsigned long r) +{ + r--; + v += r; + v &= ~(long)r; + return(v); +} + void inject_dylib(FILE* newFile, uint32_t top) { fseek(newFile, top, SEEK_SET); struct mach_header mach; @@ -53,14 +65,14 @@ void inject_dylib(FILE* newFile, uint32_t top) { fseek(newFile, -sizeof(struct mach_header), SEEK_CUR); fwrite(&mach, sizeof(struct mach_header), 1, newFile); - printf("Patching mach_header..\n"); + NSLog(@"Patching mach_header..\n"); fseek(newFile, sizeofcmds, SEEK_CUR); struct dylib_command dyld; fread(&dyld, sizeof(struct dylib_command), 1, newFile); - printf("Attaching dylib..\n\n"); + NSLog(@"Attaching dylib..\n\n"); dyld.cmd = LC_LOAD_DYLIB; dyld.cmdsize = dylib_size; @@ -75,13 +87,73 @@ void inject_dylib(FILE* newFile, uint32_t top) { fwrite([data bytes], [data length], 1, newFile); } -int main(int argc, const char * argv[]) + +void inject_dylib_64(FILE* newFile, uint32_t top) { + @autoreleasepool { + fseek(newFile, top, SEEK_SET); + struct mach_header_64 mach; + + + fread(&mach, sizeof(struct mach_header_64), 1, newFile); + + NSData* data = [DYLIB_PATH dataUsingEncoding:NSUTF8StringEncoding]; + + + unsigned long dylib_size = sizeof(struct dylib_command) + b_round(strlen([DYLIB_PATH UTF8String]) + 1, 8); + + + //round(strlen([DYLIB_PATH UTF8String]) + 1, sizeof(long)); + NSLog(@"dylib size wow %lu", dylib_size); + /*uint32_t dylib_size2 = (uint32_t)[data length] + sizeof(struct dylib_command); + dylib_size2 += sizeof(long) - (dylib_size % sizeof(long)); // load commands like to be aligned by long + + NSLog(@"dylib size2 wow %u", dylib_size2); + NSLog(@"dylib size2 wow %u", swap32(dylib_size2));*/ + + NSLog(@"mach.ncmds %u", mach.ncmds); + + mach.ncmds += 0x1; + + NSLog(@"mach.ncmds %u", mach.ncmds); + + uint32_t sizeofcmds = mach.sizeofcmds; + mach.sizeofcmds += (dylib_size); + + fseek(newFile, -sizeof(struct mach_header_64), SEEK_CUR); + fwrite(&mach, sizeof(struct mach_header_64), 1, newFile); + NSLog(@"Patching mach_header..\n"); + + fseek(newFile, sizeofcmds, SEEK_CUR); + + struct dylib_command dyld; + fread(&dyld, sizeof(struct dylib_command), 1, newFile); + + NSLog(@"Attaching dylib..\n\n"); + + dyld.cmd = LC_LOAD_DYLIB; + dyld.cmdsize = (uint32_t) dylib_size; + dyld.dylib.compatibility_version = DYLIB_COMPATIBILITY_VERSION; + dyld.dylib.current_version = DYLIB_CURRENT_VER; + dyld.dylib.timestamp = 2; + dyld.dylib.name.offset = sizeof(struct dylib_command); + fseek(newFile, -sizeof(struct dylib_command), SEEK_CUR); + + fwrite(&dyld, sizeof(struct dylib_command), 1, newFile); + + fwrite([data bytes], [data length], 1, newFile); + NSLog(@"size %lu", sizeof(struct dylib_command) + [data length]); + } +} + + +void inject_file(NSString* file, NSString* _dylib) { char buffer[4096], binary[4096], dylib[4096]; - strlcpy(binary, argv[1], sizeof(binary)); - strlcpy(dylib, argv[2], sizeof(dylib)); - DYLIB_PATH = [NSString stringWithFormat:@"@executable_path/%@", [NSString stringWithUTF8String:dylib]]; + + strlcpy(binary, [file UTF8String], sizeof(binary)); + strlcpy(dylib, [DYLIB_PATH UTF8String], sizeof(dylib)); + NSLog(@"dylib path %@", DYLIB_PATH); FILE *binaryFile = fopen(binary, "r+"); printf("Reading binary: %s\n\n", binary); @@ -89,22 +161,56 @@ int main(int argc, const char * argv[]) struct fat_header* fh = (struct fat_header*) (buffer); - - if (fh->magic == FAT_CIGAM) { - struct fat_arch* arch = (struct fat_arch*) &fh[1]; - printf("FAT binary!\n"); - int i; - for (i = 0; i < swap32(fh->nfat_arch); i++) { - printf("Injecting to arch %i\n", swap32(arch->cpusubtype)); - inject_dylib(binaryFile, swap32(arch->offset)); - arch++; + switch (fh->magic) { + case FAT_CIGAM: + case FAT_MAGIC: + { + struct fat_arch* arch = (struct fat_arch*) &fh[1]; + NSLog(@"FAT binary!\n"); + int i; + for (i = 0; i < swap32(fh->nfat_arch); i++) { + NSLog(@"Injecting to arch %i\n", swap32(arch->cpusubtype)); + if (CFSwapInt32(arch->cputype) == CPU_TYPE_ARM64) { + NSLog(@"64bit arch wow"); + inject_dylib_64(binaryFile, swap32(arch->offset)); + } + else { + inject_dylib(binaryFile, swap32(arch->offset)); + } + arch++; + } + break; + } + case MH_CIGAM_64: + case MH_MAGIC_64: + { + NSLog(@"Thin 64bit binary!\n"); + inject_dylib_64(binaryFile, 0); + break; + } + default: + { + NSLog(@"Thin 32bit binary!\n"); + inject_dylib_64(binaryFile, 0); + break; } } - else { - printf("Thin binary!\n"); - inject_dylib(binaryFile, 0); - } - printf("Complete!\n"); + + NSLog(@"complete!"); + fclose(binaryFile); +} + +int main(int argc, const char * argv[]) +{ + char buffer[4096], binary[4096], dylib[4096]; + + strlcpy(binary, argv[1], sizeof(binary)); + strlcpy(dylib, argv[2], sizeof(dylib)); + DYLIB_PATH = [NSString stringWithFormat:@"@executable_path/%@", [NSString stringWithUTF8String:dylib]]; + NSLog(@"dylib path %@", DYLIB_PATH); + + inject_file([NSString stringWithUTF8String:binary], DYLIB_PATH); + return 0; }