简介
Frida是一个动态代码插桩框架,可以将JavaScript或一些自定义的函数库注入到现有的正在运行的二进制文件中,可以注入的系统有Windows,macOS,GNU / Linux,iOS,Android和QNX上的本机应用程序,注入后可以进行进行一些额外的操作:
- 访问进程内存,可以通过该方式打印一些特有的加密数据,比如一些加盐算法的salt
- 在应用程序运行时覆盖函数,执行一些hack逻辑
- 从导入的类调用函数
- 在堆上查找对象实例并使用
- Hook、跟踪和拦截函数等
frida提供的一些工具
列出所有正在运行的app
$ frida-ps -Ua
列出所有安装的app
$ frida-ps -Uai
连接到指定的设备上
$ frida-ps -D 0216027d1d6d3a03
2. frida-cli
```bash
# 通过use连接并启动Chorme
$ frida -U Chorme
# 通过frida连接到本机正在运行的QQ应用上
$ frida QQ
____
/ _ | Frida 12.4.8 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at http://www.frida.re/docs/home/
[Local::QQ]->
# 通过frida连接到本机正在运行的QQ应用上并运行hack.js
$ frida QQ -l hack.js
# 通过usb连接到手机连接到正在运行的com.example.test应用上并运行hack.js
$ frida -u com.example.test -l hack.js
# 通过usb连接到手机连接到正在运行的com.example.test应用上并运行hack.js,debug代表以调试模式运行应用
$ frida -u com.example.test -l hack.js --debug
# 通过usb连接到手机连接,启动名为com.example.test的应用,并运行hack.js
$ frida -u -f com.example.test -l hack.js --no-pause
打印出QQ上所有用object-c写的drawRect开头的函数,并打印当前调用到的堆栈信息
$ frida-trace -m “-[NSView drawRect:]” QQ
启动手机QQ并打印内存中所有正则匹配到的libcommonCrypto*的接口调用
$ frida-trace -U -f com.tencent.mobileqq -I “libcommonCrypto*”
4. frida-kill
```bash
# 连接手机并结束某个pid的进程
$ frida-kill -D 1d07b5f6a7a72552aca8ab0e6b706f3f3958f63e 5029
frida提供的Java接口
Java.available 判断当前java虚拟机是否成功加载
if(Java.available){
Java.perform(function () {
//do something
}
}else{
console.log("Error Jvm not init")
}
Java.enumerateLoadedClasses(callbacks) 枚举当前加载的所有类并执行回调
Java.enumerateLoadedClasses(
{
// 类被加载时回调,会传入类的完成类名,可以通过Java.use()获取类,并通过类的函数名来hack函数,所有该类的实例都会被注入hack的代码
"onMatch": function(className){
console.log(className)
var classNeedHook=""
if(className==classNeedHook){
var Cls=Java.use(className);
Cls.function.implementation = function () {
console.log("you have been hacked!!")
};
}
},
// 所有类都被加载完成时调用,可以在这里执行类加载之后的hack操作
"onComplete":function(){}
}
)
Java.use(className) 通过类名获取类对象的JavaScript包装,可以通过$new来新建对象,通过$dispose来销毁对象,也可以进行函数的hack操作,如上
Java.choose(className, callbacks)
Java.cast(handle, klass)
Java.scheduleOnMainThread(fn),在主线程中执行函数,可以用于执行ui操作
Java.choose(className, callbacks)扫描并枚举堆栈中类的实例,对扫描出的实例都会执行回调,该方式可以调用类的private函数
Java.choose("com.example.test.MainActivity" , {
onMatch : function(instance){ //该类有多少个实例,该回调就会被触发多少次
console.log("Found instance: "+instance);
console.log("Result of func: " + instance.func());
},
onComplete:function(){}
});
Java.cast(handle, klass)把对象实例转换成指定的类型,可以配合Java.choose使用
var StringClass=Java.use("java.lang.String");
var NewTypeClass=Java.cast(variable,StringClass);
通过javaScriptWrapper调用函数时,需要注意重载的问题 ``` var MainActivity =Java.use(“com.example.MainActivity”) MainActivity.test.overload(“java.lang.String”).implementation = function(s) { console.log(s) }
MainActivity.test.overload(“int”).implementation = function(i) { console.log(i) }
- 类的构造函数,新建对象
var utilCls =Java.use(“com.exapmle.Utils”) utilCls.$init.implementation=function(){ consloe.log(“hook Constructor”); } var util=utilCls.$new(); console.log(util.toString());
<a name="Mcc4f"></a>
# 使用
以下操作均在mac+android系统上进行
<a name="Bcd3W"></a>
## 安装frida-server并启动
1. 在本机上安装frida
```bash
# 最新的frida需要python3以上的支持
pip install frida
pip install frida-tools
下载对应版本的frida-server文件,这里下载的是最新版frida-server-12.4.8-android-arm64.xz,在安卓设备上安装并启动frida-server
$ adb push frida-server-10.0.1-android-arm /data/local/tmp/frida-server
$ adb shell
$ adb push frida-server /data/local/tmp/
$ adb shell su #如果有root权限的话
$ adb shell "chmod 755 /data/local/tmp/frida-server"
$ adb shell "/data/local/tmp/frida-server &"
mac系统下查看frida是否成功启动,查看usb连接设备中运行的进程 ```bash $ frida-ps -U PID Name
698 adbd 2113 android.process.acore 2247 android.process.media …..
然后就可以开做上面可以做的事情,enjoy it了
<a name="VIcK4"></a>
## 编写脚本(这里只写个demo举例,实际的hack可能需要配合源码服用
先来一个简单的安卓代码
```java
public class MainActivity extends AppCompatActivity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setText("今天天气真不错");
}
private boolean setText(String text){
textView =findViewById(R.id.tv);
textView.setText("今天天气真不错");
}
}
新建一个文件,叫做hack.js
if(Java.available){
setTimeout(function() { //防止Frida超时导致异常
Java.perform(function(){
var MainActivity = Java.use("com.example.test.MainActivity");
MainActivity.setText.implementation=function(text){
console.log(text);
this.setText("you hace been hacked!!!")
}
}),0
}
}
执行命令
frida -u -f com.example.test -l hack.js
就可以看到文本已经变成了you hace been hacked!!!
对App的一些hack思路(只有思路,不同app方式可能不同
一些在对接口做了加密的app,会在本地存储一些加盐算法的salt,一般分为两类
第一类 直接在java层存放salt和加密算法的的,嗯,怎么说呢,这类app简直就是大门敞开型的,直接反编译+跟踪查看代码即可
第二类 将加密算法存在ndk层,无法通过反编译直接取得加密算法的,可用以下方式
- 抓包(http和https的抓包自行google),获取加密后的密钥关键字
- 反编译app,一般在network相关的包中可以看到这个sign的生成方式
- 跟踪下去,直到ndk层,这时的代码已经没发再阅读和跟踪,但是可以直到大概的方法名
- 使用ida进行反汇编,找到上述函数所在的so文件,可以进行检索上面找到的函数名
- 继续查找相关的地址调用,找到相应的函数,如果salt写在里面,可以直接拿到;一般salt是在外面通过参数传进来的,这时候需要通过frida来打印堆栈信息获取
- 通过frida编写脚本,查找上述函数,输出函数内部调用信息
- 获取salt和算法,然后,嘿嘿嘿~