Chaining Vulnerabilities of an iOS App — Reverse Engineering Made Easy | by Vishal Singh | Jun, 2022

Know how an application works under the hood

Photo by Windows on Unsplash

We will look at how iOS application vulnerabilities can be chained together to get an insight into how the application works and move towards gathering knowledge that will help us create a working tweak/exploit to modify the application’s runtime behavior.

Let’s get started! First things first, let’s install the necessary tools that we will be using during our exploitation.

Note: I’m using macOS and a physical iOS Device.

iDevice (iPhone/iPad): If you already have a Jailbroken device, that’s perfect. If not, you can use the guide here to see various options for your device and version of iOS.

Once Jailbroken, install the following tools onto your device for easy administration and debugging:

  • OpenSSH — Useful for SSH access over Wi-Fi.
  • Filza FileManager — Useful for viewing the filesystem.
  • Frida — Used to inject code at application runtime. Instructions here.
  • Cephei Tweak Support — A framework for jailbroken iOS devices that includes various convenience features for developers.
  • RocketBootstrap — A library that solves a denied lookup error of IPC services on iOS 7 and above.
  • PreferenceLoader — Settings view for tweaks.
  • Theos — Used for building Tweaks. Instructions on installation are available here.
  • Objection: A runtime exploration toolkit built on top of Frida. You can find instructions on installing it here.
  • Sideloadly: A good alternative to Cydia Impactor to install application (IPA file) onto the device. Can be used to install jailbreak/target application.
  • Frida-iOS-Dump: App Store applications are encrypted by default ie, the executable section of the Mach-O binary inside the IPA package is encrypted. Since it is decrypted at runtime, we can use the tool available here to pull the decrypted sections from a Jailbroken device.
  • class-dump-swift: In order to be able to get a peek into the abstracted code implementation and to support our tweak that we will be building later on, we need to dump the class and header files from the app binary. We will use class-dump-swift in order to do that since most of the modern iOS applications are written using swift.
  • DVIav2: This will be our target application for the purposes of demonstration and is an intentionally vulnerable iOS application available here.

Note: We will be using the swift version for this exercise as most of the modern applications are built using swift.

Once we have all the requirements listed above, we can start with the process. Let’s begin by installing the application onto our device.

Open Sideloadly and select the DVIAv2 IPA file that was downloaded earlier by clicking on the IPA image on the left. Make sure to select the correct device in case you have multiple devices connected to your machine and click on ‘Start‘ once you’re ready.

Once, the status at the bottom completed of the tool changes to Done from Idle.
Note: The application requires you to sign in using your Apple ID first in case you haven’t used it before

The application was installed successfully as can be seen in the image below.

If you’re having trouble opening the application, just acknowledge and accept the certificate that was used to install the application (General -> Profiles & Device Management -> Developer App)

Let’s list all the applications installed on the device. We’ll use Frida for this task. Make sure your iPhone is connected to your computer using USB since the -U parameter instructs Frida to use the device attached via USB.

Once we have the bundle identifier for our target application (com.highaltitude.DVIAswiftv2) in our case for DVIA-v2we can use Frida-iOS-Dump to dump the decrypted application contents onto our system.

The tool takes some standard options as input such as the host Ip address (-H), the port (-p), username (-u), password (-P), the bundle identifier and the output file name (-o) . The final command for me looks something like below:

python3 ../frida-ios-dump/dump.py -H 192.168.1.17 -p 22 -u root -P alpine -o DVIAv2 com.highaltitudehacks.DVIAswiftv2

Once the program completes execution, you should see something like below on your screen.

We can verify that the decrypted IPA has been saved onto the disk by listing the current directory.

Once we have the IPA file, we can then extract contents of the file using the unzip command, since an IPA package is similar to a zip file.

This should give you a new folder called Payload in your current working directory.

The new folder Payload contains all of the necessary static files and resources that the application needs to run on a device along with the executable marked by a pointer as can be seen below.

The next step is to extract header and class information from the application’s executable file. The header and class files help in identifying the functions and methods available within different sections (aka Views) of the application. The header files are also required by Theos in order to create a tweak as we’ll see later.

To dump the header files from the executable, run the following command:

class-dump-swift -H -o Headers/ Payload/DVIA-v2.app/DVIA-v2

While there may be a couple of warnings on your screen but once the execution completes, you should have the header files from the executable saved into the Headers/ folder.

Now here’s the interesting bit, if you open the Headers folder in current directory under Finder, you’ll notice that the header files contain common names such as HomeViewController, DonateViewController, PhishingViewController, etc.

The names in itself are sometimes self-explanatory as to what the code within the application must be responsible for. For example, we can see a Donate section within the application in screenshot below, which is most probably controlled via the DonateViewController class.

Let’s target the DonateViewController as an example.

Looking at the code within the file DonateViewController.hwe identify several methods such as menuTapped, viewWillAppear and viewDidLoad that do not return anything upon execution, indicated by -> (void). The name of the class is _TtC7DVIA_v220DonateViewController and inherits from the class UIViewController

Now, we need to find out when and how will our desired ViewController be loaded and function is called. We will use Objection to figure out this answer for us.
We first need to attach objection into the application running on our device. we can do that by first identifying the Process ID of the running application using the command:

frida-ps -Ua

And then instructing objection to attach to our running process using the command below and supplying the Process Identifier.

objection -g 2709 explore

If hooked successfully, you should be able to see something like below on your screen.

we’ll now instruct objection to trace all calls to the DonateViewController class using below command:

ios hooking watch class _TtC7DVIA_v220DonateViewController

As we can see from the screenshot above, all methods within the DonateViewController are now being monitored by objection. Now as soon as we click on the “Donate- The Juniper Fund” menu item is clicked, it should trigger events within the objection CLI.

The Donate List Item

The screenshot above confirms that the methods viewDidLoad and viewWillAppear are triggered as soon as the page loads.

The above trick can be used to identify which function is triggered in the code in response to an event like selecting a particular label, clicking on a certain area or entering some information on the application’s screen.

We can now use this information to build a working tweak for our target application DVIA-v2 using Theos.

Let’s first look at the list of iOS-specific vulnerabilities encountered in the app so far:

1. No Jailbreak Detection
2. No Runtime Manipulation Protection
3. Source code Not Obfuscated

In their entirety, all of the above findings would have been rated as Low in most security assessments, but we will combine the knowledge from above identified weaknesses to control the application’s behavior at runtime.

We now need to copy all the header files into the /var/theos/include folder on our iPhone. We can use the following command to do so recursively:

scp -r Headers/ root@192.168.1.15:/var/root/theos/include/DVIA-v2/

We now need to ssh into our iPhone and instantiate a new project using the New Instance Creator provided by Theos library. We invoke the nic.pl script by providing its absolute path and choose option 17 from the list as we want to create a Tweak for iPhone.

The instance creator also requests some additional information such as the project name, the maintainer, and the bundle identifier for the application we want to create a tweak for, com.highaltitudehacks.DVIAswiftv2 in our case.

Once the basic information is provided, we can see that a new folder with several files has been created in the current working directory.

The file Tweak.x is the heart of this project, and contains the actual code that will be executed. DVIAv2.plist contains the bundle identifier for the target application, that the tweak will attach to.

The Makefile contains the configuration information for the build operation, and is shown below.

We need to update the Makefile to point it to our THEOS installation and add the architecture for our device using the ARCH directive as shown below:

The file Tweak.x is where all our additional code will reside and initially contains some sample code as shown below

We will delete all of the above data from the file and update the contents of the file to below

The first two lines of the code include some necessary foundation classes that contains methods that are required by our Tweak to show a message on the screen.

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

We then declare the class that we want to Tweak to attach to using the @interface attribute.

All our additional code resides under the %hook … %end block. Here, we’re instructing the tweak again to hook to the DonateViewController class’s viewDidLoad function and show an alert. The alert is instantiated by the UIAlertController* class and was made available by the import statements at the beginning of the code.

The %orig; statement within the code ensures that the viewDidLoad functions original content is also executed along with the additional statements that were specified. If you want to override the function’s behavior, you can remove the %orig; directive from the code but since I still want the function to run its intended code, i’ll keep it.

After saving the file, we need need to issue make command from within the folder, which will create a .deb package and can be installed onto the device.

make package

If all goes well, you should be able to see a .deb package that was created by the make command.

We can now install the package via the debian package manager (dpkg) onto the device locally or host it via a Cydia based repository. We’ll take the simple path for now and install the debian package locally onto our device using the command:

dpkg -i packages/com.vishal.dvia-v2_0.0.1–1+debug_iphoneos-arm.deb

We can see that the package was successfully installed from the screenshot above.

In order to ensure that the package loads successfully, it is recommended to run the tool uicache, which clears all application data including PreferenceLoader and Cydia information. We can ensure a complete cache cleanup with the command:

uicache -afr

We should also be able to see our tweak in the installed section of our package manager Cydia/Sileo.

Now, when we open the application and browse to the Donate section of the application via the side menu, we should be able to see an alert with the Title “This is an Alert!” containing the message “This is from the Tweak!”.

The above tweak is a good example of how powerful a tweak can be!
One can modify the code in file Tweak.x to do some adverse functions like collecting and sending data into the text fields of the ViewControllerPrompt the user for authentication information and then send this information to an attacker-controlled server.

The possibilities are endless!

While this can be distributed via Cydia repositories, an application can also be repackaged and signed in a similar fashion as using the patchipa function of objection to include the dylib (dynamic library). Which would then allow the tweak to modify the application’s runtime behavior even on non-jailbroken devices.

Note: Be careful while installing applications/tweaks from third-party sources and app stores.

Hope you liked it!

Want to Connect?Please feel free to message me on LinkedIn for any feedback/general security discussions :)

Leave a Comment