reverse engineering ios apps

76
Reverse Engineering iOS apps

Post on 11-Sep-2014

6.141 views

Category:

Technology


11 download

DESCRIPTION

UAMobile 2013 talk

TRANSCRIPT

Page 1: Reverse Engineering iOS apps

Reverse Engineering

iOS apps

Page 2: Reverse Engineering iOS apps

Mobile lead at RnR XP practices follower CocoaHeads UA founder

Max Bazaliy

Page 3: Reverse Engineering iOS apps

Security audit Competitor analysis Solution advantages FUN !

Why?

Page 4: Reverse Engineering iOS apps

Analysis

Page 5: Reverse Engineering iOS apps

Traffic sniffing Module call tracing I/O activity

External

Page 6: Reverse Engineering iOS apps

SSL proxying Repeat\Edit request Breakpoints Bandwidth throttle

Charles

Page 7: Reverse Engineering iOS apps
Page 8: Reverse Engineering iOS apps

Disassembling Decompiling Debugging Resource reversing

Internal

Page 9: Reverse Engineering iOS apps
Page 10: Reverse Engineering iOS apps
Page 11: Reverse Engineering iOS apps

Binary file Image files Interface files Property list files CoreData model files

Page 12: Reverse Engineering iOS apps

Compressed => pngcrush => appcrush.rb => artwork extractor

Image files

Page 13: Reverse Engineering iOS apps

NIBs Storyboards => nib dec => nib_patch

Interface files

Page 14: Reverse Engineering iOS apps

mom => momdec CoreData Models

Page 15: Reverse Engineering iOS apps

Binary

Page 16: Reverse Engineering iOS apps

otool \ otx class-dump MachOView Hopper \ IDA Cycript

Tools

Page 17: Reverse Engineering iOS apps

Mach-O binary

Section 1 data

Section 2 data

Section 3 data

Section 4 data

Section 5 data

Section n data S

egm

ent 1

S

egm

ent 2

Segment command 1 Segment command 2

Page 18: Reverse Engineering iOS apps

0xFEEDFACE 0xFEEDFACF

0xCAFEBABE

Mach-O header

Page 19: Reverse Engineering iOS apps

__TEXT -> code and read only data

__objc sections-> data used by runtime

Page 20: Reverse Engineering iOS apps

__message_refs __cls_refs __symbols __module_info __class __meta_class

__instance_vars __inst_meth __cls_meth __cat_cls_meth __protocol_ext __cat_inst_meth

Page 21: Reverse Engineering iOS apps

__message_refs __cls_refs __symbols __module_info __class __meta_class

__instance_vars __inst_meth __cls_meth __cat_cls_meth __protocol_ext __cat_inst_meth

Page 22: Reverse Engineering iOS apps
Page 23: Reverse Engineering iOS apps

@interface RRSubscription : NSObject!{! NSString *_subscriptionID;!!unsigned int _period;!

float _price;! NSDate *_creationDate;!}!!+ (id)arrayOfSubscriptionsWithJSONArray:(id)arg1;!+ (id)subscriptionWithDictionary:(id)arg1;!!@property(readonly, nonatomic) NSDate *creationDate;!@property(readonly, nonatomic) float price; ! !!@property(readonly, nonatomic) unsigned int period; !

Page 24: Reverse Engineering iOS apps
Page 25: Reverse Engineering iOS apps

FairPlay

AES MD5

Page 26: Reverse Engineering iOS apps

otool -arch all –Vl MyApp | grep -A5 LC_ENCRYP!

Page 27: Reverse Engineering iOS apps

> address (cryptoff + cryptsize) size (base address + cryptoff + cryptsize)!

> gdb dump memory decrypted.bin 0x3000 0xD23000 !

> Address space layout randomization!

> 0x1000 -> 0x4f000!

> decrypted.bin -> binary!

Page 28: Reverse Engineering iOS apps
Page 29: Reverse Engineering iOS apps

Rasticrac

Clutch

Crackulous

Page 30: Reverse Engineering iOS apps

Binary analysis

Page 31: Reverse Engineering iOS apps

Disassembler Debugger Decompiler

Hopper

IDA Disassembler Debugger + objc_helper

Page 32: Reverse Engineering iOS apps

Disassembler Debugger Decompiler

Hopper

IDA Disassembler Debugger + objc_helper + decompiler

Page 33: Reverse Engineering iOS apps

Hopper

Page 34: Reverse Engineering iOS apps
Page 35: Reverse Engineering iOS apps

id objc_msgSend(id self, SEL op, ...)

Page 36: Reverse Engineering iOS apps

application_didFinishLaunchingWithOptions

Page 37: Reverse Engineering iOS apps

Control flow graph

Page 38: Reverse Engineering iOS apps

asm -> pseudocode

Page 39: Reverse Engineering iOS apps

! Method names Strings Constants 3rd party

Page 40: Reverse Engineering iOS apps

Works at runtime Modify ivars Instantiate objects

Invoking methods Swizzling methods

Cycript

Page 41: Reverse Engineering iOS apps
Page 42: Reverse Engineering iOS apps

But

Page 43: Reverse Engineering iOS apps
Page 44: Reverse Engineering iOS apps

No Objective-C Integrity checks SSL pinning Obfuscation

What next ?

Page 45: Reverse Engineering iOS apps
Page 46: Reverse Engineering iOS apps

Public key Certificate

SSL pinning

Page 47: Reverse Engineering iOS apps

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {!

…!NSData *remoteCertificateData =

CFBridgingRelease(SecCertificateCopyData(certificate));!

NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"MyLocalCertificate" ofType:@"cer"];!

NSData *localCertData = [NSData dataWithContentsOfFile:cerPath];!

if ([remoteCertificateData isEqualToData:localCertData]) {!

[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];!

} else {![[challenge sender]

cancelAuthenticationChallenge:challenge];!}!

Page 48: Reverse Engineering iOS apps

#define _AFNETWORKING_PIN_SSL_CERTIFICATES_ 1

!AFHTTPClient.h!@property (nonatomic, assign)

AFURLConnectionOperationSSLPinningMode sslPinningMode;

{ AFSSLPinningModePublicKey, AFSSLPinningModeCertificate }

AFURLConnectionOperation.h

When `defaultSSLPinningMode` is defined on `AFHTTPClient` and the Security framework is linked, connections will be validated on all matching certificates with a `.cer` extension in the bundle root.!

Page 49: Reverse Engineering iOS apps

Use functions Strip symbols Use #define inline

((always_inline))

Method obfuscation

Page 50: Reverse Engineering iOS apps

#define isEncrypted() bxtlrz()!static inline BOOL bxtlrz() {!…!}!

Page 51: Reverse Engineering iOS apps

XORs Encoding keys Encoding table New key for app

Use hash

Strings obfuscation

Page 52: Reverse Engineering iOS apps

#define PTRACE_STRING_ENCODED @"<mlbD3Z1" #define PTRACE_STRING_ENCODED_HASH

@"F47C218D1285CBC7F66B0FF88B15E10DC6690CBE" #define PTRACE_STRING_DECODED_HASH

@"F4B756A8181E5339D73C9E2F9214E8949D2EE4F2”

Page 53: Reverse Engineering iOS apps

#define verifyDecodedString(encoded, hashE, hashD, success)

fweybz(encoded, hashE, hashD, success)

static inline NSString * fweybz(NSString *encoded, NSString *hashE,

NSString *hashD, BOOL *success) {

NSString *decoded = decodedString(encoded);

if (success != NULL) {

*success = (decoded && [hashFromString(encoded) isEqualToString:hashEncoded] && [hashFromString(decoded) isEqualToString:hashDecoded]) ? YES : NO; return decoded;

}

Page 54: Reverse Engineering iOS apps

Deny attach Constructor -> nil Change values

Anti debugger

tricks

Page 55: Reverse Engineering iOS apps

#define denyDebugger() tmzpw()!

static __inline__ void tmzpw() {!

if (getuid() != 0) {!

!NSString *ptraceString = .. !

!void *handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);!

ptrace_ptr_t ptrace_ptr = (ptrace_ptr_t)dlsym(handle, ptraceString);!

ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);! dlclose(handle);!

}!

else!

*(volatile int *)NULL = 0xDEADBEEF;!

}!

Page 56: Reverse Engineering iOS apps

ASSEMBLER

Page 57: Reverse Engineering iOS apps

mov r0, #31!mov r1, #0!mov r2, #0!mov r3, #0!mov ip, #26!svc #0x80!

Page 58: Reverse Engineering iOS apps

int main(int argc, char *argv[])!{! @autoreleasepool {!

denyDebugger();! return UIApplicationMain(argc, argv, nil, nil));! }!}!

Page 59: Reverse Engineering iOS apps

+ (PurchaseManager *)sharedManager {!if (isDebugged())!!return nil;!

static PurchaseManager *sharedPurchaseManager = nil; !static dispatch_once_t onceToken;! !dispatch_once(&onceToken, ^{ !! ! !sharedPurchaseManager = [[self alloc] init];!

});!!return sharedPurchaseManager ; !

}!

Page 60: Reverse Engineering iOS apps

Is encrypted SC_Info dir iTunesMetadata

.dylib files

Integrity checks

Page 61: Reverse Engineering iOS apps

const struct mach_header *header = (struct mach_header *)dlinfo.dli_fbase;

struct load_command *cmd = (struct load_command *) (header + 1);

for (uint32_t i = 0; cmd != NULL && i < header->ncmds; i++) {

if (cmd->cmd == LC_ENCRYPTION_INFO) {

struct encryption_info_command *crypt_cmd = (struct encryption_info_command *)cmd;

if (crypt_cmd->cryptid < 1)

return NO;

else

return YES;

}

else

cmd = (struct load_command *)((uint8_t *) cmd + cmd->cmdsize);

}

return NO;

Page 62: Reverse Engineering iOS apps

BOOL isDirectory = NO; NSString *directoryPath = [[[NSBundle mainBundle]

bundlePath] stringByAppendingPathComponent:@”SC_Info/”];

BOOL directoryExists = [[NSFileManager defaultManager] fileExistsAtPath:directoryPath isDirectory:&isDirectory];

BOOL contentSeemsValid = ([[[NSFileManager defaultManager] contentsOfDirectoryAtPath:directoryPath error:NULL] count] == 2);

Page 63: Reverse Engineering iOS apps

!NSDictionary *iTunesMetadata = [NSDictionary !dictionaryWithContentsOfFile:[rootDirectoryPath !stringByAppendingPathComponent:@” iTunesMetadata.plist”]];!!NSString *appleID = iTunesMetadata[appleID];!

NSDictionary *accountInfo = iTunesMetadata[downloadInfoKey][accountInfo];!!BOOL isValidAppleID = (appleID.length > 0 && ![appleID rangeOfString:appleIDMailAddress !options:NSCaseInsensitiveSearch].location == !NSNotFound);!

BOOL isValidDownloadInfo = (accountInfo.count > 0);!

Page 64: Reverse Engineering iOS apps
Page 65: Reverse Engineering iOS apps

BOOL dyLibFound = NO; NSArray *directoryFiles = [[NSFileManager

defaultManager] contentsOfDirectoryAtPath:[[NSBundle mainBundle] bundlePath] error:NULL];

for (NSString *filename in directoryFiles) { if ([[filename pathExtension]

caseInsensitiveCompare:@”dylib”] == NSOrderedSame) {

dyLibFound = YES; break; } }!

Page 66: Reverse Engineering iOS apps

Terminate app Run in demo mode Change behavior

What next?

Page 67: Reverse Engineering iOS apps
Page 68: Reverse Engineering iOS apps

Path check File access Root check Process name System files

Jailbreak detection

Page 69: Reverse Engineering iOS apps

!NSError *error; !NSString *jailTest = @”Jailbreak time!";![jailTest writeToFile:@"/private/test_jail.txt"

atomically:YES encoding:NSUTF8StringEncoding error:&error];!

if(error==nil) {!…!}!!

Page 70: Reverse Engineering iOS apps

if (getuid() == 0) {!…! }!!! if (system(0)) {!...! }!

Page 71: Reverse Engineering iOS apps

NSArray *jailbrokenPaths = @[@"/Applications/Cydia.app",!

! ! !@"/Applications/RockApp.app",!

! ! !@"/Applications/Icy.app",!

! ! !@"/usr/sbin/sshd",!

! ! !@"/usr/bin/sshd",!

! ! !@"/private/var/lib/apt",!

! ! !@"/private/var/lib/cydia”!

! ! ! ! ! ! ! !@"/usr/libexec/sftp-server",!

! ! !@"/Applications/blackra1n.app",!

! ! !@"/private/var/stash"];!

!

NSString *rooted;!

for (NSString *string in jailbrokenPath)!

if ([[NSFileManager defaultManager] fileExistsAtPath:string]) {!

…!

}!

!

Page 72: Reverse Engineering iOS apps

!! for (NSDictionary * dict in processes) {!!NSString *process = [dict objectForKey:@"ProcessName"];!!! !if ([process isEqualToString:CYDIA]) {!!! ! ! !...!!! ! ! !}!

}!!

Page 73: Reverse Engineering iOS apps

struct stat sb;! stat("/etc/fstab", &sb);! long long size = sb.st_size;! if (size == 80) {!!! ! ! !return NOTJAIL;!

} else!!! ! ! !return JAIL;!

}!

Page 74: Reverse Engineering iOS apps

Cracking time =

Protection time

Page 75: Reverse Engineering iOS apps
Page 76: Reverse Engineering iOS apps

@mbazaliy