前言
这是参考一个外国博主的博客写的,这是他的博客地址,本次大致内容是将一个apk中原有的fun函数进行修改,但如果遇到同名函数,需要注意重新实现时注意函数参数,同时实现调用app实例中定义了但未被调用的函数。使用到了Frida、pyhon、js、adb、jadx、cmd、逍遥模拟器等工具及编程语言。环境配置参考Frida 学习实战记录(一)。
一、开始
(1)查看代码
同样使用jadx打开app-2,如图所示:
大致含义相比于第一个apk-1,无非是多了一个同名函数fun,输出一个字符串,然后定义了一个secret函数,但未在onCreate中调用。
(2)重构原有的重名函数fun
此时如果使用(一)中同样的python脚本,会发现控制台的输出会停留在Script loaded successfully这个输出,然后停止输出,明显是出现了问题,但python控制台没有输出错误结果。
此时使用script.on方法,可以获得js脚本的错误输出。
import frida
import time
def message_handler(message, payload):
print(message)
print(payload)
def hook2():
device = frida.get_usb_device()
pid = device.spawn(["com.example.a11x256.frida_test"])
device.resume(pid)
time.sleep(1) # Without it Java.perform silently fails
session = device.attach(pid)
script = session.create_script(open("s2.js").read())
script.on("message", message_handler)
script.load()
# prevent the python script from terminating
input()
if __name__ == "__main__":
hook2()
新定义了一个message_handler的函数用来展示错误结果,在script.on中进行调用,该方法的参数将会被自动填充,无需手动设置(实际上如果改成message_handler()会报错......)。
由此,再运行该python脚本,就可以得到错误提示,如下所示
{'type': 'error',
'description': "Error: fun(): has more than one overload,
use .overload(<signature>) to choose from:\n\t.overload('java.lang.String')\n\t.overload('int', 'int')", 'stack': "Error: fun(): has more than one overload, use .overload(<signature>) to choose
from:\n\t.overload('java.lang.String')\n\t.overload('int', 'int')\n at X
(frida/node_modules/frida-java-bridge/lib/class-factory.js:622)\n at K
(frida/node_modules/frida-java-bridge/lib/class-factory.js:617)\n at set
(frida/node_modules/frida-java-bridge/lib/class-factory.js:1099)\n at x
(/script1.js:5)\n at <anonymous> (frida/node_modules/frida-java-bridge/lib/vm.js:12)\n
at _performPendingVmOps (frida/node_modules/frida-java-bridge/index.js:250)\n at
<anonymous> (frida/node_modules/frida-java-bridge/index.js:225)\n at <anonymous>
(frida/node_modules/frida-java-bridge/lib/vm.js:12)\n at _performPendingVmOpsWhenReady
(frida/node_modules/frida-java-bridge/index.js:244)\n at perform
(frida/node_modules/frida-java-bridge/index.js:204)\n at <eval> (/script1.js:14)",
'fileName': 'frida/node_modules/frida-java-bridge/lib/class-factory.js', 'lineNumber': 622,
'columnNumber': 1}
None
大致含义就是对于同名函数没有做处理,有多余一个的重构,导致识别出现了问题。
由此,需要修改先前的js文件,让他对每个fun都重新实现一次,代码如下:
console.log("Script loaded successfully ");
Java.perform(function x() {
console.log("Inside java perform function");
var my_class = Java.use("com.example.a11x256.frida_test.my_activity");
my_class.fun.overload("int", "int").implementation = function (x, y) { //hooking the old function
console.log("original call: fun(" + x + ", " + y + ")");
var ret_value = this.fun(2, 5);
return ret_value;
};
my_class.fun.overload("java.lang.String").implementation = function (x) { //hooking the new function
var string_class = Java.use("java.lang.String");
console.log("*************************************")
var my_string = string_class.$new("My TeSt String#####");
console.log("Original arg: " + x);
var ret = this.fun(my_string);
console.log("Return value: " + ret);
console.log("*************************************")
return ret;
};
});
可以看到代码实现了两个my_class.fun.overload,分别对两个源代码中的fun函数实现了重构,从而此时再次执行python脚本,就不会出现问题,此时我把它存到了新的js文件s2.js中。
运行该脚本后输出结果为:
Script loaded successfully
Inside java perform function
original call: fun(50, 30)
*************************************
Original arg: LoWeRcAsE Me!!!!!!!!!
Return value: my test string#####
*************************************
original call: fun(50, 30)
*************************************
Original arg: LoWeRcAsE Me!!!!!!!!!
Return value: my test string#####
*************************************
使用adb logcat打印日志文件,结果如下:
11-16 21:59:09.800 8303 8303 D Sum : 80
11-16 21:59:09.800 8303 8303 D string : lowercase me!!!!!!!!!
11-16 21:59:10.802 8303 8303 D Sum : 7
11-16 21:59:10.809 8303 8303 D string : my test string#####
11-16 21:59:11.818 8303 8303 D Sum : 7
11-16 21:59:11.820 8303 8303 D string : my test string#####
11-16 21:59:12.821 8303 8303 D Sum : 7
11-16 21:59:12.822 8303 8303 D string : my test string#####
11-16 21:59:13.828 8303 8303 D Sum : 7
11-16 21:59:13.828 8303 8303 D string : my test string#####
11-16 21:59:14.835 8303 8303 D Sum : 7
11-16 21:59:14.838 8303 8303 D string : my test string#####
11-16 21:59:15.842 8303 8303 D Sum : 7
11-16 21:59:15.843 8303 8303 D string : my test string#####
11-16 21:59:16.846 8303 8303 D Sum : 7
11-16 21:59:16.850 8303 8303 D string : my test string#####
11-16 21:59:17.856 8303 8303 D Sum : 7
11-16 21:59:17.861 8303 8303 D string : my test string#####
可以看到它成功完成了这两个函数的重构。
(3)secret的调用
在源码中可以看到app的代码中定义了一个secret方法,实现对totoal的输出,但它在onCreate中没有被调用,故无法使用相同的方法来hook它。
作者使用的完整代码如下:
console.log("Script loaded successfully ");
Java.perform(function x() {
console.log("Inside java perform function");
var my_class = Java.use("com.example.a11x256.frida_test.my_activity");
my_class.fun.overload("int", "int").implementation = function (x, y) { //hooking the old function
console.log("original call: fun(" + x + ", " + y + ")");
var ret_value = this.fun(2, 5);
return ret_value;
};
var string_class = Java.use("java.lang.String");
my_class.fun.overload("java.lang.String").implementation = function (x) { //hooking the new function
console.log("*************************************")
var my_string = string_class.$new("My TeSt String#####");
console.log("Original arg: " + x);
var ret = this.fun(my_string);
console.log("Return value: " + ret);
console.log("*************************************")
return ret;
};
Java.choose("com.example.a11x256.frida_test.my_activity", {
onMatch: function (instance) {
console.log("Found instance: " + instance);
console.log("Result of secret func: " + instance.secret());
},
onComplete: function () { }
});
});
在最后使用Java.choose完成了对隐藏方法的调用,该方法有多少个实例,该回调就会被触发多少次。
从而结果输出为:
Script loaded successfully
Inside java perform function
Found instance: com.example.a11x256.frida_test.my_activity@58d29a7
Result of secret func: @@@###@@@LoWeRcAsE Me!!!!!!!!!
original call: fun(50, 30)
*************************************
Original arg: LoWeRcAsE Me!!!!!!!!!
Return value: my test string#####
*************************************
original call: fun(50, 30)
*************************************
Original arg: LoWeRcAsE Me!!!!!!!!!
Return value: my test string#####
*************************************
作者说这个Result of secret func: 的输出应该只有@@@###@@@,但我却出现了total被修改的情况,很奇怪,我尝试了重装app,重启frida,重新运行python脚本,调整js代码中Java.choose的位置,但是均没有什么用,就很奇怪,网上也有人根据这个博主的博客做过,但好像都没有出现这个问题。此处留一个坑,有空回来填。
二、总结
第二次frida尝试结束,同样很简单,这个博主仍然还有好几篇博客等待实操。