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

Thanks for flagging this SlideShare!

Oops! An error has occurred.

Reverse Engineering iOS apps

  • 8,666 views
Published

UAMobile 2013 talk

UAMobile 2013 talk

Published 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
8,666
On SlideShare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
156
Comments
0
Likes
17

Embeds 0

No embeds

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