翻译:興趣使然的小胃
预估稿费:180RMB
投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿
一、前言
在这篇文章中,我们将向读者介绍Frida的一些相关知识。Frida是移动应用安全分析中的一个非常有趣的工具。
即使你从来没有用过Frida,你也可以将这篇文章作为使用Frida开展移动应用安全研究和探索的指南。
这篇文章主要包含以下内容:
1、Frida简介
2、如何在iOS上配置Frida
3、如何使用Frida连接到某个iOS进程
4、如何导出类和方法信息
5、如何使用Frida操控正在运行的iOS应用
6、总结
二、Frida简介
Frida是一个跨平台的动态代码注入工具集,你可以使用它hook应用程序,插入自己的JavaSciprt代码,同时也能获取应用的内存和函数的完全访问权限。
Frida由Ole André V. Ravnås(@oleavr)所开发,有个非常活跃的IRC(Internet Relay Chat,互联网中继聊天)频道与之相关,你可以在这个频道中与其他Frida爱好者探讨思路、问题以及工具的新功能。IRC频道为irc.freenode.net上的#frida频道。
根据具体的使用需求,Frida的一些应用场景为:
1、Hook某个函数,修改返回值。
2、分析自定义协议,嗅探或解密实时流量。
3、调试自己的应用程序。
4、导出iOS应用的类和方法信息。
5、其他应用场景。
我之所以提到“5、其他应用场景”,是因为我们可以将Frida用于各种用途。Frida提供的API功能非常强大,是构建自己的安全或分析工具的首选方案。现在已经有几种工具以Frida为基础,比如Needle以及AppMon等。
Firda的其他应用场景中就包括它可以在非越狱设备上工作,这一点非常有用。为了在非越狱设备上运行Frida调试应用程序,我们需要使用诸如Swizzler2的工具修改应用程序,将FridaGadget dylib添加到应用程序中。
三、在iOS上配置Frida
只需要简单几步,我们就能配置Frida分析iOS应用的安全性。我们需要在iOS设备以及主机上进行配置。
为了在iOS设备上安装Frida,我们需要按照以下步骤操作:
1、在iOS设备上打开Cydia应用。
2、添加源,地址为“https://build.frida.re/”
3、进入已添加的源,搜索“Frida”,点击“Modify”然后安装。
要在主机上安装Frida,我们需要启动控制台,输入“pip install frida”命令,安装Frida程序。
四、使用Frida连接iOS进程
Frida安装完毕后,现在我们已经准备就绪,可以开始使用Frida评估iOS应用的安全性的可利用性。
我们的目标应用是Prateek Gianchandani开发的DVIA(Damn Vulnerable Ios Application,这个应用专门用于iOS平台的渗透测试)iOS应用。本文中用到的脚本大多数都可以在Interference Security的Github代码库中找到。
我们将要分析的是DVIA提供的越狱检测功能,如下所示,该应用提示设备目前处于越狱状态:
我们可以先看一下目标设备当前运行的进程列表,命令如下:
frida-ps –U
从上图中,我们可以了解到iOS设备当前正在运行的所有进程。
我们可以使用“frida –U process-name”命令,将Frida附加到任意一个进程上,命令执行成功后我们将会跳转到Frida控制台中,可以访问目标进程的所有属性、内存内容以及函数功能。
我们可以使用Frida的shell与目标进程交互,也可以编写自己的JavaScrpt代码,获取需要分析的数据。
五、导出iOS应用的类和方法信息
对于DVIA的越狱检测功能而言,我们的目标是确定哪个ViewController和函数负责检测设备的越狱状态。
首先,我们可以写个基本的Frida脚本,导出目标应用中的所有类和方法,从中找到与越狱有关的所有内容,以便在Frida的帮助下绕过应用的越狱检测。
我们的工作流程如下所示:
六、使用Frida找出DVIA中负责越狱检测的类
首先我们先找出应用中的所有类。
for (var className in ObjC.classes)
{
if (ObjC.classes.hasOwnProperty(className))
{
console.log(className);
}
}
运行脚本,将Frida附加到目标进程中(如下图所示),我们可以从运行结果中,找到目标进程的所有类。
我们最好通过grep命令搜索目标类,在本文的案例中,我们可以使用“Jailbreak”这个关键词。
通过关键词搜索,我们定位到一个名为“JailbreakDetectionVC”的类,如下图所示:
找到所有实例后,你可能会看到一个错误提示,忽略这个提示即可。
现在我们已经找到目标类,接下来我们可以探索这个类中的关键函数。
七、使用Frida找出DVIA中负责越狱检测的方法
为了查找类方法,我们需要使用Frida提供的“ObjC.classes.class-name.$methods”方法。在本文案例中,我们只需要查找“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");
运行这个脚本,使用grep命令查找类似“Jailbreak”、“Jailbroken”、“Detection”之类的关键词,如下图所示:
根据这些关键词,我们找到了三个方法,分别为“isJailbroken”、“jailbreakTest1Tapped:”以及“jailbreakTest2Tapped:”。
对于本文案例,“isJailbroken”看上去更像是检测设备是否越狱的方法。
八、使用Frida修改DVIA中负责越狱检测方法的返回值
现在我们可以分析“isJailbroken”方法究竟发送了什么类型的返回值。
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!");
}
运行这个脚本,点击iOS应用中的“Jailbreak Test 1”按钮,之后我们就可以在Frida控制台中看到函数的返回值。
由于我们的设备已越狱,我们获得的返回值为0x1,表明函数的返回结果为True。
接下来我们的任务是覆盖这个返回值,修改这个方法,使得不管什么时候我们点击应用中的“Jailbreak Test 1”按钮,函数的返回值始终为false(即0x0)。
我们只需要添加一行代码,就可以修改这个函数的返回值。
我们可以通过如下代码,修改函数的返回值,并将返回值反馈到控制台中:
newretval = ptr("0x0")
retval.replace(newretval)
console.log("t[-] New Return Value: " + newretval)
最终的脚本如下所示:
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!");
}
运行这个脚本,我们可以在控制台中看到函数的返回值已经被成功修改:
回头看看这个iOS应用,你会发现应用提示设备处于未越狱状态,如下所示:
九、总结
这就是本文的全部内容。在接下来的文章中,我们会向大家介绍Frida脚本语言的详细知识,以及如何利用Frida的API函数和其他工具对iOS和Android应用的安全性进行评估。