首页
社区
课程
招聘
[翻译]Object-C测试工具与Frida 译者:lockdown(看雪ID:小调调)
2016-11-29 09:18 6992

[翻译]Object-C测试工具与Frida 译者:lockdown(看雪ID:小调调)

2016-11-29 09:18
6992

原文链接:https://rotlogix.com/2016/03/20/objective-c-instrumentation-with-frida/

原文作者:Rotlogix

译者:lockdown(看雪ID:小调调)

搬运工:草莓丶(看雪ID:ksmokee)

微信公众号:看雪iOS安全小组

我们的微博:http://weibo.com/pediyiosteam


加入我们:看雪iOS安全小组成员募集中:http://bbs.pediy.com/showthread.php?t=212949

Overview
一个朋友最近在问怎么使用Frida来测试Objective-C的应用程序,我将这个过程分享给大家,这个简要的教程阐述了我是如何教他一步一步做到的。
Frida是一个非常强大的跨平台测试工具。对于那些不熟悉Frida是什么、能做什么的人,我强烈建议在开始这个教程之前,先去下面的网页查看一下。

http://www.frida.re/

在本教程中,我们将使用Frida在一个非常简单的Objective-C应用中,拦截一个方法(函数)。我们将使用Frida的Python通用接口来实现。

Objective-C Application

我们的Objective-C程序中有一个类叫Hook和一个实例化方法叫hookMe。该实例化方法有一个参数,并通过NSLog打印输出。

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


在应用程序的main函数中,我们创建一个新的Hook实例,然后调用hookMe。
Hook *hook = [[Hook alloc]init];
[hook hookMe:@"Hello, World!"];


我们的目标是编写一个脚本,它将拦截hookMe并打印出其参数内容以及一些附加信息。

Hook.py
想要阅读完整的脚本,你可以在这里查看这里
在本教程中,我们仅关注注入到我们的目标进程中的JavaScript代码。我更倾向于对所有的Frida Python脚本使用相同的框架代码,所以你可以根据需要复制粘贴,并根据自己的需求添加自己所需要的功能。

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


如果你查看Frida的文档中对Objective-C的支持,你会看到ObjC.classes返回当前注册类的映射表。 这些类可以很容易地通过for循环遍历,并且应该允许我们查找我们的目标类Hook。
它不包括在脚本中,但是可以使用以下的方式执行访问方法。

ObjC.classes.Hook.$methods;  


你可以使用特殊属性 $methods访问对象公开的方法数组。这将包括hookMe方法以及通过继承可用的任何其他方法。

事情从这里开始变的有趣了。

if(ObjC.available) {
    for(var className in ObjC.classes) {
        if (ObjC.classes.hasOwnProperty(className)) {
            if(className == "Hook") {
                send("Found our target class : " + className);
            }
        }
    }
    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!");
}


首先,我们创建一个包含我们要拦截的方法的新变量。

在Objective-C中 “-“ 是描述实例方法的语法。如果你遍历$methods特殊属性返回的所有方法,你将看到hookMe以这种方式展现出来。
Objective-C运行时将所有方法调用转换为objc_msgSend调用。objc_msgSend函数声明如下:

id objc_msgSend(id self, SEL op, args);


当我们拦截的方法被 Objective-C 运行时调用时,Frida通过拦截方法的参数提供对底层objc_msgSend函数的访问接口。

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());  


第一个参数是一个指针,指向接收消息的实例类。在我们的例子中它指向 Hook 。 您还可以通过Frida还提供的$ superClass特殊属性访问对象的超类。
objc_msgSend声明中的第二个参数是SEL,它本质上是一个包含调用方法名的CString(selector)。你可以使用Frida的selectorAsString JavaScript函数将其转换并将其发送回您的Python代码。

我们可以访问传递给args [2]中的hookMe方法的参数,并从中创建一个新的ObjC.Object。 Frida对对象的处理允许我们简单地调用toString以获得参数的值。
下面是我们的hook.py脚本的最终输出:


Conclusion

我希望这些信息对你有帮助。再次,你可以仔细阅读整个脚本。我强烈建议深入了解Frida的文档和frida-gum,以更熟悉Frida。

References

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

阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!

上传的附件:
收藏
点赞1
打赏
分享
最新回复 (2)
雪    币: 949
活跃值: (119)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
starbuck 1 2016-12-4 21:26
2
0
刚接触frida不久,前排支持
雪    币: 27
活跃值: (90)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
caihaonan 2016-12-20 15:14
3
0
学习了,感觉frida还是很强大的
游客
登录 | 注册 方可回帖
返回