当我们分析恶意APP样本时,难免会遇到单靠静态和逆向分析无法解决问题的情况。例如:
-
Hook一个方法:如,分析APP通信加密时,需要Hook加密函数来查看其具体实现方法和参数。
-
调用静态方法:如,尝试越权访问API时,需要调用APP中某个用于验证用户权限的静态方法,来绕过权限验证。
-
更改变量的值:如,分析用户身份、权限信息的过程中,需要查看并修改APP本地缓存用户身份信息等变量的数值,以模拟不同用户身份或权限级别。
诸如此类,都需要引入基于Frida的动态插桩技术。Frida 是一款强大的动态代码分析工具,可以用于在移动应用程序中进行代码注入、调试和反编译等操作。使用Frida需要安装前置的Python、Frida、安卓模拟器及其依赖环境(可参考官方文档:https://frida.re/docs/home/)。这些繁琐的过程,可能会对有意愿了解和使用该类技术的人员造成阻碍。【大狗涉网线索分析平台】的【云真机操作台】引入了 Frida 脚本功能,该功能不仅可以省去复杂的安装过程,还能够实现一键运行 Frida 脚本。这意味着,用户可以在无糖浏览器中随时随地对恶意 APP 进行动态调试,大大提高了工作效率和便利性。
为了使用Frida达到Hook函数/方法、调用静态方法、更改变量值等目的,我们需要掌握以下技术和方法:
-
Frida框架:了解Frida框架的基本原理和架构,包括Frida Server和Frida Client之间的通信机制。
-
Frida脚本:学习使用JavaScript编写Frida脚本,这些脚本可以用于在目标应用程序中执行各种操作,如函数钩子、数据修改、调试等。
-
函数Hook(钩子):掌握如何在目标应用程序中通过Frida对特定函数进行Hook,以便监视、修改或替换函数的行为。
下面将对这些基础用法进行讲解和演示。
本系列文章将以Frida-lab中的题目为例,首先分上、下两篇为大家介绍云真机操作台中Frida脚本的基础用法和背景知识,然后分篇为大家讲解Frida脚本的更多进阶用法。Frida-lab是Github上的一个开源项目,是专为学习Frida for Android而设计的一系列挑战,包含多个CTF风格的APP样本,旨在帮助初学者掌握Frida及其常用的API基础知识。
项目链接:https://github.com/DERE-ad2001/Frida-Labs
-
Jadx反编译工具:jadx是一个功能强大、使用简单的Android反编译利器,适合开发者在逆向工程和代码分析时使用。(官方网站:https://github.com/skylot/jadx)
-
JavaScript脚本:我们将使用JavaScript API来完成Frida脚本的编写。(API文档地址:https://frida.re/docs/javascript-api/)(值得注意的是,Frida也支持Python。)
-
Frida框架:本次我们使用【大狗涉网线索分析平台】-【云真机操作台】中引入的Frida脚本功能。
-
了解Frida框架的基本原理和架构。
-
了解Hook技术拦截和修改函数或方法的基础知识。
-
掌握使用jadx进行逆向工程的基础知识。
-
具备理解Java代码的能力。
-
具备编写小型JavaScript代码片段的能力。
打开【无糖浏览器】进入【大狗平台专区】-【云真机操作台】(图1),上传Challenge 0x1.apk文件,在云真机操作台中完成模拟安装(图2)。
图1. 进入云真机操作台
图2. 点击上传APK文件
图3. 应用程序
图4. 输入数字
图5. 程序入口
1 int get_random() {
2 return new Random().nextInt(100);
3 }
check方法被传入了两个参数,一个是我们在APP页面输入后提交的的数字i2,一个是程序启动时调用get_random方法生成的随机数i。该方法会检查表达式(i * 2) + 4 == i2)是否成立,如果成立则将正确的flag输出到绑定的textView控件上,反之则会提示“Try again”。
编写这个脚本,我们可以在jadx中右键get_random方法,选择复制为Firda片段。复制下来的Firda片段展示了Hook这个方法的一般流程,从中我们可以提取出关键信息,Hook这个方法需要使用APP中com.ad2001.frida0x1包的MainActivity类。
1 let MainActivity = Java.use(“com.ad2001.frida0x1.MainActivity”);
2 MainActivity[“get_random”].implementation = function () {
3 console.log(`MainActivity.get_random is called`);
4 let result = this[“get_random”]();
5 console.log(`MainActivity.get_random result=${result}`);
6 return result;
7 };
然后,在这个基础上修改代码,实现Hook get_random方法,并获取其返回值——随机数i值的JavaScript脚本代码实现如下:
下面是关于这段代码的解释:
●
●var a=Java.use(“com.ad2001.frida0x1.MainActivity”); 声明了一个变量a来表示目标 Android应用程序中的Java类,Java.use函数指定要使用com.ad2001.frida0x1包中的MainActivity类。
●a.get_random.implementation = function(){…}使用变量a在所选类的内部勾取get_random方法。
●var ret_val = this.get_random(); console.log(“MainActivity.get_random result is ” + ret_val); 获取get_random方法运行的返回值,将其输出到控制台。
在【云真机操作台】–【Frida脚本】空白处点击【新增脚本】,或在左侧脚本库【运行脚本】功能区点击添加,来新增一个Frida脚本(图6),命名为Challenge_0x1_hook,将编写好的代码复制进来(当然,也可以直接在这里编写脚本)。然后点击【加载脚本】,由于反编译代码中get_random方法是在APP加载的时候被调用的,因此我们运行Frida脚本时,需要选择重启APP(图7)。脚本运行成功后,get_random方法的返回值已经输出到控制台(图8)。
图6.
图8.
图9.
Frida Hook方法的脚本模板:
1 Java.perform(function() {
2 var <class_reference> = Java.use(“<package_name>.<class>”);
3 <class_reference>.<method_to_hook>.implementation = function(<args>) {
4 /*
5 我们自己的方法实现
6 */
7 }
使用jadx反编译APP,得到程序源代码。分析代码可以发现,应用程序只包含一个MainActivity类,在程序启动时加载activity_main布局,并获取该布局中的TextView控件对象赋值给静态变量t1。这个类中存在一个未被使用的静态方法get_flag,在get_flag中比较了传入的参数,如果传入的参数为4919则解密flag,设置给TxtView控件(图11)。
图11.
分析完APP源代码可以知道,程序中只包含了一个MainActivity类,类中定义了一个静态get_flag方法,方法中比较了传入的参数是否为4919。我们要找的flag就藏在get_flag方法中,但是程序本身不会从任何地方调用该方法。因此,要获取flag,我们需要使用Frida框架来调用该静态方法,并将传入的参数变量设置为4919。
首先明确我们要调用的get_flag静态方法位于程序com.ad2001.frida0x2包MainActivity类中。调用该方法,并将传入的参数变量设置为4919的代码实现如下:
图12 运行Frida脚本获取flag
1 Java.perform(function (){
2 var <class_reference> = Java.use(“<package_name>.<class>”);
3 a.function(val); // 需要调用的方法名称
4 })
03
APP下载:
下载Challenge 0x3.apk文件并上传至大狗云真机操作平台后,可以看到该APP有一个按钮和一个 TextView,TextView 提供有关标志的提示,没有EditText可以输入任何内容。如果您单击该按钮,它会显示“TRY AGAIN”,重复点击界面仍然显示“TRY AGAIN”(图13)。猜测程序中可能存在某个变量的值,只有当它达到预设值时才能触发下一步操作,我们将APK放入jadx进行静态分析。
图13.
我们需要使用Frida框架,编写一个JavaScript脚本,将code变量的值修改为512.
首先明确code变量位于程序com.ad2001.frida0x3包的Checker类中,将它的值修改为512的代码实现如下:
在云真机操作台添加Frida脚本,命名为Challenge_0x3_hook,将编写好的代码复制进来。点击【加载脚本】,由于code作为Checker类中的静态变量,不需要在程序启动时调用,因此不需要在运行脚本时重启APP。脚本运行成功后,再次点击按钮,此时flag成功显示在程序界面中(图16)。
1 Java.perform(function (){
2 var <class_reference> = Java.use(“<package_name>.<class>”);
3 <class_reference>.<variable>.value = <value>; //需要修改的变量
4 })
以上为本期分享的三个Frida的基础用法,后续我们还将分享更多相关基础和进阶用法。欢迎相关公检法技术工作者注册安装【无糖浏览器】,自行通过【大狗平台专区】的【云真机操作台】复现研究。大家还可以根据Frida-lab项目中的参考答案,尝试更多有趣的解题方法。
[1]用法1:https://github.com/DERE-ad2001/Frida-Labs/blob/main/Frida+0x1/Solution/Solution.md
[2]用法2:https://github.com/DERE-ad2001/Frida-Labs/blob/main/Frida+0x2/Solution/Solution.md
[3]用法3:https://github.com/DERE-ad2001/Frida-Labs/blob/main/Frida+0x3/Solution/Solution.md
无糖浏览器-您身边的办案助手
下载地址(PC端与APP同链接):
http://browser.nosugar.tech
邀请码:注册邀请码可从已认证通过的公安民警处获得,完成注册流程并审核通过可开通完整使用权限。
如有疑问,可以扫描下方二维码进入无糖反网络犯罪研究中心。
原文始发于微信公众号(无糖反网络犯罪研究中心):APP动态分析系列 – Frida的基础用法(上)