介绍 下载地址: DERE-ad2001/Frida-Labs:该仓库包含一系列学习 Frida for Android Exploitation 的挑战。 — DERE-ad2001/Frida-Labs: The repo contains a series of challenges for learning Frida for Android Exploitation. (github.com)
介绍 项目中包含了11个不同的实战案例,分别从java层到Native层,介绍了常见的Frida API使用场景:
challenge 0x01:hook普通方法
challenge 0x02:调用静态方法
challenge 0x03:更改变量的值
challenge 0x04:创建实例对象
challenge 0x05:在现有实例上调用方法
challenge 0x06:调用带有对象参数的方法
challenge 0x07:hook构造函数
challenge 0x08:hook so层函数
challenge 0x09:更改so层函数返回值
challenge 0x0A:调用原生函数
challenge 0x0B:使用 X86Writer 和 ARM64Writer 修补汇编
challenge 0x01
1、提示【Try again】。使用jadx反编译后打开,定位到关键代码处:
可以直接搜索 “Try again”,适用于代码较多的情况下
2、分析代码,可以先定位到 check 函数
当(i * 2) + 4 == i2的时候,可以执行下一步的代码
3、查看调用了check函数的地方,定位到了 oncreate 函数
MainActivity.this.check(i, Integer.parseInt(obj));
其中参数 i 和 Integer.parseInt(obj)分别为:
final int i = get_random(); //通过get_random得到 String obj = editText.getText().toString(); //用户输入
3、所以,可以得到逻辑为:
通过get_random()函数得到的随机值,经过运算后,得到我们输入的值即可通过校验。
所以,这块只需要hook掉 get_random()函数,让他返回一个固定值即可。
4、Frida代码如下:
function main ( ){ Java .perform (function ( ){ var className = Java .use ("com.ad2001.frida0x1.MainActivity" ); var method = className.get_random ; method.implementation = function ( ){ console .log ("get_random function called" ); console .log ("Returning 5" ); return 5 ; } }); } setImmediate (main);
直接让 get_random 函数的返回值为5,则用户输入应该为 5*2+4=14
challenge 0x02
1、定位到MainActivity类中,找到了get_flag函数
2、全局搜索,没有发现调用 get_flag函数的地方,也就是说,这块定义了一个函数,但是没有做引用
3、所以,这块使用Frida调用 get_flag函数,并且要求传入的参数为 4919
4、代码如下:
function main ( ){ Java .perform (function ( ){ var a = Java .use ("com.ad2001.frida0x2.MainActivity" ); a.get_flag (4919 ); }); } setImmediate (main);
5、也可以不写脚本,直接frida中输入代码hook即可:
challenge 0x03
1、jadx查看MainActivity类,定位到了onClick方法:
2、查看代码逻辑,当Checker.code == 512的时候,执行后续代码,当不等于512的时候,返回 try again!
定位到Checker.code处:
code是一个静态成员变量。
3、这块有两种方法进行HOOk:
①直接hook修改静态成本变量Checker.code的值
②hook increase方法,使用for循环执行 512/2=216次
方法一:Hook成员变量
function main ( ){ Java .perform (function ( ){ var a = Java .use ("com.ad2001.frida0x3.Checker" ); a.code .value = 512 ; }); } setImmediate (main);
方法二:Hook对应方法
function main ( ){ Java .perform (function ( ){ var className = Java .use ("com.ad2001.frida0x3.Checker" ); for (var i = 1 ; i <= 256 ; i++) { console .log ("Calling increase() method " + i + " times" ); className.increase (); var code_value = className.code .value ; console .log ("Current variable value: " + code_value); } }); } setImmediate (main);
challenge 0x04
1、jadx反编译后定位到了MainActivity,查看后没有发现有用信息:
2、查看另一个类Check,里面定义了一个 get_flag方法
3、要求传入的参数值a = 1337,才会继续向下执行。
由于没有在MainActivity中发现实例化的Check类。
所以,可以先使用$new()新建一个Check的实例对象,然后调用get_flag方法,打印输出即可。
function main ( ){ Java .perform (function ( ){ var check = Java .use ("com.ad2001.frida0x4.Check" ); var check_obj = check.$new(); var res = check_obj.get_flag (1337 ); console .log ("FLAG--1 " + res); }); } setImmediate (main);
这块的get_flag方法是非静态方法,创建实例后也可以使用Java.choose来进行hook定位
function main ( ){ Java .perform (function ( ){ var check = Java .use ("com.ad2001.frida0x4.Check" ); var check_obj = check.$new(); var res = check_obj.get_flag (1337 ); console .log ("FLAG--1 " + res); Java .choose ('com.ad2001.frida0x4.Check' , { onMatch : function (instance ){ console .log ("Found `HookedObject` instance:" , instance); var res = instance.get_flag (1337 ); console .log ("FLAG--2 " + res); }, onComplete : function ( ){ console .log ("Found Completed" ); } }); }); } setImmediate (main);
challenge 0x05
jadx反编译,定位到关键函数:
查看关键代码 if (code == 1337) 的执行函数后续代码:
所以,这块可以参考上节demo的做法。
这块有个问题,就是不能直接 $new 创建一个实例后再调用 flag 方法。
原因:flag函数在MainActivity类中,一般MainActivity是由程序直接创建的,不会通过代码来调用。
所以,这块使用 Java.choose 定位到实例,然后再调用即可:
function main ( ){ Java .perform (function ( ){ Java .choose ("com.ad2001.frida0x5.MainActivity" ,{ onMatch : function (instance ){ console .log ("Found MainActivity instance: " + instance); instance.flag (1337 ); }, onComplete : function ( ){} } ) }); } setImmediate (main);
challenge 0x06
if (1234 == A.num1 && 4321 == A.num2)
MainActivity中的get_flag方法,传参为 Checker的一个实例。
但是没有在MainActivity中发现调用get_flag方法的代码,所以,这块需要定位到实例后主动调用;
因为if判断中对Check类的两个成员变量有要求,所以,还需要实例化一个Check类并对成员变量进行初始化。
代码如下:
function main ( ) { Java .perform (function ( ) { Java .choose ('com.ad2001.frida0x6.MainActivity' , { onMatch : function (instance ) { console .log ("Instance found" ); var checker = Java .use ("com.ad2001.frida0x6.Checker" ); var checker_obj = checker.$new(); checker_obj.num1 .value = 1234 ; checker_obj.num2 .value = 4321 ; instance.get_flag (checker_obj); }, onComplete : function ( ) {} }); }); } setImmediate (main)
challenge 0x07 本质是要Hook构造函数 : $init
代码如下:
function main ( ) { Java .perform (function ( ) { Java .choose ("com.ad2001.frida0x7.MainActivity" , { onMatch : function (instance ) { console .log ("Found instance of MainActivity" ); var check_class = Java .use ("com.ad2001.frida0x7.Checker" ); instance.flag (check_class.$new(513 , 513 )); }, onComplete : function ( ) { console .log ("Done" ); } }); }); } setImmediate (main);