Building an iOS Application Scanner Part 1 - IPA Bundle Explorationios mobile reverse engineering python
Whether you consider yourself a researcher, a reverse engineer, or a curious tinkerer– you're guaranteed to go further if you can find ways to analyze your targets more efficiently. In this first of a series of posts, we're going to begin looking at the .IPA file format used by iOS applications, and how we can use existing Python libraries to write a standalone .IPA security scanning tool.
Today I'm going to show you how to begin writing a standalone iOS application scanner– a tool that will automatically process and analyze an iOS application package so that you can get to the fun parts: figuring how your target works, and finding bugs! During the course of this multi-part tutorial series, we will:
- Become familiar with the composition and structure of the .IPA file format.
- Explore some of the existing Python libraries available for writing scripts to work with the different files we'll encounter.
- Learn how to hook our script into popular reverse engineering frameworks to perform advanced analysis tasks such as decompilation of dynamic libraries.
There are many tools that already do this. Some examples include:
- MobSF (https://github.com/MobSF/Mobile-Security-Framework-MobSF)
- Passionfruit (https://github.com/chaitin/passionfruit)
Things I'm not going to cover in this series:
- Jailbreaking your device
- Decrypting applications downloaded from the App Store
While these topics are necessary prerequisites to really begin testing applications, there are plenty of other guides out there for setting up a testing environment. The details of these topics changes relatively frequently, and some aspects (jailbreaking) differ based on your iOS version, device hardware, etc.
All you will need to follow along with this project is Python, and an iOS application bundle. For this post, I'm going to be using v2 of the DVIA application, which you can find here.
IPA Format Overview
Applications written for the iOS are packaged in the IPA (iOS App Store Package) file format. On the actual device, IPAs that you've downloaded from the App Store will be installed into /private/var/mobile/Applications, and will be encrypted by Apple's Fair Play DRM– an anti-piracy measure that can be bypassed on a jailbroken device by dumping the decrypted, running application from memory.
If you take a look at an IPA file in your favorite hex editor, you can learn something interesting:
$ hexdump -C -n64 DVIA-v2-swift.ipa 00000000 50 4b 03 04 0a 00 00 00 00 00 f6 6c 93 4c 00 00 |PK.........l.L..| 00000010 00 00 00 00 00 00 00 00 00 00 08 00 10 00 50 61 |..............Pa| 00000020 79 6c 6f 61 64 2f 55 58 0c 00 e2 63 d8 5a e0 63 |yload/UX...c.Z.c| 00000030 d8 5a f5 01 14 00 50 4b 03 04 0a 00 00 00 00 00 |.Z....PK........| 00000040
Here, I'm using the hexdump utility's canonical display option to view the first 64 bytes of the file. What the first 4 bytes tell us is that this is a zip-based file format. Such files will start with either 50 4B 03 04, 50 4B 05 06, or 50 4B 07 08.
Assuming “zip-based” means this file is a zip archive, the next question is: what's inside? An IPA is generally broken down into the following structure, with a “Payload” directory at the top level, and where “Application” is the name of your application:
App.ipa -> /Payload -> /Application.app -> /_CodeSignature -> CodeResources -> /Application (the "binary") -> /embedded.mobileprovision -> /Frameworks -> /Info.plist -> *OTHER RESOURCES -> /iTunesArtwork -> /iTunesMetadata.plist
- /Application.app This is a subdirectory within the top level
Payloaddirectory, which contains most of the bundle's files.
- /_CodeSignature/CodeResources - An important aspect of iOS security is that all iOS code is signed (link). All resources are also signed, and those signatures exist in this XML property list file.
- /Application - This is the actual Mach-O binary executable. It often, but not always, will share the name of whatever the .App file is called.
- embedded.mobileprovision - This is the provisioning profile, which is a property list (plist) file that specifies permissions for the app. If it is a “development”, or “ad-hoc” release of the app, this file will also contain the UDIDs of devices that the app is provisioned to run on.
- /Frameworks - The Frameworks folder contains compiled dynamic libraries used by the application uses, as well as additional .framework directories. These directories encapsulate a dynamic library with whatever additional resources it needs.
- OTHER RESOURCES - An application can contain virtually any other types of resources, from images, to video files, to XML and JSON format configuration files. Extracting useful information from these resource files is very valuable task, as they can contain configuration details, informaiton such as URLs pointing to external API endpoints, email addresses, and even sensitive information such as passwords or other secrets.
Now that you hopefully understand a little bit more about the IPA file format and the files you can expect to find within an IPA bundle, we can begin taking it apart.
The process of analyzing this file will consist of the following general steps:
- Exract the contents of the archive.
- Learn more about the application by reading the Info.plist property list file.
- Perform static code analysis on the application binary, and any shared libraries.
- Additional tasks as necessary =P
Lucky for us, there are already some really great Python libraries that exist for working with all of the file formats you'll find inside of an IPA.
- zipfile - (https://docs.python.org/3/library/zipfile.html)
- macholib - (https://pypi.org/project/macholib/)
- plistlib - (https://docs.python.org/3/library/plistlib.html)
We'll begin our exploration by extracting the contents of the archive. To do that, we'll just need two libraries, zipfile and argparse. While entirely optional, argparse makes it far easier to build a command line tool by simplifying the processing of working with command line arguments. Since we'll be taking a command line argument (the name of our IPA), we'll use it here.
When you run it, you'll see something like this:
$ python unpackage.py DVIA-v2-swift.ipa [+] Searching for Info.plist... Payload/ Payload/DVIA-v2.app/ Payload/DVIA-v2.app/_CodeSignature/ Payload/DVIA-v2.app/_CodeSignature/CodeResources Payload/DVIA-v2.app/main-bg.png Payload/DVIA-v2.app/LaunchImage-1100-Portraitfirstname.lastname@example.org Payload/DVIA-v2.app/Phishing.storyboardc/ Payload/DVIA-v2.app/Phishing.storyboardc/Phishing.nib/ Payload/DVIA-v2.app/Phishing.storyboardc/Phishing.nib/objects-11.0+.nib Payload/DVIA-v2.app/Phishing.storyboardc/Phishing.nib/runtime.nib Payload/DVIA-v2.app/Phishing.storyboardc/yd0-Gb-t2M-view-uOc-SH-0G0.nib/ Payload/DVIA-v2.app/Phishing.storyboardc/yd0-Gb-t2M-view-uOc-SH-0G0.nib/objects-11.0+.nib Payload/DVIA-v2.app/Phishing.storyboardc/yd0-Gb-t2M-view-uOc-SH-0G0.nib/runtime.nib Payload/DVIA-v2.app/Phishing.storyboardc/Info.plist Payload/DVIA-v2.app/AppIcon20x20@2x.png Payload/DVIA-v2.app/RuntimeManipulation.storyboardc/ [continued...]
As you can see, the package bundle contains a large number of resource files, in addition to the notable files described above. I'd recommend taking some time to explore the resource file types that may be unfamiliar to you, such as .car, .nib, and .mom files.
At this point, I hope you understand a little bit more about what's going on in an IPA, and have managed to build a small script that will extract some key pieces of information from an iOS application.
In future posts, I'll dive deeper into the IPA bundle to add enhancements to our tool which will fingerprint development frameworks, hunt for interesting data in resource files, and peform some basic static analysis on the binary executable and dynamic libraries.