Reverse Engineering iOS apps
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

Reverse Engineering iOS apps

  • 7,573 views
Uploaded on

UAMobile 2013 talk

UAMobile 2013 talk

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
7,573
On Slideshare
7,546
From Embeds
27
Number of Embeds
1

Actions

Shares
Downloads
127
Comments
0
Likes
13

Embeds 27

https://twitter.com 27

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Reverse Engineering iOS apps
  • 2. Max Bazaliy Mobile lead at RnR XP practices follower CocoaHeads UA founder
  • 3. Why? Security audit Competitor analysis Solution advantages FUN !
  • 4. Analysis
  • 5. External Traffic sniffing Module call tracing I/O activity
  • 6. Charles SSL proxying RepeatEdit request Breakpoints Bandwidth throttle
  • 7. Internal Disassembling Decompiling Debugging Resource reversing
  • 8. Binary file Image files Interface files Property list files CoreData model files
  • 9. Image files Compressed => pngcrush => appcrush.rb => artwork extractor
  • 10. Interface files NIBs Storyboards => nib dec => nib_patch
  • 11. CoreData Models mom => momdec
  • 12. Binary
  • 13. Tools otool otx class-dump MachOView Hopper IDA Cycript
  • 14. Segment 1 Segment command 2 Segment 2 Mach-O binary Segment command 1 Section 1 data Section 2 data Section 3 data Section 4 data Section 5 data … Section n data
  • 15. Mach-O header 0xFEEDFACE 0xFEEDFACF 0xCAFEBABE
  • 16. __TEXT -> code and read only data __objc sections-> data used by runtime
  • 17. __message_refs __cls_refs __symbols __module_info __class __meta_class __instance_vars __inst_meth __cls_meth __cat_cls_meth __protocol_ext __cat_inst_meth
  • 18. __message_refs __cls_refs __symbols __module_info __class __meta_class __instance_vars __inst_meth __cls_meth __cat_cls_meth __protocol_ext __cat_inst_meth
  • 19. @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; ! !!
  • 20. FairPlay AES MD5
  • 21. otool -arch all –Vl MyApp | grep -A5 LC_ENCRYP!
  • 22. > address (cryptoff + cryptsize) size (base address + cryptoff + cryptsize)! > gdb dump memory decrypted.bin 0x3000 0xD23000 ! > Address space layout randomization! > 0x1000 -> 0x4f000! > decrypted.bin -> binary!
  • 23. Rasticrac Clutch Crackulous
  • 24. Binary analysis
  • 25. Hopper Disassembler Debugger Decompiler IDA Disassembler Debugger + objc_helper
  • 26. Hopper Disassembler Debugger Decompiler IDA Disassembler Debugger + objc_helper + decompiler
  • 27. Hopper
  • 28. id objc_msgSend(id self, SEL op, ...)
  • 29. application_didFinishLaunchingWithOptions
  • 30. Control flow graph
  • 31. asm -> pseudocode
  • 32. ! Method names Strings Constants rd party 3
  • 33. Cycript Works at runtime Modify ivars Instantiate objects Invoking methods Swizzling methods
  • 34. But
  • 35. What next ? No Objective-C Integrity checks SSL pinning Obfuscation
  • 36. SSL pinning Public key Certificate
  • 37. - (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];!
  • 38. #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.!
  • 39. Method obfuscation Use functions Strip symbols Use #define inline ((always_inline))
  • 40. #define isEncrypted() bxtlrz()! static inline BOOL bxtlrz() {! …! }!
  • 41. Strings obfuscation XORs Encoding keys Encoding table New key for app Use hash
  • 42. #define PTRACE_STRING_ENCODED @"<mlbD3Z1" #define PTRACE_STRING_ENCODED_HASH @"F47C218D1285CBC7F66B0FF88B15E10DC6690CBE" #define PTRACE_STRING_DECODED_HASH @"F4B756A8181E5339D73C9E2F9214E8949D2EE4F2”
  • 43. #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; }
  • 44. Anti debugger tricks Deny attach Constructor -> nil Change values
  • 45. #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;! }!
  • 46. ASSEMBLER
  • 47. mov r0, #31 ! mov r1, #0 ! mov r2, #0 ! mov r3, #0 ! mov ip, #26 ! svc #0x80 !
  • 48. int main(int argc, char *argv[])! {! @autoreleasepool {! denyDebugger();! return UIApplicationMain(argc, argv, nil, nil));! }! }!
  • 49. + (PurchaseManager *)sharedManager {! if (isDebugged())! !return nil;! static PurchaseManager *sharedPurchaseManager = nil; ! static dispatch_once_t onceToken;! !dispatch_once(&onceToken, ^{ ! !! !sharedPurchaseManager = [[self alloc] init];! });! !return sharedPurchaseManager ; ! }!
  • 50. Integrity checks Is encrypted SC_Info dir iTunesMetadata .dylib files
  • 51. 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;
  • 52. 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);
  • 53. !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);!
  • 54. 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; } }!
  • 55. What next? Terminate app Run in demo mode Change behavior
  • 56. Jailbreak detection Path check File access Root check Process name System files
  • 57. ! NSError *error; ! NSString *jailTest = @”Jailbreak time!";! [jailTest writeToFile:@"/private/test_jail.txt" atomically:YES encoding:NSUTF8StringEncoding error:&error];! if(error==nil) {! …! }! !
  • 58. if (getuid() == 0) {! …! }! ! ! if (system(0)) {! ...! }!
  • 59. NSArray *jailbrokenPaths = @[@"/Applications/Cydia.app",! ! ! !@"/usr/sbin/sshd",! ! !@"/usr/bin/sshd",! ! ! !@"/private/var/lib/apt",! ! ! !@"/private/var/lib/cydia”! ! ! !@"/usr/libexec/sftp-server",! ! ! !@"/Applications/blackra1n.app",! ! ! !@"/Applications/Icy.app",! ! ! ! ! ! !@"/Applications/RockApp.app",! ! !! ! ! !@"/private/var/stash"];! ! NSString *rooted;! for (NSString *string in jailbrokenPath)! if ([[NSFileManager defaultManager] fileExistsAtPath:string]) {! …! }!
  • 60. ! ! for (NSDictionary * dict in processes) {! !NSString *process = [dict objectForKey:@"ProcessName"];! !! !if ([process isEqualToString:CYDIA]) {! !! ! ! !...! !! ! ! !}! }! !
  • 61. struct stat sb;! stat("/etc/fstab", &sb);! long long size = sb.st_size;! if (size == 80) {! !! ! ! !return NOTJAIL;! } else! !! ! ! !return JAIL;! }!
  • 62. Cracking time = Protection time
  • 63. @mbazaliy