diff --git a/Clutch/ARM64Dumper.m b/Clutch/ARM64Dumper.m index 1fddf83a..106231df 100644 --- a/Clutch/ARM64Dumper.m +++ b/Clutch/ARM64Dumper.m @@ -116,7 +116,6 @@ - (BOOL)dumpBinary { if ((err = task_for_pid(mach_task_self(), pid, &port) != KERN_SUCCESS)) { ERROR(@"Could not obtain mach port, did you sign with proper entitlements?"); - sleep(60); goto gotofail; } diff --git a/Clutch/ARMDumper.m b/Clutch/ARMDumper.m index e6206fb9..65ca37b3 100644 --- a/Clutch/ARMDumper.m +++ b/Clutch/ARMDumper.m @@ -102,9 +102,11 @@ - (BOOL)dumpBinary { break; } + NSLog(@"binary path %@", swappedBinaryPath); + // we need to have all of these if (!foundCrypt || !foundSignature || !foundStartText) { - DumperDebugLog(@"dumping binary: some load commands were not found %@ %@ %@",foundCrypt?@"YES":@"NO",foundSignature?@"YES":@"NO",foundStartText?@"YES":@"NO"); + ERROR(@"dumping binary: some load commands were not found %@ %@ %@",foundCrypt?@"YES":@"NO",foundSignature?@"YES":@"NO",foundStartText?@"YES":@"NO"); return NO; } diff --git a/Clutch/ApplicationsManager.m b/Clutch/ApplicationsManager.m index 5749dfc4..6c8a6b83 100644 --- a/Clutch/ApplicationsManager.m +++ b/Clutch/ApplicationsManager.m @@ -6,7 +6,7 @@ // // -#define applistCachePath @"/tmp/applist-cache.clutch" +#define applistCachePath @"applist-cache.plist" #define dumpedAppPath @"/etc/dumped.clutch" #import @@ -129,12 +129,17 @@ - (NSDictionary *)_allApplications Application *app =[[Application alloc]initWithBundleInfo:bundleInfo]; returnValue[proxy.bundleIdentifier] = app; [self cacheBundle:bundleInfo]; + } } } } - [_cachedApps writeToFile:applistCachePath atomically:YES]; + dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0); + dispatch_async(queue, ^{ + [_cachedApps writeToFile:applistCachePath atomically:YES]; + }); + return [returnValue copy]; } diff --git a/Clutch/Clutch-Prefix.pch b/Clutch/Clutch-Prefix.pch index f62796ff..52ce78e9 100644 --- a/Clutch/Clutch-Prefix.pch +++ b/Clutch/Clutch-Prefix.pch @@ -23,7 +23,7 @@ #define CLUTCH_VERSION @"2.0 RC3" -# define SUCCESS(M, ...) fprintf(stderr, "\033[0;31mDONE\033[0m: %s\n",[[NSString stringWithFormat:M, ##__VA_ARGS__] UTF8String]); +# define SUCCESS(M, ...) fprintf(stderr, "\033[1;31mDONE\033[0m: %s\n",[[NSString stringWithFormat:M, ##__VA_ARGS__] UTF8String]); #ifdef DEBUG # define FILE_NAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) // shortened path of __FILE__ is there is one diff --git a/Clutch/ClutchBundle.m b/Clutch/ClutchBundle.m index 6e31f4b7..3ac43aa0 100644 --- a/Clutch/ClutchBundle.m +++ b/Clutch/ClutchBundle.m @@ -42,7 +42,7 @@ - (void)prepareForDump { thin_header _thinHeader = headers[i]; NSString *rpath = self.parentBundle ? [self.parentBundle.bundlePath stringByAppendingPathComponent:@"Frameworks"] : [self.bundlePath stringByAppendingPathComponent:@"Frameworks"] ; - + NSLog(@"checking rpath for %@", self.executable.binaryPath); insertRPATHIntoBinary(rpath, data, _thinHeader); } diff --git a/Clutch/Dumper.m b/Clutch/Dumper.m index 7eb4167a..ca307328 100644 --- a/Clutch/Dumper.m +++ b/Clutch/Dumper.m @@ -108,7 +108,7 @@ - (pid_t)posix_spawn:(NSString *)binaryPath disableASLR:(BOOL)yrn suspend:(BOOL) posix_spawnattr_destroy (&attr); - NSLog(@"got the pid %u %@", pid, binaryPath);l + NSLog(@"got the pid %u %@", pid, binaryPath); return pid; } @@ -123,7 +123,7 @@ - (BOOL)dumpBinary return NO; } -- (void)swapArch +/*- (void)swapArch { thin_header macho = _thinHeader; @@ -167,8 +167,11 @@ - (void)swapArch struct fat_arch keep_arch; char data[20]; + NSLog(@"sizeof struct fat_arch %lu", sizeof(struct fat_arch)); memset(data,'\0',sizeof(data)); + struct fat_arch fat_arches[20]; //don't think an app can have more than 20 + for (int i = 0; i < fat.nfat_arch; i++) { struct fat_arch arch; arch = *(struct fat_arch *)([buffer bytes] + offset); @@ -194,6 +197,98 @@ - (void)swapArch DumperLog(@"wrote new header to binary!"); +}*/ + + +-(void)swapArch { + + thin_header macho = _thinHeader; + + DumperLog(@"swapping archs"); + + //time to swap + NSString* suffix = [NSString stringWithFormat:@"_%@", [Dumper readableArchFromHeader:_thinHeader]]; + + NSString *swappedBinaryPath = [_originalBinary.binaryPath stringByAppendingString:suffix]; + NSString *newSinf = [_originalBinary.sinfPath.stringByDeletingPathExtension stringByAppendingString:[suffix stringByAppendingPathExtension:_originalBinary.sinfPath.pathExtension]]; + NSString *newSupp = [_originalBinary.suppPath.stringByDeletingPathExtension stringByAppendingString:[suffix stringByAppendingPathExtension:_originalBinary.suppPath.pathExtension]]; + + NSString *newSupf; + if ([[NSFileManager defaultManager] fileExistsAtPath:_originalBinary.supfPath]) { + newSupf = [_originalBinary.supfPath.stringByDeletingPathExtension stringByAppendingString:[suffix stringByAppendingPathExtension:_originalBinary.supfPath.pathExtension]]; + } + + [[NSFileManager defaultManager] copyItemAtPath:_originalBinary.binaryPath toPath:swappedBinaryPath error:nil]; + [[NSFileManager defaultManager] copyItemAtPath:_originalBinary.sinfPath toPath:newSinf error:nil]; + + [[NSFileManager defaultManager] copyItemAtPath:_originalBinary.suppPath toPath:newSupp error:nil]; + + if (newSupf) { + [[NSFileManager defaultManager] copyItemAtPath:_originalBinary.supfPath toPath:newSupf error:nil]; + } + + [self.originalFileHandle closeFile]; + self.originalFileHandle = [[NSFileHandle alloc]initWithFileDescriptor:fileno(fopen(swappedBinaryPath.UTF8String, "r+"))]; + + uint32_t magic = [self.originalFileHandle intAtOffset:0]; + bool shouldSwap = magic == FAT_CIGAM; +#define SWAP(NUM) (shouldSwap ? CFSwapInt32(NUM) : NUM) + + NSData *buffer = [self.originalFileHandle readDataOfLength:4096]; + + struct fat_header fat = *(struct fat_header *)buffer.bytes; + fat.nfat_arch = SWAP(fat.nfat_arch); + int offset = sizeof(struct fat_header); + + for (int i = 0; i < fat.nfat_arch; i++) { + struct fat_arch arch; + arch = *(struct fat_arch *)([buffer bytes] + offset); + + if (!((SWAP(arch.cputype) == _thinHeader.header.cputype) && (SWAP(arch.cpusubtype) == _thinHeader.header.cpusubtype))) { + + if (SWAP(arch.cputype) == CPU_TYPE_ARM) { + switch (SWAP(arch.cpusubtype)) { + case CPU_SUBTYPE_ARM_V6: + arch.cputype = SWAP(CPU_TYPE_I386); + arch.cpusubtype = SWAP(CPU_SUBTYPE_PENTIUM_3_XEON); + break; + case CPU_SUBTYPE_ARM_V7: + arch.cputype = SWAP(CPU_TYPE_I386); + arch.cpusubtype = SWAP(CPU_SUBTYPE_PENTIUM_4); + break; + case CPU_SUBTYPE_ARM_V7S: + arch.cputype = SWAP(CPU_TYPE_I386); + arch.cpusubtype = SWAP(CPU_SUBTYPE_ITANIUM); + break; + case CPU_SUBTYPE_ARM_V7K: // Apple Watch FTW + arch.cputype = SWAP(CPU_TYPE_I386); + arch.cpusubtype = SWAP(CPU_SUBTYPE_XEON); + break; + } + } else { + + switch (SWAP(arch.cpusubtype)) { + case CPU_SUBTYPE_ARM64_ALL: + arch.cputype = SWAP(CPU_TYPE_X86_64); + arch.cpusubtype = SWAP(CPU_SUBTYPE_X86_64_ALL); + break; + case CPU_SUBTYPE_ARM64_V8: + arch.cputype = SWAP(CPU_TYPE_X86_64); + arch.cpusubtype = SWAP(CPU_SUBTYPE_X86_64_H); + break; + } + + } + + [self.originalFileHandle replaceBytesInRange:NSMakeRange(offset, sizeof(struct fat_arch)) withBytes:&arch]; + } + + offset += sizeof(struct fat_arch); + } + + + DumperLog(@"wrote new header to binary"); + } - (BOOL)_dumpToFileHandle:(NSFileHandle *)fileHandle withEncryptionInfoCommand:(uint32_t)togo pages:(uint32_t)pages fromPort:(mach_port_t)port pid:(pid_t)pid aslrSlide:(mach_vm_address_t)__text_start diff --git a/Clutch/FinalizeDumpOperation.m b/Clutch/FinalizeDumpOperation.m index 3a950254..4192f7bc 100644 --- a/Clutch/FinalizeDumpOperation.m +++ b/Clutch/FinalizeDumpOperation.m @@ -56,8 +56,11 @@ - (void)start { } self.completionBlock = ^{ - exit(0); - CFRunLoopStop(CFRunLoopGetCurrent()); + dispatch_async(dispatch_get_main_queue(), ^{ + NSLog(@"ending the thread bye bye"); + CFRunLoopStop(CFRunLoopGetCurrent()); + }); + }; // If the operation is not canceled, begin executing the task. diff --git a/Clutch/main.m b/Clutch/main.m index f64949f6..1258d27b 100644 --- a/Clutch/main.m +++ b/Clutch/main.m @@ -195,7 +195,7 @@ int main (int argc, const char * argv[]) gettimeofday(&end, NULL); int dif = diff_ms(end,start); float sec = ((dif + 500.0f) / 1000.0f); - gbprintln(@"Finished dumping %@ in %u s", _selectedApp.bundleIdentifier, sec); + gbprintln(@"Finished dumping %@ in %f s", _selectedApp.bundleIdentifier, sec); diff --git a/Clutch/optool-operations.m b/Clutch/optool-operations.m index ee9a9ec3..03f36755 100755 --- a/Clutch/optool-operations.m +++ b/Clutch/optool-operations.m @@ -244,6 +244,7 @@ BOOL binaryHasRPATH(NSMutableData *binary, NSString *dylib, uint32_t *lastOffset // Loop through compatible LC_LOAD commands until we find one which points // to the given dylib and tell the caller where it is and if it exists + bool foundRPATH = NO; for (int i = 0; i < macho.header.ncmds; i++) { if (binary.currentOffset >= binary.length || binary.currentOffset > macho.offset + macho.size + macho.header.sizeofcmds) @@ -251,6 +252,7 @@ BOOL binaryHasRPATH(NSMutableData *binary, NSString *dylib, uint32_t *lastOffset uint32_t cmd = [binary intAtOffset:binary.currentOffset]; uint32_t size = [binary intAtOffset:binary.currentOffset + 4]; + switch (cmd) { case LC_RPATH: { @@ -264,6 +266,7 @@ BOOL binaryHasRPATH(NSMutableData *binary, NSString *dylib, uint32_t *lastOffset binary.currentOffset += size; loadOffset = (unsigned int)binary.currentOffset; + foundRPATH = YES; break; } default: @@ -274,7 +277,11 @@ BOOL binaryHasRPATH(NSMutableData *binary, NSString *dylib, uint32_t *lastOffset if (lastOffset != NULL) *lastOffset = loadOffset; - + if (!foundRPATH) { + NSLog(@"didn't find rpath, no injection!"); + return YES; + + } return NO; }