In the First part of the article, we have discussed about the iPhone application traffic analysis. Second part, Third part and Fourth part of the article covered in-depth analysis of insecure data storage locations on the iPhone. In this part we will take a look at runtime analysis of iOS applications. Runtime analysis allows an attacker to manipulate the application’s behaviour at runtime to bypass the security locks and access the sensitive information from memory. Before getting into runtime analysis first we will take a look at the iOS application architecture and its runtime protection features.
iOS Application Architecture:
iOS application is a zip archive with .ipa file extension. The zip file contains the executable binary and the iTunesArtwork which is used by the iTunes to manage the application. Typical structure of an iOS application is shown in the image below.
The .app folder within the Payload directory contains the application binary, all the resources of the application like images & audio, provisioning profile that specifies application permissions and code signature.
iOS application binary is ARM compiled and uses Mach-O (mach object) file format. Mach-O format consists of 3 main regions – header, load commands and segments/sections. The picture below illustrates the Mach-O file basic structure.
Mach-O structure of an iOS application can be viewed using otool on a jailbroken device. Otool is available in Darwin CC Tools package on Cydia.
It identifies the Mach-O file and contains basic file type information like target architecture and flags that affect the interpretation of rest of the file. To view the Mach-O header of an iOS application connect the iPhone over SSH and execute the below command.
otool –h ApplicationBinary
Below is the Mach-O header of Facebook iOS application.
cputype and subtype values in the Mach-O header indicates the application’s target architecture. The above image shows that the Facebook application is built for ARM7 processor.
ARM7s (iPhone 5) = cputype 12/ subtype 11
ARM7 (iPhone 4 & 4S) = cputype 12/ subtype 9
ARM6 (iPhone 3GS) = cputype 12/ subtype 6
Applications that are built for multiple architectures contain more than one Mach-O file. These binaries are called fat binaries or universal binaries. To view the Mach-O header of a fat binary, run the below command on SSH terminal.
otool –arch all -h ApplicationBinary
The above image shows that CardInfo application is compiled for ARM7 and ARM7s processors.
Load commands specify the layout and linkage characteristics of the file. It includes initial layout of the file in virtual memory, location of symbol table, execution state of main thread of the program and shared library details. Load commands (LC_ENCRYPTION_INFO) also define whether the application binary is encrypted or not. To view the load commands of an application, run the below command on SSH terminal.
otool –Vl ApplicationBinary
Mach-O file contains the actual data in one or more segments. Each segment contains zero or more sections. Each section of a segment contains code or data of some particular type. The exact number and layout of segments and sections is specified by the load commands.
iOS Application Runtime Protection Features:
The iOS platform provides a lot of runtime security features like ASLR, stack smashing protection and ARC. Understanding the runtime protection features is important for reversing & analyzing iOS applications.
Address Space Layout Randomization:
ASLR is an important exploit mitigation technique introduced in iOS 4.3. ASLR makes the remote exploitation of memory corruption vulnerabilities significantly more difficult by randomizing the application objects location in the memory. By default iOS applications uses limited ASLR and only randomizes part of the objects in the memory. In order to take full advantage of the ASLR the application has to compile with -fPIE -pie flag (“Generate Position-Dependent Code” build option in Xcode). In the latest version of the XCode this flag is automatically checked by default. The image below compares the different memory sections for partial and full ASLR applications.
To find out whether the application is compiled with PIE flag or not, connect the iPhone over SSH and execute the below command.
otool –Vh ApplicaitonBinary
The above image shows PIE at the end of the output. It indicates that the Facebook application is compiled with PIE flag.
Stack Smashing Protection:
Stack smashing protection is an exploit mitigation technique that protects against stack overflow attacks by placing a random value known as stack canary before local variables on stack. The stack canary is checked upon return of the function. Incase of an overflow the canary is corrupted, and the application is able to detect and protect against the overflow. In order to take advantage of the stack smashing protection the application has to compile with –fstack-protector-all flag.
iOS applications which are using the stack canaries will contain _stack_chk_fail and _stack_chk_guard symbols in the binary. To find out whether the application is protected with stack smashing protection or not, connect the iPhone over SSH and execute the below command.
otool –I –v ApplicationBinary | grep stack
Result shown in the above image indicates that the Facebook application is using the stack smashing protection.
Automatic Reference Counting:
ARC is another exploit mitigation technique introduced in iOS 5. It protects the applications from memory corruption vulnerabilities by moving the responsibility of memory management from the developer to the compiler. ARC can be enabled in an application within XCode by setting the compiler option “Objective-C Automatic Reference Counting” to “yes”. By default it is marked as “yes”.
iOS applications with ARC enabled will contain _objc_release symbols in the binary. To find out whether the application is using ARC or not, execute the below command on SSH terminal.
otool –I –v ApplicationBinary | grep _objc_release
Result shown in the above image indicates that the Facebook application is compiled with ARC flag.
Runtime protection features add an additional layer of security to the application. So during a pentest it’s always a best practice to recommend the application to implement the runtime protection features.
Reversing iOS Applications:
Objective-C is the primary language used to develop native iOS applications. Objective-C is a dynamic language based on the principles of message passing. As it is a dynamic language, all the classes, methods and any other components are stored in the binary itself. This information can be extracted using the class-dump-z tool written by kennytm.
1. On a JailBroken iPhone, install wget and unzip from Cydia.
2. Connect to the iPhone over ssh and run the below commands.
wget -U Mozilla/5.0 http://www.securitylearn.net/wp-content/uploads/tools/iOS/class-dump-z.zip
mv class-dump-z /usr/bin
3. To dump the class information from an iOS application navigate to the application’s .app folder and run the below command.
Below image shows the class dump of Gmail iOS application. The class dump does not reveal any useful data as the Gmail binary is encrypted. Applications downloaded from the AppStore are encrypted using FairPlay DRM to protect the piracy.
To find out whether the application is encrypted or not, run the below command on the SSH terminal.
otool –l ApplicationBinary | grep crypt
cryptid 1 indicates that the application is encrypted. For unencrypted applications cryptid value is 0.
So in case of reversing iOS applications often the first step includes removing the AppStore encryption. Removing this encryption allows an attacker to get a greater understanding of how the application binary works, the internal class structure and to get the binary in a suitable state for reverse engineering. The applications which are in-house distributed and self signed are not encrypted.
Decrypting iOS applications:
When an iOS application is launched, the loader decrypts it and loads it into memory. So a pretty well established process exists to take advantage of this process and remove the FairPlay copy protection of an iOS application. iOS application decryption process includes the below steps-
- Finding the starting offset and the size of the encrypted data in the application binary.
- Finding the memory loading address of the application (changes every time if the app is compiled with PIE).
- Dumping the decrypted portion of the application from memory using a debugger (ex: gdb).
- Overwriting the applications encrypted area with the dumped binary data.
- Changing the cryptid value to 0.
The complete decryption process has been automated by Cydia applications namely Clutch and Rasticrac.
Decrypting the Gmail iOS applications with Clutch:
1. On a JailBroken iPhone, go to Cydia and add the repo http://AppAddict.org/repo by navigating to Manage->Sources.
2. Download ClutchPatched, ZIP and IPA Installer from Cydia.
3. Connect to the iPhone over SSH and type the ‘Clutch’ command. It lists out all the applications installed on the iPhone.
4. Supplying the application name to the Clutch will decrypt it and stores the decrypted ipa file under /var/root/Documents/Cracked/ folder. The below image shows that Clutch cracked the Gmail application and stored the decrypted file as /var/root/Documents/Cracked/Gmail-v18.104.22.16821.ipa.
5. The cracked ipa file can be installed on the iPhone directly from SSH using the below command.
installipa –c [iPAPath]
The below image shows the class dump of the decrypted Gmail application.
A full class dump of a decrypted application maps to the classes, methods and provides an insight into what’s going on inside an application. Once the class dump is obtained, we can look into it for interesting classes, methods, properties and perform a runtime analysis.
Runtime Analysis With Cycript:
Runtime analysis involves reversing and analyzing the application work flow to bypass security locks, performing authentication bypass attacks, access sensitive information from memory, breaking logical checks and accessing restricted areas of the application. As Objective C is a reflective language, it allows to modification of its own behaviour at runtime. On the iPhone, iOS application runtime can be modified easily using the CyCript. Cycript is available in Cydia packages.
Before getting into the runtime analysis, it is necessary to understand the execution flow of an iOS application.
Objective C is a superset of C, so its execution also begins with main() function. When a user touches the application icon on the springboard, it calls main() function. Main() function in turn invokes UIApplicationMain method. UIApplicationMain instantiates the UIApplication object, displays the GUI (windows, views), creates the application delegate and set up the events cycle. Application delegate monitors the high level actions/events in the application. With Cycript we can connect to the running process and get access to the UIApplication object. UIApplication is a singleton object that represents the application and acts as a central control. So gaining access to the UIApplication object in turn gives access to the application internals.
The power of the cycript is demonstrated in below examples. For demonstration, I’ve used an older version of photo vault application. Before hooking into the application process with cycript first grab the class dump of the application using class-dump-z.
Accessing the instance variables with Cycript:
The photo vault application keeps the private photos securely by protecting with a password. When we launch the photo vault application for the first time, it prompts the user to set a password. Later, the user has to enter the correct password in order to access the private photos. Below steps explains how to grab the password from runtime using cycript.
1. Launch the photo vault application and it prompts for password.
2. Connect to the iPhone over SSH and grab the process id using ps ax command.
3. Hook into the application process using cycript –p [PID] command.
Note: If you know the application name you can attach the cycript using cycript –p [ApplicationName] command.
4. On the cycript prompt, we can get the instance of the application either by invoking [UIApplication sharedApplication] method or using the UIApp variable.
5. To find out the application delegate run UIApp.delegate command.
6. Search the class dump for the application delegate PhotoVaultAppDelegate and look for the @interface of it (class dump will have @interface & @protocol directives). An interface contains the declaration of all the methods and the properties. Whereas the protocol contains a group of related methods, which an object might call on its delegate.
7. Looking at the properties of the application delegate, shows an interesting property strPass. Access the value stored in the strPass using UIApp.delegate.strPass command.
8. Bingo!. It reveals the password to unlock the private photos. Type the password in the application and you will get access to the users private photos.
Cycript also allows to modify the instance variables, invoke instance methods and overwrite the existing methods directly from the runtime.
Penetration Testing For iPhone Applications is going to be covered in a series of articles. In the Part 6, we will take a look at method swizzling techniques with cycript and runtime analysis with GNU Debugger (gdb).
- Debunking NSLog Misconceptions
- Hacking and Securing iOS Applications by Jonathan Zdziarski
- “Apple iOS 4 Security Evaulation” by Dino Dai Zovi