In recent weeks I had an itch to take another look at mobile testing. The last time I looked at mobile testing most of my environment revolved around applications developed for Android. I think this is a choice that most testers choose due to the fact of how complicated it is to get bootstrapped into an environment for iOS testing. Apple does not make things easy for the security researcher. First, getting root access to an iOS device requires obtaining/finding a jailbreak for your device. Second, emulation for iOS did not exist for a long time until Corellium showed up, and even then Apple tried to buy them and then sue them out of existence (luckily they still exist!). Third, applications from the official App Store are encrypted/signed with Apple being the only authority. Forth, official iOS development has been pretty much locked to OS X only. Fifth, because of the cat and mouse game between Apple and jailbreakers, googling for information on how to do any of this security research is hit or miss and ever-changing year by year making this whole process super confusing.
I decided to write this blog post as a set of steps for myself to take whenever I need to create an environment for iOS testing in the modern day. In this blog post I will describe the following steps for testing on 2 types of environments:
Environment: Physical Device
- Enabling ssh on your physical iOS device
- Create an iOS tweak development environment on Ubuntu (AWS EC2)
- Deploy certificate pinning bypass from Ubuntu to physical iOS device
- Set up Burp MITM for testing Apps on your physical iOS device
Environment: Emulated Device (Corellium)
- Set up an emulated jailbroken iOS device on Corellium
- Configure emulated iOS device to side load apps via ssh
- Be able to decrypt apps from your physical iOS device, re-package them and side load them onto your emulated iOS device
- Test Apps on your emulated iOS device through Burp
Best of all is that all these steps do not require OS X. This guide sets up Burp for a physical iOS device and an emulated iOS device. You are probably wondering why we can’t just use an emulated iOS device. The answer is that you can if you have an unencrypted IPA file of the App you wish to test on Corellium. However, I am assuming if you are a bug bounty hunter then you are trying to obtain the most up-to-date apps that the App Store has to offer from your target. Unfortunately due to certain limitations Corellium emulated iOS devices cannot give you access to the App Store. Therefore, this guide shows how you can pull Apps off of a physical device with App Store access and decrypt/re-sign the App and deploy it on 1 or more Corellium emulated devices. So let’s get started!
OK so I lied a tiny bit. I did have to use a MacBook (OS X) briefly to pull off my jailbreak (but technically you shouldn’t need to). For my target physical device I decided to purchase an iPad Mini 4. The reason why I chose this hardware is because the Mini 4 still gets the latest iOS updates (at the time of this writing) and has hardware that is vulnerable to the bootrom exploit triggered by checkra1n. You can find checkra1n here: https://checkra.in/ and in theory checkra1n should work on devices running linux, but in practice I could never get it to work. Using a MacBook on the other hand always yielded a successful jailbreak. I’m not going to document the steps here on how to jailbreak your specific device, there are tons of resources on the internet on how to do such a thing. The best place to start is: https://canijailbreak.com/
Setting up iOS device for SSH/Tweaks
After you’ve jailbroken your device and you are on your device with Cydia installed, the next thing to do is to ensure that OpenSSH is installed and running and that mobilesubstrate is up to date. To do that follow these steps:
1) Once you’ve successfully jailbroken your device and have Cydia installed go ahead an open “Cydia”
2) Cydia may ask you to upgrade, go ahead an select “Complete Upgrade”, "Confirm" and “Return to Cydia” when complete
3) Tap on the search tool and search for “openssh”, tap on it and then tap on “install” and “confirm”
4) Tap on “Return to Cydia”
5) Next thing to install/update is mobilesubstrate for supporting tweaks, go to the search tool again
6) Search for “cydia substrate”, tap on it
7) Tap on install (or modify then tap on update)
8) Tap on “Restart Springboard”
9) If for whatever reason your respring fails in an infinite loop, re-jailbrake your device in safe mode and reinstall “cydia substrate”
Setting up a Linux Development Environment
Next, we’ll create a development environment on Ubuntu. Specifically for me I am using Ubuntu 20 on a T2 EC2 AWS instance. There is no hard requirement to using EC2, feel free to use other cloud service provider or your own hardware. Next, we’ll be installing all the requirements for Theos https://github.com/theos/theos . Theos is an iOS development toolchain that is cross platform and will allow us to build iOS software on our linux instance and deploy it to either our physical iOS device or emulated iOS device. The following are the terminal commands I used to get everything configured.
Starting from a WSL2/Linux terminal we first set up an ssh tunnel to our linux instance with a remote port forward to our physical iOS device (You can do the same in Putty, but for this tutorial I’ll stick to linux). For this example lets assume our iOS device IP is 192.168.1.100 (change this to what your device IP really is) and we use the -R flag to create a service on the linux instance at port 2222 to forward into our device’s ssh port at 192.168.1.100:22
1) ssh <Instance IP> -R 2222:192.168.1.100:22
Next while on the instance we start to provision the dependencies we need for the software we intend to use.
2) sudo apt update
3) sudo apt-get install git zstd perl clang-6.0 build-essential libz3-dev zip unzip openvpn -y
We then configure our bash profile to be aware of Theos specific configuration.
4) nano ~/.profile
a) append the following lines in nano and save:
b) export THEOS=~/theos
c) export PATH=$THEOS/bin:$PATH
d) export THEOS_DEVICE_IP=127.0.0.1
e) export THEOS_DEVICE_PORT=2222
f) alias theos="nic.pl"
Exit the instance and ssh back to sync the settings
5) exit -> ssh <Instance IP> -R 2222:192.168.1.100:22
Now lets install Theos
6) git clone --recursive https://github.com/theos/theos.git $THEOS
Next we need to deploy the iOS SDKs into Theos
7) curl -LO https://github.com/theos/sdks/archive/master.zip
8) TMP=$(mktemp -d)
9) unzip master.zip -d $TMP
10) mv $TMP/sdks-master/*.sdk $THEOS/sdks
11) rm -r master.zip $TMP
Next we need to deploy the clang toolchain for compiling ObjC and Swift apps
12) wget https://github.com/CRKatri/llvm-project/releases/download/swift-5.3.2-RELEASE/swift-5.3.2-RELEASE-ubuntu20.04.tar.zst
13) tar -I zstd -xvf swift-5.3.2-RELEASE-ubuntu20.04.tar.zst
14) mkdir -p $THEOS/toolchain/linux/iphone
15) mv ./swift-5.3.2-RELEASE-ubuntu20.04/* $THEOS/toolchain/linux/iphone/
16) rm -rf swift-5.3.2-RELEASE-ubuntu20.04*
(Optional) Next lets try and create our very first iOS tweak
17) run command "theos"
18) <select iphone/tweak>
19) <name project "test">
20) <press enter for the remaining questions>
21) cd test
At this point your tweak should have successfully compiled, neat.
(Optional) Other tips:
a) make package # this creates a deb package to deploy
b) make install # this connects via SSH to install deb package
c) make GO_EASY_ON_ME=1 # to turn off warnings as errors
That’s it! you now have a workable iOS development environment in Linux.
Setting up your physical iOS Device through Burp
For those familiar with web app testing using Burp Suite on Android this section of steps should seem straight forward. These steps assume a fairly open network configuration, if your network is set up differently then your steps on how to proxy traffic from iOS through Burp may vary, however this is a good example in any case.
1) Download and install Burp Suite Community Edition from https://portswigger.net/
2) Start Burp Suite
3) Click on the “Proxy” tab
4) Click on “Intercept is on” button
5) Click on “Options” tab
6) Under Proxy Listeners click on “127.0.0.1:8080” and click edit
7) Click on the “All Interfaces” radio button and click “OK”
8) Click on “Yes” to the listen on all interfaces warning dialog
9) Click on the “HTTP History” tab
10) On your physical iOS device open the “Settings” app
11) tap on “Wi-Fi”
12) tap on the “i” button on your connected Wi-Fi network
13) tap on “Configure Proxy”
14) tap on “Manual”
15) tap on “Server” and enter the internal IP address of the machine running Burp Suite (assuming its on the same network)
16) tap on “Port” and enter “8080” and tap on “Save”
17) tap on home button to go back to main screen
At this point you should have all HTTP/HTTPS traffic proxying through Burp, however all TLS session should fail due to either a lack of a trusted certificate or failure of certification pin validation. Let’s test that real quick:
1) Go to into Safari
2) Navigate to https://www.google.com
3) At this point you should have a “This Connection is Not Private” warning
Using SSLBypass to Bypass All Certificate Checks
So at this point many people are familiar with installing a Burp Suite signed certificate into the OS to get TLS running. Furthermore, if you are familiar with certificate pinning bypass on Android using Frida you are probably also concerned with cert pin failures on iOS. We can kill 2 birds with 1 stone by using a tweak from EvilPeguin called SSLBypass. Let’s go back to our EC2 dev instance and compile this tweak.
1) Go back to your EC2 instance at your home directory: cd ~
2) git clone https://github.com/evilpenguin/SSLBypass
3) cd SSLBypass
4) make package
5) make install # use 'alpine' when asked for a password
After a quick restart of the SpringBoard the iOS device should now be fully capable of establishing TLS connections through burp via Safari or native app and you can now test apps on your device to your heart’s content.
Decrypt Apps for Reversing and Sideloading
So now that we have our physical device set up correctly there is an important reason why we need it for Corellium. The emulated iOS instances do not allow you to download apps off the AppStore. What we need to do is download any/all Apps we require from the AppStore on an authentic device, transfer the app off the device and side load it onto the emulated iOS instance. However, in order to package the app correctly for it to run on Corellium we need to decrypt the binary. All apps on the AppStore are encrypted so that they are only allowed to run from the intended device. Luckily we can use another piece of software to decrypt binaries. The other benefit of decrypting iOS app binaries is that you can load them into IDA and other binary research tools for further reverse engineering analysis. For this example we will be using Twitter’s iOS app as an arbitrary example. They do allow researchers to test their app per their bounty program guidelines found here.
Prep the device
1) On your physical device go back to settings and turn off the proxy settings in order to remove Burp out of the loop.
2) On your physical device download/install Twitter from the AppStore (account and login required)
3) SSH into your physical device: ssh firstname.lastname@example.org -p 2222Install flexdecrypt by John Coates on your device
4) wget https://github.com/JohnCoates/flexdecrypt/releases/download/1.1/flexdecrypt.deb
5) dpkg -i flexdecrypt.deb
6) rm flexdecrypt.deb
Now that we have flexdecrypt installed we can decrypt any Mach-O binary on your iOS device. This tool can be used for dumping and re-packaging iOS apps off your physical device and onto a Corellium device. In order to assist in this process I created a wrapper tool for flexdecrypt called flexdump found here. Using this tool you can dump the Twitter app into an IPA file to load onto Corellium. Flexdump was a hack script that was created for this tutorial and was only tested on an iPad mini 4 running iOS 14.6. This script may not work in older versions of iOS.
First lets install some dependencies:
1) apt update # make sure manual proxy is not configured
2) apt install zip unzipNext we install flexdump by running this exact command:
3) wget https://gist.githubusercontent.com/defparam/71d67ee738341559c35c684d659d40ac/raw/30c7612262f1faf7871ba8e32fbe29c0f3ef9e27/flexdump -P /usr/local/bin; chmod +x /usr/local/bin/flexdump
You can review all the apps you have installed by running:
Now that we know the app name
Twitter.app we can dump, decrypt and create an IPA package by running:
flexdump dump Twitter.app which should look roughly like this:
Sweet! we now have an IPA file that we can transfer off the physical device and transfer onto out Corellium device. Next lets
exit the iOS device back to our EC2 instance, and transfer the IPA file onto your instance by running the command:
scp -P 2222 email@example.com:/var/mobile/Documents/Flexdump/Twitter_8.69.2_fd.ipa ~
And that’s it! We no longer need the physical device anymore and we can now distribute the IPA file to all your Corellium instances or fellow collaborators running Corellium that don’t have iOS hardware.
(edit) Note: Just a quick warning on IPA dumps. They will not always work for every app. Because decryption/signing will modify the various binaries in the IPA this may break application specific integrity checks. For example if the app you are targeting has logic that checks if the device or the app itself has been tampered than you may not be successful running the App on a different device.
Setup a Corellium Instance and Install IPA
Now that we have a decrypted IPA file of the target app off your authentic iOS device lets now create an emulated iOS device and install the app onto it.
Go to https://app.corellium.com/ and login into your account
Once logged in go and create a new device
Select the device that is close if not identical to your physical device. In my case I tested this flow on an iPad mini 4 (Wi-Fi only).
Select your iOS version and make sure the device is jailbroken. In my case this flow was tested on iOS 14.6.
Feel free to name your device and set advanced boot options. In my case I just clicked “Create Device”.
Now wait a moment as your emulated device is being created in the background (Note: this may take a while)
Done and running!
So at this point the emulated device is ready for the IPA file to be installed onto it. Corellium has an interface to install IPA files in the web interface however, this interface is not reliable for IPA files built using Flexdump. In order to install this IPA file we need to install AppSync/appinst onto our emulated device. We can do that through our EC2 instance using a VPN tunnel to the device. Let’s start by setting up that tunnel.
First click on the OPVN FILE button under the connect tab, save the file because we will be using it later on the windows side and open the opvn file in a text editor.
Copy the entire contents of this file into your clipboard and go into your EC2 instance and run the command:
This will open up nano, paste the entire contents of the ovpn data and save the file to disk. This way we can connect to the VPN both from Windows and from your EC2 instance.
On your EC2 instance lets go ahead and connect to the VPN by running the following command:
sudo openvpn --config ~/device.ovpn &
This should connect to the VPN successfully like so:
We have successfully connected to the Corellium VPN service and we can now access our emulated device via the SSH service on
Now lets go ahead and compile/install AppSync/Appinst on our instance place it onto our emulated device.
First lets clone the repo for AppSync/Appinst:
1) git clone https://github.com/akemin-dayo/AppSync
2) cd AppSyncNext we need to patch the Makefile real quick for THEOS to work
3) sed -i 's/clang::5.0/clang::6.0/g' ./Makefile
4) sed -i 's/clang::5.0/clang::6.0/g' ./appinst/MakefileNext set up the THEOS variable for installing onto Corellium. Corellium in the WebUI should specify the device IP address
5) export THEOS_DEVICE_IP=10.11.1.1 # The IP shown in webui
6) export THEOS_DEVICE_PORT=22Next lets build/install AppSync onto Corellium
7) make package GO_EASY_ON_ME=1
8) make install # enter password 'alpine' each time it asksNext lets build/install Appinst onto Corellium
9) cd ./appinst
10) make package GO_EASY_ON_ME=1
11) make install # enter password 'alpine' each time it asks
Now that we have appinst installed we can finally install our Twitter IPA onto the Corellium device. If you remember, the IPA is currently at
~/Twitter_8.69.2_fd.ipa on our instance. Lets go head and load it onto our Corellium device via SCP:
1) scp ~/Twitter_8.69.2_fd.ipa firstname.lastname@example.org:~
Excellent next lets go ahead an SSH into our Corellium device and use appinst to finally install the dumped Twitter IPA:
1) ssh email@example.com # password 'alpine'Once your are in the device
2) appinst ~/Twitter_8.69.2_fd.ipa
And that’s it! Once the IPA is installed the output should look like:
And most importantly your device output screen should show the app and be able to open it successfully!
Now before we loop Burp Suite in this flow I just want to identify that Corellium has a nice traffic viewer. If you go into the “Network” tab and click on “Start Monitoring” you can get a pretty nice view of some of the HTTPS traffic that the app sends at launch:
Setup Burp Suite for Analysis with Corellium
So now that we have the app installed on Burp Suite we are going to follow similar steps from the steps listed in the above section “Setting up your physical iOS Device through Burp”. The first thing you’ll want to do is install OpenVPN for Windows. Go to https://openvpn.net and download/install the client for Windows. Once you have OpenVPN running go to the taskbar and right click on the OpenVPN icon and click “Import File…”
Remember the OVPN file we downloaded earlier? Go ahead and navigate/import the file into OpenVPN. Then go back to the OpenVPN icon and click on “Connect”.
Once a connection is made OpenVPN should have an IP address assign to you and you can have your emulated device interact with your Burp Suite session. In my case, the IP address assigned to me is
At this point the steps on setting up Burp Suite are similar to the ones above, namely:
1) Start Burp Suite
2) Click on the “Proxy” tab
3) Click on “Intercept is on” button
4) Click on “Options” tab
5) Under Proxy Listeners click on “127.0.0.1:8080” and click edit
6) Click on the “All Interfaces” radio button and click “OK”
7) Click on “Yes” to the listen on all interfaces warning dialog
8) Click on the “HTTP History” tab
9) On your Corellium iOS device open the “Settings” app
10) tap on “Wi-Fi”
11) tap on the “i” button on the "Corellium" Wi-Fi network
12) tap on “Configure Proxy”
13) tap on “Manual”
14) tap on “Server” and enter the IP address given to you from OpenVPN, in my case this is "10.11.3.3"
15) tap on “Port” and enter “8080” and tap on “Save”
16) tap on home button to go back to main screen
Now when you open the Twitter app and attempt to login you will see all the traffic being routed through Burp Suite on your Windows machine via the VPN. Also it appears we don’t need to install the SSLBypass tweak to bypass cert pinning or to install the Burp certificate. I believe by virtue of starting the Network Monitor, Corellium does some magic in the background to take care of the certificate validation in order to enhance our visibility and make it easier for researchers. If for whatever reason this proves not to be true in all cases, feel free to follow the SSLBypass tweak install steps in the above section and target the Corellium device IP instead of your physical device. SSLBypass should be able to be installed on Corellium devices too.
I wrote this document after several weeks of bashing my head trying to figure out how to do all this. This document serves as reference material for me in the future because I WILL forget all these nitty-gritty steps. I’m happy to publish this material for everyone else to use in order to bootstrap yourself into an iOS testing enviroment for pentesters and bounty hunters. The wonderful thing about Corellium is that once one pentester or bounty hunter has dumped a target IPA on a physical device they can now enable all their collaborators to test the target iOS app on emulated Corellium devices without having to purchase expensive Apple hardware and deal with jailbraking!
A big thanks to my colleague James Emrich (EvilPenguin) for developing SSLBypass and for helping me reason through A LOT of issues I encountered along the way. And thanks to you for reading this, happy testing!