Skip to content

Commit

Permalink
Fixes issues with application listing on iOS7, new header stripping m…
Browse files Browse the repository at this point in the history
…echanism
  • Loading branch information
ttwj committed Jun 13, 2015
1 parent 47494cc commit b911ab0
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 83 deletions.
10 changes: 7 additions & 3 deletions Clutch/ApplicationsManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,21 @@ - (NSDictionary *)_allApplications
NSDictionary *appI=installedApps[bundleID];

NSURL *bundleURL = [NSURL fileURLWithPath:appI[@"Path"]];

NSString *scinfo=[bundleURL.path stringByAppendingPathComponent:@"SC_Info"];

BOOL isDirectory;

BOOL purchased = [[NSFileManager defaultManager]fileExistsAtPath:scinfo isDirectory:&isDirectory];

if (purchased && isDirectory) {
NSString* name = appI[@"CFBundleDisplayName"];
if (name == nil) {
name = appI[@"CFBundleExecutable"];
}
NSDictionary* bundleInfo = @{@"BundleContainer":bundleURL.URLByDeletingLastPathComponent,
@"BundleURL":bundleURL,
@"DislayName": appI[@"CFBundleDisplayname"],
@"DisplayName": name,
@"BundleIdentifier": bundleID};
Application *app =[[Application alloc]initWithBundleInfo:bundleInfo];
[self cacheBundle:bundleInfo];
Expand Down
114 changes: 47 additions & 67 deletions Clutch/BundleDumpOperation.m
Original file line number Diff line number Diff line change
Expand Up @@ -133,23 +133,22 @@ - (void)main {
thin_header macho = headers[i];
Dumper<BinaryDumpProtocol> *_dumper = nil;

NSLog(@"Finding compatible dumper for binary %@", originalBinary);
NSLog(@"Finding compatible dumper for binary %@ with arch cputype: %u", originalBinary, macho.header.cputype);
for (Class dumperClass in dumpers) {
_dumper = [[dumperClass alloc]initWithHeader:macho originalBinary:originalBinary];

if ([_dumper compatibilityMode] == ArchCompatibilityNotCompatible) {
//NSLog(@"%@ cannot dump binary %@ (arch %@). Dumper not compatible, finding another dumper \n\n",_dumper,originalBinary,[Dumper readableArchFromHeader:macho]);
//_dumper = nil;
NSLog(@"%@ cannot dump binary %@ (arch %@). Dumper not compatible, finding another dumper",_dumper,originalBinary,[Dumper readableArchFromHeader:macho]);
_dumper = nil;
} else {
break;
}
}

if (_dumper == nil) {
NSLog(@"Couldn't find compatible dumper for binary %@ with arch %@. Will have to \"strip\".",originalBinary,[Dumper readableArchFromHeader:macho]);

NSValue* archValue = [NSValue value:&macho withObjCType:@encode(thin_header)];
[_headersToStrip addObject:archValue];
NSLog(@"offset %u", macho.offset);
[_headersToStrip addObject:[NSNumber numberWithUnsignedInt:macho.offset]];
continue;
}

Expand All @@ -164,7 +163,7 @@ - (void)main {
if (result) {
dumpCount++;
gbprintln(@"Finished dumping binary %@ %@ with result: %i",originalBinary,[Dumper readableArchFromHeader:macho],result);
}else {
} else {
ERROR(@"Failed to dump binary %@ with arch %@",originalBinary,[Dumper readableArchFromHeader:macho]);
}

Expand All @@ -180,74 +179,55 @@ - (void)main {


#pragma mark "stripping" headers in FAT binary
if (isFAT) {
if ([_headersToStrip count] > 0) {
NSFileHandle *_dumpHandle = [[NSFileHandle alloc]initWithFileDescriptor:fileno(fopen(_binaryDumpPath.UTF8String, "r+"))];

NSData *buffer = [_dumpHandle readDataOfLength:4096];

uint32_t magic = [_dumpHandle intAtOffset:0];
bool shouldSwap = magic == FAT_CIGAM;
#define SWAP(NUM) (shouldSwap ? CFSwapInt32(NUM) : NUM)
NSMutableArray* _headersToKeep = [NSMutableArray new];
struct fat_header fat = *(struct fat_header *)buffer.bytes;
fat.nfat_arch = CFSwapInt32(fat.nfat_arch);

NSData *buffer = _dumpHandle.availableData;
//bunch of zeroes
char data[20];
memset(data,'\0',sizeof(data));

struct fat_header fat = *(struct fat_header *)buffer.bytes;
int offset = sizeof(struct fat_header);

for (NSValue *valueWithArch in _headersToStrip) {
thin_header stripArch;
[valueWithArch getValue:&stripArch];
for (int i = 0; i < fat.nfat_arch; i++) {
struct fat_arch arch = *(struct fat_arch *)([buffer bytes] + offset);
NSNumber* archOffset = [NSNumber numberWithUnsignedInt:CFSwapInt32(arch.offset)];
NSLog(@"current offset %u", CFSwapInt32(arch.offset));
if ([_headersToStrip containsObject:archOffset]) {
NSLog(@"arch to strip %u %u", CFSwapInt32(arch.cpusubtype), CFSwapInt32(arch.cputype));
}
else {
NSValue* archValue = [NSValue value:&arch withObjCType:@encode(struct fat_arch)];
[_headersToKeep addObject:archValue];
//NSLog(@"storing the arch we want to keep %u", CFSwapInt32(arch.cpusubtype));
}

for (int i = 0; i < SWAP(fat.nfat_arch); i++) {
struct fat_arch arch;
arch = *(struct fat_arch *)([buffer bytes] + offset);

if (((SWAP(arch.cputype) == stripArch.header.cputype) && (SWAP(arch.cpusubtype) == stripArch.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;
}

}

stripArch.header.cputype = SWAP(arch.cputype);
stripArch.header.cpusubtype = SWAP(arch.cpusubtype);

[_dumpHandle replaceBytesInRange:NSMakeRange(offset, sizeof(struct fat_arch)) withBytes:&arch];
[_dumpHandle replaceBytesInRange:NSMakeRange(stripArch.offset, sizeof(stripArch.header)) withBytes:&stripArch.header];
[_dumpHandle replaceBytesInRange:NSMakeRange(offset, sizeof(struct fat_arch)) withBytes:&data]; //blank all the archs
offset += sizeof(struct fat_arch);
}

//skip 4 bytes for magic, 4 bytes of nfat_arch
uint32_t nfat_arch = CFSwapInt32([_headersToKeep count]);
[_dumpHandle replaceBytesInRange:NSMakeRange(sizeof(uint32_t), sizeof(uint32_t)) withBytes:&nfat_arch];
//NSLog(@"changing nfat_arch to %u %u", nfat_arch, CFSwapInt32(nfat_arch));


offset = sizeof(struct fat_header);

for (NSValue* archValue in _headersToKeep) {
struct fat_arch keepArch;
[archValue getValue:&keepArch];
NSLog(@"headers to keep: %u %u", CFSwapInt32(keepArch.cpusubtype), CFSwapInt32(keepArch.cputype));
[_dumpHandle replaceBytesInRange:NSMakeRange(offset, sizeof(struct fat_arch)) withBytes:&keepArch];
offset += sizeof(struct fat_arch);
}

}

offset += sizeof(struct fat_arch);
}
NSLog(@"wrote new header to binary!");

}

[_dumpHandle closeFile];
}
Expand Down
2 changes: 1 addition & 1 deletion Clutch/Clutch-Prefix.pch
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#import <Foundation/Foundation.h>
#endif

#define CLUTCH_VERSION @"2.0 RC3"
#define CLUTCH_VERSION @"2.0 RC4"

# define SUCCESS(M, ...) fprintf(stderr, "\033[1;31mDONE\033[0m: %s\n",[[NSString stringWithFormat:M, ##__VA_ARGS__] UTF8String]);

Expand Down
22 changes: 13 additions & 9 deletions Clutch/Dumper.m
Original file line number Diff line number Diff line change
Expand Up @@ -386,23 +386,27 @@ - (BOOL)_dumpToFileHandle:(NSFileHandle *)fileHandle withEncryptionInfoCommand:(
return YES;
}

- (ArchCompatibility)compatibilityMode;
{
cpu_type_t cputype = self.supportedCPUType;
cpu_subtype_t cpusubtype = _thinHeader.header.cpusubtype;
- (ArchCompatibility)compatibilityMode {

NSLog(@"segment cputype: %u, cpusubtype: %u", _thinHeader.header.cputype, _thinHeader.header.cpusubtype);
NSLog(@"device cputype: %u, cpusubtype: %u", Device.cpu_type, Device.cpu_subtype);
NSLog(@"dumper supports cputype %u", self.supportedCPUType);

if (self.supportedCPUType != _thinHeader.header.cputype) {
//why cut a potato with a pencil?
NSLog(@"why cut a potato with a pencil?");
return ArchCompatibilityNotCompatible;
}

else if ((Device.cpu_type == CPU_TYPE_ARM64) && (_thinHeader.header.cputype == CPU_TYPE_ARM))
return ArchCompatibilityCompatible; // god mode on

else if ((cputype != _thinHeader.header.cputype) || (cpusubtype > Device.cpu_subtype) || (_thinHeader.header.cputype > Device.cpu_type)) {
else if ((_thinHeader.header.cpusubtype > Device.cpu_subtype) || (_thinHeader.header.cputype > Device.cpu_type)) {
NSLog(@"cannot use dumper %@, device not supported", NSStringFromClass([self class]));
return ArchCompatibilityNotCompatible;
}

else if ((Device.cpu_type == CPU_TYPE_ARM64) && (_thinHeader.header.cputype == CPU_TYPE_ARM)) {
return ArchCompatibilityCompatible; // god mode on
}


return ArchCompatibilityCompatible;

}
Expand Down
1 change: 1 addition & 0 deletions Clutch/FinalizeDumpOperation.m
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ - (void)main {
}
else {
ERROR(@"Failed to dump %@ :(", _application.bundleIdentifier);
exit(1);
}

[self completeOperation];
Expand Down
4 changes: 2 additions & 2 deletions Clutch/main.m
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ int main (int argc, const char * argv[])
for (NSString* selection in selections) {
int key;
struct timeval start, end;
NSLog(@"selection wow %@ ", selection);
//NSLog(@"selection wow %@ ", selection);

if (!(key = [selection intValue])) {
gbprintln(@"Please enter a proper number.");
Expand Down Expand Up @@ -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 %f s", _selectedApp.bundleIdentifier, sec);
gbprintln(@"Finished dumping %@ in %0.1f seconds", _selectedApp.bundleIdentifier, sec);



Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Works with all devices, iOS versions, architecture types, with most binaries.

This product is meant only for educational purposes and security research.

Current version: 2.0
Current version: *2.0-RC4*


Usage
Expand Down

0 comments on commit b911ab0

Please sign in to comment.