神刀安全网

Objective-C Instrumentation with Frida

Overview

A friend recently asked for help with using Frida to instrument applications written in Objective-C, so I thought I would shared the brief tutorial I walked him through.

Fridais a very powerful cross-platform instrumentation toolkit. For those who are not familiar with what Frida is and what it can do, I would highly suggest checking it out before continuing.

http://www.frida.re/

In this tutorial will we be using Frida to intercept a method in a very simple Objective-C application. Our implementation will be written using Frida’s Python bindings.

Objective-C Application

Our Objective-C application consists of a single class called Hook and a single instance method called hookMe . Our target method takes a single argument and passes it to NSLog .

-(void)hookMe:(NSString *)arg {      NSLog(@"%@", arg); } 

Inside of the application’s main , we create a new instance of Hook , then call hookMe as so.

Hook *hook = [[Hook alloc]init];  [hook hookMe:@"Hello, World!"]; 

Our goal is write a script that will intercept hookMe and print out its single argument contents with some additional information.

hook.py

To read over the entire script you can check it out here . In this tutorial we will only focusing on the JavaScript that is injected into our target process. I tend to use the same skeleton code for all of my Frida Python scripts, so you can copy paste as needed and dive into its functionality later on your own.

for(var className in ObjC.classes) {               if (ObjC.classes.hasOwnProperty(className)) {                 if(className == "Hook") {                     send("Found our target class : " + className);                 }             }         } 

If you check out the Frida’s documentation on its support for Objective-C, you will see that ObjC.classes returns mappings for currently registered classes. These classes can easily be iterated through with a for loop and should allow us to look up our target class Hook .

It is not included in the script, but accessing methods can be performed in a similar fashion.

ObjC.classes.Hook.$methods;   

You can use the special property $methods to access an array of methods exposed by the object. This will include the hookMe method as well as any other methods available through inheritance.

Here is where the fun begins.

var hook = ObjC.classes.Hook["- hookMe:"];           Interceptor.attach(hook.implementation, {             onEnter: function(args) {                  var receiver = new ObjC.Object(args[0]);                 send("Target class : " + receiver);                 send("Target superclass : " + receiver.$superClass);                  var sel = ObjC.selectorAsString(args[1]);                 send("Hooked the target method : " + sel);                  var obj = ObjC.Object(args[2]);                 send("Argument : " + obj.toString());             }         });     } else {         console.log("Objective-C Runtime is not available!");     } 

First we create a new variable containing the method we want to intercept.

var hook = ObjC.classes.Hook["- hookMe:"];   

In Objective-C the - is the syntax to describe an instance method. If you were to iterate through all the methods returned from $methods special property, you will see hookMe displayed in the exact format.

The Objective-C runtime converts all method invocations into objc_msgSend calls. The objc_msgSend function declaration is as such.

id objc_msgSend(id self, SEL op, args)   

When intercepting a method invoked in the Objective-C runtime, Frida provides access to the underlying objc_msgSend function through the intercepted method’s arguments.

var receiver = new ObjC.Object(args[0]);   send("Target class : " + receiver);   send("Target superclass : " + receiver.$superClass);  var sel = ObjC.selectorAsString(args[1]);   send("Hooked the target method : " + sel);  var obj = ObjC.Object(args[2]);   send("Argument : " + obj.toString());   

The first argument is a pointer to the instance class that is to receive the message. In our case that would be Hook . You can also access the object’s super class through the $superClass special property that Frida also provides.

The second argument in the objc_msgSend declaration is the SEL , which is essentially a CString that contains the method name for invoking. You can use Frida’s selectorAsString JavaScript function to convert this and send it back to your Python code.

We can access the argument passed to the hookMe method in args[2] and create a new ObjC.Object from it. Frida’s handling of the object allows us to simply call toString in order get the argument’s value.

Here is the final output of our hook.py script:

Objective-C Instrumentation with Frida

Conclusion

I hope this was helpful and informative. Again, you can checkout the entire script here . I would highly suggest diving into Frida’s documentation and frida-gum itself to more acquainted with the power of Frida .

References

https://github.com/frida/frida-gum/blob/master/bindings/gumjs/gumjs-objc.js

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Objective-C Instrumentation with Frida

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
分享按钮