Bypass Jailbreak Detection with Frida in iOS applications

In this blog post, we will have a look at Frida, which is one of the really interesting tools for mobile application security analysis.

This is also something we cover in-depth in our Advanced Android and iOS Exploitation training for which you can register here – Training Link

Even if you have never used Frida, this post will serve as a guide for you to get started into the world of Frida for Mobile application security analysis and exploitation.

Here’s what we are going to cover in this blog post:

  1. Introduction to Frida
  2. Setting it up on iOS
  3. Connecting to an iOS process using Frida
  4. Dumping class and method information
  5. Runtime manipulation of iOS apps using Frida
  6. Conclusion

Introduction to Frida

Frida is a dynamic code instrumentation toolkit allowing you to hook into applications, inject your own JavaScript while getting complete access to the memory and functions.

The tool is written by Ole André V. Ravnås (@oleavr) and also has a pretty active IRC channel where you can jump in to discuss ideas, questions and new features with other like minded people who have worked on Frida. You can join the IRC at #frida on irc.freenode.net .

Some of the use cases of Frida (depending on for which purpose you are using it) are –

  • Hooking into a specific function and changing the return value
  • Analysing custom protocols in place and sniffing/decrypting the traffic on the fly
  • Performing debugging of your own applications
  • Dumping class and method information from an iOS app
  • And so on.

The reason why I mentioned “and so on” is because Frida could be used for a number of different purposes. The API of Frida is what makes it so powerful and a first choice for building your own security or analysis tools. There have been several tools which are built on Frida including Needle and AppMon.

One of the other things which make Frida so useful is its ability to work on non-jailbroken devices. In order to run Frida to debug applications on non-jailbroken devices, you can use tools such as Swizzler2 which modifies the application to add the FridaGadget dylib  in the app.

Setting up Frida for iOS

Setting up Frida to perform iOS application security is fairly straightforward. You need to perform setup both on the iOS device as well as your host machine.

To install Frida server on your iOS device, follow the below steps.

  1. Open Cydia app on your iOS device.
  2. Add a Source with the URL being: https://build.frida.re

Adding source for Frida in Cydia

  1. Open up the Source or search for Frida, and click on Modify, then Install.

Installing Frida from Cydia

To install Frida’s Python bindings on your system, launch up your terminal and type in pip install frida to install Frida’s bindings.

Connecting to an iOS process using Frida

Now that we have Frida all set up, we are ready to start using Frida and start our iOS application security assessment and exploitation journey!

The target application in our case is the Damn Vulnerable iOS Application (DVIA) by Prateek Gianchandani, available from here. The credits for most of the scripts below go to Interference Security Github’s repo available here.

We are going to be analyzing the Jailbreak Detection exercise from DVIA, which currently shows that the device is Jailbroken.

Device is Jailbroken
Device is Jailbroken

Let’s start by seeing a list of all the running processes on our target device:

frida-ps –U

List of running processes

As you can see from the screenshot above, we now have a list of all the running processes on our iOS device.

To attach to any process, we could do a frida –U process-name  and we would now be in the frida console where we can access all the different properties, memory content and functions of our target process.

Attaching to an iOS process using Frida
Attaching to an iOS process using Frida

We can either work here in the Frida’s shell and interact with our process, or we can write our own JavaScript to obtain analyze the data that we want.

Dumping Class and Method Information

The goal for this exercise is to identify which ViewController and function are responsible for validating whether our device is jailbroken or not – in the Jailbreak Detection exercise of DVIA.

Let’s go ahead and write a basic Frida script to dump all the various classes and methods present in our target application. Here, we will be looking for anything related to Jailbreak, so that we are able to perform Jailbreak Bypass with the help of Frida.

Here’s how our process would look like

iOS application security process
iOS application security process

Finding Classes for Jailbreak Detection with Frida in DVIA

Let’s get started by identifying all the classes in the application.

for (var className in ObjC.classes){ 
    if (ObjC.classes.hasOwnProperty(className))         
        {console.log(className);} }

Once you run this, you’ll see that Frida is attaching to the target process (as shown below) and once it does, it will show you a ton of classes present in our target process.

Executing JavaScript with Frida on iOS
Executing JavaScript with Frida on iOS

It’s often better to grep for the expected class, which in our case would contain the word Jailbreak.

As we run the above command with a grep  for Jailbreak , we see that there is a class called JailbreakDetectionVC, as shown below.

Identifying target class of the iOS application with Frida
Identifying target class of the iOS application with Frida

After it has found all the instances, you might see an error statement which is safe to ignore.

So now that our first task of finding our target class is done, let’s go ahead and figure out any interesting methods from this class.

Finding Methods for Jailbreak Detection with Frida in DVIA

To find the methods, we would need to use ObjC.classes.class-name.$methods . We will also only look for methods of our target class, which in this case is JailbreakDetectionVC.

console.log("[*] Started: Find All Methods of a Specific Class"); 
if (ObjC.available) { 
    try { 
        var className = "JailbreakDetectionVC"; 
        var methods = eval('ObjC.classes.' + className + '.$methods'); 
        for (var i = 0; i < methods.length; i++) { 
            try { console.log("[-] "+methods[i]); } 
            catch(err) { console.log("[!] Exception1: " + err.message); } 
            } } 
        catch(err) { console.log("[!] Exception2: " + err.message); } } 
else { console.log("Objective-C Runtime is not available!"); } 
console.log("[*] Completed: Find All Methods of a Specific Class");

Let’s go ahead and run this, and also apply a grep for strings such as Jailbreak , Jailbroken  and Detection  as shown below.

Identifying target methods of an iOS application class with Frida
Identifying target methods of an iOS application class with Frida

We find that there are three methods which have one of our strings namely isJailbroken , jailbreakTest1Tapped:  and jailbreakTest2Tapped:.

In our case, isJailbroken looks like the most likely function for detecting whether the device is Jailbroken or not and sending a return value.

Modifying return values of Methods for Jailbreak Detection with Frida in DVIA

So let’s go ahead and see what kind of return value does isJailbroken  sends.


if (ObjC.available) { 

try { var className = "JailbreakDetectionVC"; 
var funcName = "- isJailbroken"; 
var hook = eval('ObjC.classes.' + className + '["' + funcName + '"]');

Interceptor.attach(hook.implementation, { 
    onLeave: function(retval) { console.log("[*] Class Name: " + className);
    console.log("[*] Method Name: " + funcName); 
    console.log("\t[-] Type of return value: " + typeof retval);
    console.log("\t[-] Return Value: " + retval); } }); } 
catch(err) { console.log("[!] Exception2: " + err.message); } } 

else { console.log("Objective-C Runtime is not available!"); }

Once you run this script, press the Jailbreak Test 1 in the iOS application and you’ll see the return value being shown in the Frida console.

Finding return value of target method
Finding return value of target method

Since our device is jailbroken, it shows a return value of 0x1, which simply means that the function is returning True .

Our next task is to overwrite this return value and patch the method, so that whenever the Jailbreak Test 1 button is pressed in the application, it returns false , or 0x0 .

Let’s just add another line to change the return value of this specific function.

This could be done by the following line of code which changes the return value as well as logs it to the console:

newretval = ptr("0x0"); 
retval.replace(newretval); 
console.log("\t[-] New Return Value: " + newretval);

This final script is given below.

if (ObjC.available) { 

try { 
var className = "JailbreakDetectionVC"; 
var funcName = "- isJailbroken"; 
var hook = eval('ObjC.classes.' + className + '["' + funcName + '"]');

Interceptor.attach(hook.implementation, { 
    onLeave: function(retval) { console.log("[*] Class Name: " + className); 
    console.log("[*] Method Name: " + funcName); 
    console.log("\t[-] Type of return value: " + typeof retval); 
    console.log("\t[-] Original Return Value: " + retval); 
    newretval = ptr("0x0") 
    retval.replace(newretval) 
    console.log("\t[-] New Return Value: " + newretval) } }); } 
catch(err) { console.log("[!] Exception2: " + err.message); } } 

else { console.log("Objective-C Runtime is not available!"); }

Once we run this, we see that the return value has been modified as shown below.

Patching function by modifying the return value in an iOS app - Jailbreak Detection bypass
Patching function by modifying the return value in an iOS app – Jailbreak Detection bypass

If you look in your iOS application now, it would say that the Device is not Jailbroken (as shown below).

Jailbreak Detection Bypass - Device is Not Jailbroken
Jailbreak Detection Bypass – Device is Not Jailbroken

Conclusion

That is all for this blog post. In the upcoming blog post, we will look more into Frida Scripting and how you could leverage Frida’s API and additional tools to perform iOS and Android application security assessment.



comments powered by Disqus
Tags
Android android application security android hands on security and exploitation training android security Apktool application auditing application security auditing appsec usa appwatch attify attify badge attify training binwalk blackberry pentesting blackhat ble BLE hacking and exploitation BLE sniffing box brut Exception chroot cloud based mobile application security scanner consulting CTF Damn Vulnerable iOS App devops dumping memory embedded hacking exploitation exploiting smart devices Firmware hacking frida hackfest hacking smart devices how to secure iot device IDA internet of things Internet of Things Security ios application security ios security iot iot device IoT Exploitation iot hacking iot pentest iot pentesting iot security iot security training iotsecurity jtag jtag debugging mobile app mobile application security mobile application security testing mobile security ninja recon technique offensive iot exploitation ola cabs owasp owasp appsec penetration testing pentesting pentesting mobile apps powerofcommunity PrinterSecurity qemu quizup radio communication protocol radio coomunication Reversing sdr secure coding guidelines security security issue security services security training security vulnerability smart devices social networking spi threat modeling training uart vulnerability writeups xposed hooking zigbee zigbee exploitation zigbee security zwave firmware reverse engineering firmware emulation firmware analysis toolkit firmadyne getting started with firmware hacking iot penetration testing iot attacks recent iot attacks cyber attacks iot hacks biggest iot attacks of all time hacked smart devices iot bots, malwares latest iot attacks BtleJuice bleah

Instagram