Trelis Blog My Staff

Frida iOS

2019-08-09
Trelis
iOS

How to use Frida in iOS devices: command line, Frida Gadget and scripts (JavaScript and Python).

Frida

It’s a dynamic code instrumentation toolkit. It lets you inject snippets of JavaScript or your own library into native apps on Windows, macOS, GNU/Linux, iOS, Android, and QNX. Frida also provides you with some simple tools built on top of the Frida API. These can be used as-is, tweaked to your needs, or serve as examples of how to use the API.

Commands (via USB)

Show all the applications of the device

frida-ps -Uai

Starts the Frida Gadget

frida -U APP_NAME

Script injection

frida -U -l SCRIPT.js APP_NAME

Tracing native APIs (partial method name with wildcards allowed)

frida-trace -U APP_NAME -i "METHOD_NAME"$

Tracing Objective-C metods (partial method and class name with wildcards allowed)

$ frida-trace -U APP_NAME -m "-[CLASS_NAME METHOD_NAME]"

Execute Objective-C commands from terminal

frida -q -U APP_NAME -e "COMMAND"

JavaScript API

Get instance object

var instance = ObjC.chooseSync(ObjC.classes.CLASS_NAME)[0];

Call method

instance.METHOD_NAME();

Dump the entire view hierarchy of a window

w = ObjC.classes.UIWindow.keyWindow()
desc = w.recursiveDescription().toString()

Application installation path

ObjC.classes[CLASS_NAME].$moduleName;

Class methods

ObjC.classes[CLASS_NAME].$ownMethods;

Mapping each instance variable name to its current value

ObjC.classes[CLASS_NAME].$ivars;

Javascript

Call method (inside onEnter or onLeave)

var obj = new ObjC.Object(arg[0]);
obj.METHOD_NAME();

Print class and method

this._className = ObjC.Object(args[0]).toString();
this._methodName = ObjC.selectorAsString(args[1]);
console.log('Detected call to:');
console.log('   ' + this._className + ' --> ' + this._methodName);

Modify return value

returnValue.replace(ptr(NEW_VALUE));

Scripts

The following scripts can be found in my Github Trelis24

start_frida.py

Python script that given a script and a app bundle, it starts the app, inject de script and resume the execution.

find_classes.js

Search for classes

  • If no strings are specified in “search_class” array, the script will print all the classes.
  • If one or more strings are specified in “search_class array”, the script will only print classes which contains the strings in their name.

find_methods.js

Search for methods

  • If no strings are specified in “search_class” nor “search_method” arrays, the script will print the methods of all the classes (frida server might stop running if there are a lot of classes).
  • If one or more strings are specified in “search_class array”, the script will print the methods of the classes which contains the strings in their name.
  • If one or more strings are specified in “search_method” array, the script will print the classes which contains the strings in the name of one or more of their methods.
  • If one or more strings are specified in “search_method” and “search_class” array, the script will print only the classes and methods that meet with the search criteria.

hooking.js

Hooks into methods

  • Given one or more classes in “search_class”, it hooks into all their methods.
  • Given one or more methods in “search_method”, it hooks into all methods of any classes that meet with the search criteria.
  • Given a class and a method, it hooks into the method of this class.
  • Neither class nor method full name is needed in order to hook. If a partial string is given, the script will hook into all the methods that have the string in their name.

replace.js

Replace methods return values

  • Given an especific class, method and value it replaces the return value of the method.
  • Method format: for example: “- isJailbroken:”
  • Data must be in the same array position (classNmes, methodNames, returnValues). For example: [‘class1’,’class2’][‘method1’,’method2’][‘retvalue1’,’retvalue2’]
  • If returnValues of a method is left empty, the method will be hooken but the script will not modify the return value.

PoC

In this section, I will use DVIA iOS application in order to show how can frida and my scripts be used. Specifically I will analise jailbreak detection test 1. The objective is to bypass the jailbreak detection control.

Commands

List applications. The ones with a PID are currently active:

With frida-trace, hooking into all methods whose name has the substring “jail”:

With frida-trace, hooking into all methods of the class JailbreakDetectionVC:

With frida-trace, hooking into an specific method an class:

In order to detect which methods are called, one way is to hook into all methods of a class. In the following image you can see how the view was loaded first and then the method “jailbreakTest1Tapped:” and “isJailbroken” are called:

Of course, in the device the following message is shown:

Scripts

Due to the jailbreak detection control only shows an alert text box and it does not terminate the application execution, I will execute the scripts via terminal. Otherwise, I would have used the python script in order to inject the scripts before the applications terminates.

Find classes

First of all, you should look for classes of your interest. In this example, I have looked for the string “jail” (find_classes.js):

var search_class = ['jail'];

The only class with the substring “jail” is “JailbreakDetectionVC”:

Find methods

An other way to find classes is to look into their methods. The only drawback is that depending of the string, a lot of results can be found. I have looked for the string “jail” in the methods (find_methods.js):

var search_class = [''];
var search_method = ['jail'];

The class “JailbreakDetectionVC” is in the list, however there are a lot more classes I am not interested in:

Now that I have detected the class, let’s print all its methods (find_methods.js):

var search_class = ['JailbreakDetectionVC'];
var search_method = [''];

There are a total of 7 methods:

Hooking

Now that I know the class, I can hook into the methods in order to understand how are they called (hooking.js):

var search_class = ['JailbreakDetectionVC'];
var search_method = [''];
...
	onEnter:
	...
	//print_arguments(args);

In the code below, I have commented the line “print_arguments(args);”, which prints the arguments send into the methods, because it prints information not needed for this example.

After the script execution, it shows:

  1. Calls “jailbreakTest1Tapped:”
  2. Calls “isJailbroken”
  3. “isJailbroken” returns 0x1
  4. “jailbreakTest1Tapped:” returns 0x1035a9d10

I can deduce that “isJailbroken” might be de method which checks if the device is jailbroken due to it returns a “false”. However, if you want to be sure, static analysis can always be done. Check my post about bypassing Jailbreak with IDA.

Replace

Finally, I will try to replace the return value of “isJailbroken” so it always returns “false” (replace.js):

var classNames = ['JailbreakDetectionVC'];
var methodNames = ['- isJailbroken'];
var returnValues = ['0x0'];

The script hooks into the method. When isJailbroken returns the 0x1, frida intercepts it, changes the value to 0x0 and resume the execution:

After changing the return value from 0x1 to 0x0, the alert textbox is:


Similar Posts

Content