Frida简介
Frida是一款基于python + javascript 的hook框架,通杀android\ios\linux\win\osx等各平台,由于是基于脚本的交互,相比xposed和substrace cydia更加便捷,本文重点介绍Frida在android下面的使用。
Frida的官网为:http://www.frida.re/
环境配置
- pip install frida 安装frida环境
- 在root的手机上运行frida server端
- wget https://build.frida.re/frida/android/arm/bin/frida-server
- adb push frida-server /data/lcoal/tmp
- chmod 755 frida-server
- ./frida-server &
- adb forward
- adb forward tcp:27042 tcp:27042
- adb forward tcp:27043 tcp:27043
- 完成配置,直接在PC端运行hook脚本即可
需要注意的是,frida的客户端和服务度版本应该相同,否则会出现不可预知的其他错误。1
frida --version 查看版本
免root实现frida hook(重打包)
apktool反编译apk
1
$ apktool d test.apk -o test
将对应版本的gadget拷贝到/lib没有了下.例如arm32的设备路径如下.
/lib/armeabi/libfrida-gadget.so
下载地址:
https://github.com/frida/frida/releases/
smali注入加载library,选择application类或者Activity入口.
1
const-string v0, "frida-gadget" invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
如果apk没有网络权限需要在配置清单中加入如下权限申明
1
<uses-permission android:name="android.permission.INTERNET" />
回编译apk
1
$ apktool b -o newtest.apk test/
重新签名安装运行.成功后启动app会有如下日志
Frida: Listening on TCP port 27042
实现hook
以下为frida hook的框架代码,只需要修改jscode就可以实现自定义的hook1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34import frida, sys
def on_message(message, data):
if message['type'] == 'send':
print("[*] {0}".format(message['payload']))
else:
print(message)
jscode = """
Java.perform(function () {
// 要hook的类名
var MainActivity = Java.use('com.example.xxx.MainActivity');
// hook按钮点击事件
MainActivity.onClick.implementation = function (v) {
// Show a message to know that the function got called
send('onClick');
// 执行原始方法代码
this.onClick(v);
//修改MainActivity中属性的值
this.m.value = 0;
this.n.value = 1;
this.cnt.value = 999;
//打印日志
console.log('Done:' + JSON.stringify(this.cnt));
};
});
"""
# 设置要注入的进程名或者pid
process = frida.get_usb_device().attach('com.example.seccon2015.rock_paper_scissors')
script = process.create_script(jscode)
script.on('message', on_message)
print('[*] Running CTF')
script.load()
sys.stdin.read()
采坑记录
需要自己注意脚本加载时机 app启动后进行attach.可以使用-f参数frida来生成已经注入的进程(先注入Zygote为耗时操作),通常配合–no-pause使用.
1
frida -U -f com.tencent.tmgp.pubgmhd -l chiji.js
hook不上的原因?
- 要hook的函数是不是正好被打了热补丁?
- hook的进程是否正确,比如com.tencent.mm有好几个进程
- hook中可能出现“函数名参数完全相同,但返回值不同的情况”,这种情况frida暂时无法实现,收到测试此情况代码编译不会通过,但编译后可以改bytecode,不影响执行结果
- 这种情况可以枚举函数的overloads属性,挨个hook,或者使用数组索引hook,例如a.overloads[1].implement=xxxx
使用enumerateLoadedClasses报“VM::GetEnv failed”错误
enumerateLoadedClasses需要在Java.perform()下使用,参考https://github.com/frida/frida/issues/237Failed to spawn: unable to find application with identifier ‘com.dzvuhumnjt.kfwmalytfds’
如果包名是正确的,应该是这个包名是一个服务,没有lunch activity, 此时只能靠启动后抢时间的方式来attach, spawn行不通
Frida 基础数据类型
Int
1 | var Integerclass = Java.use("java.lang.Integer"); |
Long
1 | var Longclass = Java.use("java.lang.Long"); |
ByteArray
js传给python
1
2
3
4
5
6
7
8
9// js中send(byte[]数组)
def on_message(message, data):
if message['type'] == 'send':
data = message['payload']
for i in range(len(data)):
data[i] = data[i] & 0xff
open("tmp",'wb').write(bytearray(data))
else:
passpython传给js
1
var a = Java.array('byte', [ 0xac,0x37,0x43,0x4f,0xaf,0xa8]);
Frida Hook实例
以下为我曾经用过或自己实现的frida脚本,主要适用于Android平台,根据不同的使用场景进行了分类,如需获取更多的使用或脚本,请参考awesome-frida,该项目搜集了各种通过frida实现的hook需求,并且不分区平台
https://github.com/dweinstein/awesome-frida
1. 打印hook函数的返回值
直接运行一遍原函数,将结果赋值给一个新变量,输出并return新变量即可,例如:
1 | Java.perform(function () { |
2. hook重载函数
1 | cls.loadUrl.overload("java.lang.String").implementation = function(param)…… |
3. 打印java函数的调用栈
1 | var Exc = Java.use("java.lang.Exception"); |
4. 打印native函数调用栈
1 | console.log("begin===="); |
5. dump内存
1 | var data = Memory.readByteArray(ptr(0x824a9000), 159744); |
6. Hook Android IMEI
1 | Java.perform(function () { |
7. Hook Android webview http请求
主要针对以下webview中的以下函数:
1 | - loadUrl(String url) |
1 | Java.perform(function () { |
8. 获取context
1 | var currentApplication = Java.use('android.app.ActivityThread').currentApplication(); |
9. 创建bundle对象
1 | var bundle = Bundle.$new(); |
10. hook 对象
1 | //读取实例对象的属性值,对于得到的对象,需要使用Java.cast()方法转换后才可以使用 |
11. 导出函数并被任意调用
1 | rdev = frida.get_remote_device() |
12. hook构造函数
1 | obj.$init.implementation = function (){ |
13.枚举所有加载的类
1 | Java.enumerateLoadedClasses({ |