How to Reverse Engineer and Patch an iOS Application for Beginners: Part I
So you want to reverse and patch an iOS application? I got you >_<
If you’ve missed the blogs in the series, check them out below ^_^
Part 1: How to Reverse Engineer and Patch an iOS Application for Beginners
Part 2: Guide to Reversing and Exploiting iOS binaries: ARM64 ROP Chains
Part 3: Heap Overflows on iOS ARM64: Heap Spraying, Use-After-Free
This blog is focused on reversing an iOS application I built for the purpose of showing beginners how to reverse and patch an iOS app. No fancy tools are required (IDA O.o), it's just you, me & a debugger <3
The app is a simple, unencrypted Objective-C application that just takes in a password and the goal of this is to bypass the password mechanism and get the success code. This blog post will focus on reversing/debugging the application and will not cover aspects of static analysis. The reason I wanted to write this is because I realised this topic is confusing for a lot of people and I wanted to try and write a blog that attempts to explain it in a more beginner-friendly way.
Originally, I planned this content to be a TikTok video, but I am sick of TikTok’s community guidelines and rules against any “offensive” security content. So… as a result, I’m probably going to be writing more blogs now.
The screenshot below shows you what my cute app looks like – it is called “breakmedaddy” and the left shows you attempting to put in passwords – and the right shows you the desired bypass screen.
Why did I build this in Objective-C and not Swift? Because your girl is a qt and a masochist :)! But also because Objective-C allows you to modify methods during run time which means it’s easier to hook into functions than if the app was built in Swift.
If you want to follow along with this blog post, the app is available on my GitHub (the first thing I’ve ever uploaded publicly because I am shy >_<):
To make this as easy to understand as possible, I have broken the blog into three parts so you can skip to whatever part you are interested in:
- High level steps we will take (this is to demonstrate the logic behind how to perform something like this)
- Tools we will use for the analysis
- Reverse engineering and patching the application
This is the logic we are going to follow in this tutorial:
- Jailbreak an iOS device (I am using an old phone I had around which is running iOS 14.1).
- Upload the application onto the jailbroken device via SSH and SFTP by unzipping the IPA file into the /Applications directory.
- Restart Springboard (you can do this via CLI through SSH or through Respring which you can find in Cydia).
- Open the application and keep it in the foreground with your phone unlocked
- Using SSH find the PID of the application.
- Hook into the running app process by using Cycript to allow you to look at instances from the runtime.
- Use otool to review libraries present in the application.
- Use pagestuff to review the structure of a Mach-o file (this will show you segments, headers, code signatures, symbol tables etc).
- Locate any interesting method names and variable names.
- Reverse and debug the Mach-O file through running debugserver on the iOS device and connecting to the running application process via LLDB.
TOOLS WE'LL USE
There are a lot of tools you can use to perform this, however, for the purpose of keeping this walkthrough lean, here are the analysis tools we will use:
- Otool Command – https://www.unix.com/man-page/osx/1/otool/
- Pagestuff Command - https://www.unix.com/man-page/osx/1/pagestuff/
- Cycript - http://www.cycript.org/
- LLDB - https://lldb.llvm.org/
REVERSE ENGINEERING IOS GUIDE
Step 1: Jailbreak an iOS device and set up SSH,SFTP
I am not going to cover how to jailbreak a device as there are plenty of write-ups and videos about it. The phone I tested this on and built the application for was running iOS 14.1 and I used the unc0ver jailbreak here: https://unc0ver.dev/. The website for unc0ver explains in detail how to perform the jailbreak :)
Once the jailbreak is completed, go into Cydia and set up SSH. This is as simple as performing a search for “openssh” and installing it.
Step 2: Upload the application onto the jailbroken device via SFTP and unzip it into the Applications directory
The result is something like this:
Step 3: Check that the application is loaded and functioning
- Can we manipulate any interesting methods/functions
- Are there any interesting variables we should take notes on
- File headers
- Symbol tables
- Code signatures
- a pointer to the instance of the class that receives the message
- selector of the method that handles the message
- an argument list that contains the arguments to the method
- $x0 – The password we put into the application “isthmus the password :)"
- $x1 – A call to the method “isEqualToString” where a comparison is going to be made between the strings stored in x0 and x2
- $x2 – The actual password that the program is expecting “babiesareevil”