Frida是一种基于JavaScript的动态分析工具,可以用于逆向开发、应用程序的安全测试、反欺诈技术等领域。Frida主要用于在已安装的应用程序上运行自己的JavaScript代码,从而进行动态分析、调试、修改等操作,能够绕过应用程序的安全措施,可以助力于对应用程序进行逆向分析。
Frida不需要依赖于任何特殊的工具或设备,只需要在目标设备上安装Frida服务器,就可以使用Frida客户端与之通信。
一、环境搭建
1.1 安装Frida客户端
首先,在Windows、macOS、Linux平台上使用以下命令安装Frida客户端,安装的命令如下:
pip install frida
pip install frida-tools
如果没有安装python环境,请先安装python环境后再运行上面的命令,安装完成之后,可以使用下面的命令来检查是否安装成功。
frida --version
还可以使用pip list命令来列出所有安装的模块,如下图。
1.2 frida-server服务端
对于Android、iOS平台上,可以直接从Frida官方网站下载相应的安装包。下载frida-server服务端,下载地址:github.com/frida/frida…。注意frida版本要与frida-server版本一致,比如我本地安装的16.0.19。
如果不知道自己手机CPU的版本和型号,可以使用下面的命令查看:
adb shell
getprop ro.product.cpu.abi #输出:arm64-v8a
那么我们只需要找到相应的服务器server:frida-core-devkit-16.0.19-android-arm64.tar.xz下载即可。
1.3 在安卓设备上安装frida-server服务端
将上面下载的压缩包解压,改名为frida-server,然后推送到手机中,添加执行权限,启动服务操作。
# push进手机
adb push frida-core-devkit-16.0.19-android-arm64.tar.xz /data/local/tmp
# 端口转发
adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043
# 运行frida
adb shell
walleye:/ $ su
walleye:/ # cd /data/local/tmp
walleye:/ # chmod 777 frida-core-devkit-16.0.19-android-arm64.tar.xz
walleye:/ # ./frida-core-devkit-16.0.19-android-arm64.tar.xz
walleye:/ #
执行完上面的操作后,可以新打开一个新的命令行窗口,然后执行frida-ps -U命令查看是否能显示模拟器上的安卓进程。
注意:如果出现失败可能就是frida-server版本出问题了,还有需要root权限,建议使用夜神模拟器。
二、基本使用
2.1 示例
下面是一段测试的示例,我Hook的是com.xxx.test.ec.util.Md5Util这个方法,这个需要根据app的实际方法来,我是通过jadx反编译后复制出来的类名。
下面是Hook的代码:
# -*- coding: utf-8 -*-
# 导入 frida, sys 库
import frida, sys
#md5--hook-
jscode = """
Java.perform(function(){
<!-- 获取 MD5Util 这个类的对象 -->
var utils = Java.use("com.xxx.test.ec.util.Md5Util");
<!-- 调用 ToMd5 这个,这个方法的参数有1个 -->
utils.md5.overload('java.lang.String').implementation = function(a){
send("Hook Start...");
send("传入参数: " +a);
<!-- 获取 ToMD5 这个方法执行的结果,并打印到控制台上 -->
var res= this.md5(a);
send("ToMD5 方法返回值: " +res);
return res;
}
});
"""
# 这下面的代码的作用就是为了执行上面 JS 代码,输出 JS 中 send() 方法中的内容
def message(message, data):
if message["type"] == 'send':
print("[*] {0}".format(message['payload']))
else:
print(message)
# 获取这个 APK 的进程
#process = frida.get_remote_device().attach('com.xxx.test:pushcore')
#process = frida.get_usb_device().attach(3281)
process = frida.get_remote_device().attach('这里填目标app的名字')
# 加载 JS 代码
script = process.create_script(jscode)
script.on("message", message)
print('[*] Running CTF')
script.load()
sys.stdin.read()
2.2 其他操作
Hook函数
使用JavaScript代码Hook应用程序中的某个函数,示例代码:
Interceptor.attach(Module.findExportByName("libexample.so", "example_func"), {
onEnter: function(args) {
console.log("example_func enter");
},
onLeave: function(retval) {
console.log("example_func leave");
}
});
该代码将Hook应用程序中名为example_func的函数,当进入函数时,会打印"example_func enter",当离开函数时,会打印"example_func leave"。
内存读取
使用JavaScript代码读取目标进程中的内存,示例代码:
var addr = Module.findExportByName("libexample.so", "example_data");
var data = Memory.readByteArray(addr, 0x100);
console.log(hexdump(data));
该代码读取了名为example_data的变量,并将其打印到控制台上。
其他操作
劫持Java的函数调用,使用示例:
Java.perform(function() {
var MainActivity = Java.use('com.example.MainActivity');
MainActivity.onCreate.implementation = function(savedInstanceState) {
console.log("[*] onCreate hooked");
this.onCreate(savedInstanceState);
};
var TextView = Java.use('android.widget.TextView');
TextView.setText.implementation = function(text) {
console.log("[*] setText hooked");
this.setText(text);
};
});
模拟按钮点击事件,使用示例:
var button = Java.use('android.widget.Button');
var view = Java.cast(button.$new(), Java.use('android.view.View'));
Java.perform(function() {
view.performClick();
});
绕过SSL Pinning,使用示例:
var SSLPinning = Java.use('com.example.SSLPinning');
SSLPinning.execute.overload('javax.net.ssl.SSLSocketFactory', 'java.lang.String', 'int').implementation = function(socketFactory, hostname, port) {
console.log("[*] SSLPinning.execute(" + socketFactory + ", " + hostname + ", " + port + ")");
var allowAllHostnameVerifier = Java.use('javax.net.ssl.HttpsURLConnection').getDefaultHostnameVerifier();
var nullarray = Java.array('java.lang.Object', [null]);
allowAllHostnameVerifier.verify(hostname, socketFactory.createSocket(hostname, port).getSession());
return true;
};
以上是Frida逆向开发的基本操作代码示例,使用Frida可以进行更多复杂的逆向操作和应用程序开发,更多的详情还是参考:frida.re/docs/home/