Reverse Engineering iOS Apps - iOS 11 Edition (Part 1)
Even though there are already many, many blog posts, tutorials and even youtube videos about "reverse engineering iOS apps", every time Apple releases a new iOS version the "game" changes; researchers have to find a new way to jailbreak the new released version of iOS and we have to update our tools to work with the new jailbroken environment. This is especially true for the latest iOS 11 jailbreak, both LiberiOS and Electra jailbreaks, which are based on Ian Beer's async_wake exploit, have very different techniques than the previous jailbreaks and most (all?) of the existing tools are broken on these jailbreaks.
I'm going to focus on LiberiOS for this post since that's the only jailbreak I've tested. But also because I'm a huge fan of Jonathan Levin's work and his contributions to the community. The LiberiOS jailbreak is what's called a KPP-less jailbreak (KPP stands for Kernel Patch Protection). It basically means there are no modifications to the kernel areas that KPP guards, and most of the jailbreak tools (like Clutch, dumpdecrypted) and all of the tweaks that depend on Cydia Substrate haven't been updated to work with this approach.
This post ended up being a bit too long, so I decided to split it in two parts:
- Part 1: Will help you setup your device and decrypt iOS apps
- Part 2: Will help you dump the app's classes, disassemble its instructions and manipulate the runtime to change the app's behaviour
Syllabus
Part 1
- Jailbreak your device (external link)
- Setup
iTunnel
- Setup
bfinject
- Decrypt Starbucks iOS app using
bfinject decrypt
Part 2
- Dump Starbucks app's Classes using
class-dump
- Disassemble the Starbucks app using
Hopper
- Runtime manipulation using
bfinject cycript
Jailbreak your device (external link)
To begin RE'ing iOS apps you need a jailbroken device. In this post I'm assuming you are on iOS 11 so let's start with jailbreaking your device. I like the iClarified tutorials and they have a great one for jailbreaking your iPhone/iPod/iPad (iDevice) on iOS 11-11.1.2:
- Follow iClarified's tutorial to jailbreak your iDevice using LiberiOS here.
Now that your iDevice is jailbroken we can start reverse engineering iOS Apps!
Setup iTunnel
Even though LiberiOS' version of Dropbear SSH has wifi connectivity enabled, I find USB faster and more reliable. To SSH into your device via USB using your lighting cable you'll need to setup iTunnel
(or a similar tool).
- Download the latest version of
iTunnel
from here - Extract the contents of the .zip file
- Copy the
itnl
binary to/usr/local/bin
- Copy the
libmd.dylib
library to/usr/local/lib
You can also leave both files in a folder and execute theitnl
command with the./
prefix.
Setup bfinject
As I said before, many of the existing tools don't work as in previous jailbreaks, but thanks to Bishop Fox we can now use Clutch
in LiberiOS by doing the following:
- Create a folder called
bfinject
in your desktop - Download the latest .tar file in the
bfinject
folder - Run
itnl
to forward the ssh traffic to a different port,--lport
is the local port and--iport
is the iDevice port:
> itnl --lport 2222 --iport 22
- In a different terminal session SSH into the iDevice:
> ssh -p 2222 root@localhost
- Enter the root password, the default password is
alpine
(though you should change it)
- To enable the
binpack
add the binaries directories toPATH
:
# export PATH=$PATH:/jb/usr/bin:/jb/bin:/jb/sbin:/jb/usr/sbin:/jb/usr/local/bin:/sbin:/usr/sbin:/usr/local/bin:
- Create a
bfinject
folder in/jb
and change directory to it:
# mkdir /jb/bfinject && cd /jb/bfinject
- In a different terminal session, copy the .tar file to the device:
> scp -P 2222 bfinject.tar root@localhost:/jb/bfinject
Update: if you get the bash: scp: command not found
error, you'll need to execute /jb/makeMeAtHome.sh
before being able to use scp
. (Thanks @jackmccr for the heads up):
# cd /jb
# ./makeMeAtHome.sh
- Enter the root password and wait for the file to be transfered
- Extract the .tar file contents:
# tar xvf bfinject.tar
- Add the
/jb/bfinject
path toPATH
:
# export PATH=$PATH:/jb/bfinject:
- Optional: you can move or copy the
.dylib
libraries to/usr/local/lib
to be able to runbfinject
from any directory
From now on you can add/jb/bfinject
to the list of binpack paths. For more information aboutbfinject
visit their GitHub repo.
tl;dr of why we need to decrypt apps first
The app binary of an app downloaded from the App Store is encrypted using Apple's FairPlay DRM to protect the dev's intellectual property and avoid tampering.
Decrypt Starbucks iOS app using bfinject decrypt
- Download the Starbucks app from the App Store
- Run
itnl
to forward the ssh traffic to a different port (if you haven't already done so):
> itnl --lport 2222 --iport 22
- In a different terminal session SSH into the iDevice (if you haven't already done so):
> ssh -p 2222 root@localhost
- Enter the root password
- Change directories to
/private/var/containers/Bundle/Application
, this is the directory where iOS stores all the apps downloaded from the App Store:
# cd /private/var/containers/Bundle/Application
- Here you'll see a list of UUID folders, iOS generates a random UUID every time you download an app. If you have many applications installed, a quick hack to know which one is the last installed one is to sort the files by date:
# ls -lat
- Change directories to the very first UUID folder, in this case it should be the Starbucks app. You will see something like this:
- Take a note of the name of the
.app
bundle, in this case is justStarbucks.app
but other apps might have different names. This name is important becausebfinject decrypt
takes it as a parameter and will search for a bundle named exactly as your parameter
Side note
If you change directories to the Starbucks.app
, here you'll see all the files included with the Starbucks
app bundle. As you can see not a single file is encrypted. When Apple says they encrypt the app, they mean the actual binary not the assets and extra files. (Tip: sometimes you might get lucky and find some server configuration files or secret keys because some devs might not realize we can extract these files). Don't worry about transferring these files to your machine, you'll have access to them once we decrypt the app.
- On your iDevice, open the Starbucks app
- On your terminal type:
# bash bfinject -P Starbucks -L decrypt
If you didn't move/copy the .dylib
libraries to /usr/local/lib
you will need to change directories to /jb/bfinject
and execute the command from there.
- On your device you should see a pop up dialog like the following:
- Optional: Tap on
YES
and follow the instructions if you want to transfer the decrypted app usingNetCat
- I prefer using
scp
to transfer the decrypted app. The decrypted app will be stored in the/Documents
folder of the original app. The directory for theData
section of the iOS apps is/private/var/mobile/Containers/Data/Application/
. Change directories to theData
section:
# cd /var/mobile/Containers/Data/Application/
- Again, you'll see a list of UUID folders, you can sort by date again to get the latest modified folder, change directories to that UUID and then to the
Documents
folder, you should see adecrypted-app.ipa
file:
- In a different terminal session transfer the
decrypted-app.ipa
file to your machine:
> scp -P 2222 root@localhost:/var/mobile/Containers/Data/Application/{UUID}/Documents/decrypted-app.ipa decrypted-app.ipa
Update: if you get the bash: scp: command not found
error, you'll need to execute /jb/makeMeAtHome.sh
before being able to use scp
. (Thanks @jackmccr for the heads up):
# cd /jb
# ./makeMeAtHome.sh
- Optional: I don't like having files laying around, after transferring the
decrypted-app.ipa
to my machine, I usually delete it from the device:
# rm /var/mobile/Containers/Data/Application/{UUID}/Documents/decrypted-app.ipa
- On your machine, rename and change the file's extension to
Starbucks.zip
:
> mv decrypted-app.ipa Starbucks.zip
- Extract the .zip contents:
> unzip -a Starbucks.zip
- You should get a folder named
Payload
and inside a bundle calledStarbucks.app
, right-click on theStarbucks.app
bundle and selectShow Package Contents
, now you should see all the files contained in the Starbucks bundle, including the decrypted version of theStarbucks
binary, yay!
I know this is a lot of information and instructions, that's why I divided this post in two parts. Try repeat these steps with a few different apps to get familiar with the flow and the tools and next we'll get a sense of how to disassemble and dump the decrypted app's classes.
Note: The reason why I chose the Starbucks app is because they have a bug bounty program on HackerOne and their iOS app is in scope of that program, so if by following this tutorial you manage to find a vulnerability you get to report it to them.