Reverse Engineering
iOS apps
Max
Bazaliy

Mobile lead at RnR
XP practices follower
CocoaHeads UA founder
Why?

Security audit
Competitor analysis
Solution advantages
FUN !
Analysis
External

Traffic sniffing
Module call tracing
I/O activity
Charles

SSL proxying
RepeatEdit request
Breakpoints
Bandwidth throttle
Internal

Disassembling
Decompiling
Debugging
Resource reversing
Binary file
Image files
Interface files
Property list files
CoreData model files
Image
files

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

NIBs
Storyboards
=> nib dec
=> nib_patch
CoreData
Models

mom
=> momdec
Binary
Tools

otool  otx
class-dump
MachOView
Hopper  IDA
Cycript
Segment 1

Segment command 2

Segment 2

Mach-O
binary

Segment command 1

Section 1 data
Section 2 data
Section 3 data
Se...
Mach-O
header

0xFEEDFACE
0xFEEDFACF
0xCAFEBABE
__TEXT -> code and read only data

__objc sections-> data used by runtime
__message_refs
__cls_refs
__symbols
__module_info
__class
__meta_class

__instance_vars
__inst_meth
__cls_meth
__cat_cls_m...
__message_refs
__cls_refs
__symbols
__module_info
__class
__meta_class

__instance_vars
__inst_meth
__cls_meth
__cat_cls_m...
@interface RRSubscription : NSObject!
{!
NSString *_subscriptionID;!
!unsigned int _period;!
float _price;!
NSDate *_creati...
FairPlay
AES

MD5
otool -arch all –Vl MyApp | grep -A5 LC_ENCRYP!
> address (cryptoff + cryptsize) size (base address + cryptoff + cryptsize)!

> gdb dump memory decrypted.bin 0x3000 0xD23...
Rasticrac
Clutch
Crackulous
Binary
analysis
Hopper

Disassembler
Debugger
Decompiler

IDA

Disassembler
Debugger
+ objc_helper
Hopper

Disassembler
Debugger
Decompiler

IDA

Disassembler
Debugger
+ objc_helper
+ decompiler
Hopper
id objc_msgSend(id self, SEL op, ...)
application_didFinishLaunchingWithOptions
Control flow graph
asm -> pseudocode
!

Method names
Strings
Constants
rd party
3
Cycript

Works at runtime
Modify ivars
Instantiate objects
Invoking methods
Swizzling methods
But
What
next ?

No Objective-C
Integrity checks
SSL pinning
Obfuscation
SSL
pinning

Public key
Certificate
- (void)connection:(NSURLConnection *)connection
willSendRequestForAuthenticationChallenge:
(NSURLAuthenticationChallenge ...
#define _AFNETWORKING_PIN_SSL_CERTIFICATES_ 1
!
AFHTTPClient.h!
@property (nonatomic, assign)
AFURLConnectionOperationSSLP...
Method
obfuscation

Use functions
Strip symbols
Use #define
inline
((always_inline))
#define isEncrypted() bxtlrz()!
static inline BOOL bxtlrz() {!
…!
}!
Strings
obfuscation

XORs
Encoding keys
Encoding table
New key for app
Use hash
#define PTRACE_STRING_ENCODED @"<mlbD3Z1"
#define PTRACE_STRING_ENCODED_HASH
@"F47C218D1285CBC7F66B0FF88B15E10DC6690CBE"
#...
#define verifyDecodedString(encoded, hashE, hashD, success)
fweybz(encoded, hashE, hashD, success)
static inline NSString ...
Anti
debugger
tricks

Deny attach
Constructor -> nil
Change values
#define denyDebugger() tmzpw()!
static __inline__ void tmzpw() {!
if (getuid() != 0) {!
!NSString *ptraceString = .. !
!voi...
ASSEMBLER
mov r0, #31
!
mov r1, #0
!
mov r2, #0
!
mov r3, #0
!
mov ip, #26
!
svc #0x80
!
int main(int argc, char *argv[])!
{!
@autoreleasepool {!

denyDebugger();!
return UIApplicationMain(argc, argv, nil, nil))...
+ (PurchaseManager *)sharedManager {!
if (isDebugged())!
!return nil;!
static PurchaseManager *sharedPurchaseManager = nil...
Integrity
checks

Is encrypted
SC_Info dir
iTunesMetadata
.dylib files
const struct mach_header *header = (struct mach_header *)dlinfo.dli_fbase;
struct load_command *cmd = (struct load_command...
BOOL isDirectory = NO;
NSString *directoryPath = [[[NSBundle mainBundle]
bundlePath]
stringByAppendingPathComponent:@”SC_I...
!NSDictionary *iTunesMetadata = [NSDictionary
!dictionaryWithContentsOfFile:[rootDirectoryPath
!stringByAppendingPathCompo...
BOOL dyLibFound = NO;
NSArray *directoryFiles = [[NSFileManager
defaultManager] contentsOfDirectoryAtPath:
[[NSBundle main...
What next?

Terminate app
Run in demo mode
Change behavior
Jailbreak
detection

Path check
File access
Root check
Process name
System files
!

NSError *error; !
NSString *jailTest = @”Jailbreak time!";!
[jailTest writeToFile:@"/private/test_jail.txt"
atomically:...
if (getuid() == 0) {!
…!
}!
!
!
if (system(0)) {!
...!
}!
NSArray *jailbrokenPaths = @[@"/Applications/Cydia.app",!
!

!

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

!

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

!

!

!@"/pr...
!
!
for (NSDictionary * dict in processes) {!
!NSString *process = [dict
objectForKey:@"ProcessName"];!
!! !if ([process i...
struct stat sb;!
stat("/etc/fstab", &sb);!
long long size = sb.st_size;!
if (size == 80) {!
!! ! ! !return NOTJAIL;!
} els...
Cracking time
=
Protection time
@mbazaliy
Reverse Engineering iOS apps
Reverse Engineering iOS apps
Reverse Engineering iOS apps
Reverse Engineering iOS apps
Reverse Engineering iOS apps
Reverse Engineering iOS apps
Reverse Engineering iOS apps
Reverse Engineering iOS apps
Reverse Engineering iOS apps
Reverse Engineering iOS apps
Reverse Engineering iOS apps
Reverse Engineering iOS apps
Reverse Engineering iOS apps
Upcoming SlideShare
Loading in...5
×

Reverse Engineering iOS apps

13,089

Published on

UAMobile 2013 talk

Published in: Technology
1 Comment
39 Likes
Statistics
Notes
No Downloads
Views
Total Views
13,089
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
229
Comments
1
Likes
39
Embeds 0
No embeds

No notes for slide

Reverse Engineering iOS apps

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

    Clipping is a handy way to collect important slides you want to go back to later.

×