[原创] 【frida 实战】远程过程调用(rpc) | 宜武汇-ag真人国际厅网站

本文是 frida 实战系列教程的第五篇,讲解远程过程调用(rpc)的使用方法,也就是将应用进程中的 objective-c 方法或 c 函数导出,提供给 python 使用。

 

远程过程调用(rpc)对于应用逆向起到了很便捷的作用,比如目标应用有一个加解密的函数内部实现非常复杂,想分析整个加解密的实现过程的工作量较大,此时可以使用 frida 的 rpc 功能,只要知道加解密函数的名称或地址,还有相应的参数,即可直接调用得到加解密后的结果。

 

下面我们来做一个实例,编写一个 crackme 程序,定义一个 coreclass 类,里面有 4 个比较重要的方法,分别是 getdeviceid、httppost、encrypt、decrypt,从它们的名称可以看出大概的意思,具体的定义如下:

@interface coreclass : nsobject @end @implementation coreclass - (nsstring*)getdeviceid{ return @"e10adc3949ba59abbe56e057f20f883e"; }  (nsstring*)httppost:(nsstring*)url{ nslog(@"url: %@", url); return @"test"; } - (nsstring*)encrypt:(nsdata*)data :(nsstring*)key{ nslog(@"data: %@", data); nslog(@"key: %@", key); return @"encrypt successed!"; } - (nsstring*)decrypt:(nsstring*)str :(nsstring*)key{ nslog(@"str: %@", str); nslog(@"key: %@", key); return @"decrypt successed!"; } @end 

下面我们要做的事情是在 js 脚本里去调用这 4 个方法。objective-c 方法有两种,一种是 – 号开头,称为对象方法,还有一种是 号开头,称为类方法,前者需要初始化一个实例才能调用,后者不需要初始化实例,可以直接调用。先来看看对象方法在 js 脚本里如何调用,比如我们要调用 -[coreclass getdeviceid] 方法,调用的代码如下:

var coreclass = objc.classes.coreclass.alloc(); var deviceid = coreclass['- getdeviceid'].call(coreclass); console.log("deviceid: "   deviceid.tostring()); 
var coreclass = objc.classes.coreclass; var url = objc.classes.nsurl.urlwithstring_("http://www.ioshacker.net"); var retstring = coreclass.httppost_(url); console.log("retstring: "   retstring); 

-[coreclass encrypt::] 的调用代码如下,输入的参数有两个,一个参数是 nsdata 类型的,一个是 nsstring 类型。

var coreclass = objc.classes.coreclass.alloc(); var str = objc.classes.nsstring.stringwithstring_("test"); //nsdata *data = [@"data" datausingencoding:nsutf8stringencoding]; var data = str.datausingencoding_(4); var key = objc.classes.nsstring.stringwithstring_("key"); var encryptstring = coreclass['- encrypt::'].call(coreclass, data, key); console.log("encryptstring: "   encryptstring); 

-[coreclass decrypt::] 的调用代码如下,两个参数都是 nsstring 类型。

var coreclass = objc.classes.coreclass.alloc(); var str = objc.classes.nsstring.stringwithstring_("test"); var key = objc.classes.nsstring.stringwithstring_("key"); var decryptstring = coreclass['- decrypt::'].call(coreclass, str, key); console.log("decryptstring: "   decryptstring); 

在上面我们已经学会如何在 js 脚本里调用目标应用的 objective-c 方法,接下面要做的就是将功能代码导出提供给 python 使用。在 js 代码里定义4个函数,分别是 getdeviceid、httppost、encrypt、decrypt,这 4 个函数分别代表了调用目标进程的 4 个 objective-c 方法,然后再使用 rpc.exports 将这 4 个函数导出,代码如下:

function getdeviceid(){ var coreclass = objc.classes.coreclass.alloc(); var deviceid = coreclass['- getdeviceid'].call(coreclass); console.log("deviceid: "   deviceid.tostring()); console.log("--------------------"); } function httppost(inputurl){ var coreclass = objc.classes.coreclass; var url = objc.classes.nsurl.urlwithstring_(inputurl); var retstring = coreclass.httppost_(url); console.log("retstring: "   retstring); console.log("--------------------"); } function encrypt(inputstr, inputkey){ var coreclass = objc.classes.coreclass.alloc(); var str = objc.classes.nsstring.stringwithstring_(inputstr); //nsdata *data = [@"data" datausingencoding:nsutf8stringencoding]; var data = str.datausingencoding_(4); var key = objc.classes.nsstring.stringwithstring_(inputkey); var encryptstring = coreclass['- encrypt::'].call(coreclass, data, key); console.log("encryptstring: "   encryptstring); console.log("--------------------"); } function decrypt(inputstr, inputkey){ var coreclass = objc.classes.coreclass.alloc(); var str = objc.classes.nsstring.stringwithstring_(inputstr); var key = objc.classes.nsstring.stringwithstring_(inputkey); var decryptstring = coreclass['- decrypt::'].call(coreclass, str, key); console.log("decryptstring: "   decryptstring); console.log("--------------------"); } //getdeviceid(); //httppost("http://www.ioshacker.net"); //encrypt("123", "456"); //decrypt("123", "456"); // 导出rpc函数 rpc.exports = { deviceid: function () { getdeviceid(); }, httppost: function(urlstr) { httppost(urlstr); }, encrypt: function (inputstr, inputkey) { encrypt(inputstr, inputkey); }, decrypt: function(inputstr, inputkey) { decrypt(inputstr, inputkey); }, }; 

接着我们再编写 python 代码,首先调用 get_usb_device().attach 附加到目标进程,附加成功会返回一个 session 实例,然后读取 call.js 文件里的内容,这里的内容就是上面我们编写的 js 代码,然后调用 session.create_script 创建脚本,再调用 load 加载脚本,最后调用 script.exports 获取 js 导出的 rpc 函数,此时就可以调用 rpc 函数,代码如下:

# -*- coding: utf-8 -*- import codecs import frida if __name__ == '__main__': #附加到目标进程 session = frida.get_usb_device().attach(u'crackme') #读取js脚本 with codecs.open('./call.js', 'r', 'utf-8') as f: source = f.read() script = session.create_script(source) script.load() rpc = script.exports #调用导出的函数 rpc.deviceid() rpc.httppost("http://www.ioshacker.net") rpc.encrypt("123", "456") rpc.decrypt("123", "456") session.detach() 

上面我们讲到了如何将 objective-c 方法导出给 python 使用,那如何导出 c 函数呢?比如调用 nshomedirectory 这个系统提供的函数,知道它所在的模块是 foundation,找到它的地址在 js 脚本里就可以调用,然后在 rpc.exports 里添加一个导出函数,这样 python 就可以调用了。代码如下:

function gethomedir(){ var nshomedirectory = new nativefunction(ptr(module.findexportbyname("foundation", "nshomedirectory")), 'pointer', []); var path = new objc.object(nshomedirectory()); console.log('homedir: '   path); } // 导出rpc函数 rpc.exports = { //...... homedir: function(){ gethomedir(); } }; 

最后希望读者能够仔细领悟,翻一翻前面几篇教程,多加练习,相信一定会融会贯通。期待下一篇教程我们还会再见,感谢各位的支持。

 

最后于 2020-6-7 23:33 被暗夜盗魔编辑 ,原因:

原文链接:https://bbs.kanxue.com/thread-259979.htm

网络摘文,本文作者:15h,如若转载,请注明出处:https://www.15cov.cn/2023/08/27/原创-【frida-实战】远程过程调用(rpc)/

发表评论

邮箱地址不会被公开。 必填项已用*标注

网站地图