

Frida实战hook学习笔记
source link: https://shingle.me/post/frida%E5%AE%9E%E6%88%98hook%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Frida实战hook学习笔记
动态hook神器
- 安装 frida,具体看官方文档就不写了 https://www.frida.re/docs/installation/
- root 的手机或模拟器
- adb 调试工具
电脑上安装好 frida 环境后,在 github 上 https://github.com/frida/frida/releases 下载你手机对应架构的frida-server
,解压然后
adb push frida-server-12.6.21-android-arm64 /data/local/tmp/
手机连接电脑,利用 adb shell 运行该服务
adb shell cd /data/local/tmp/ chmod 755 frida-server-12.6.21-android-arm64 ./frida-server-12.6.21-android-arm64
此时如果没有报错,手机上的frida-server
就算启动了
接着再把frida-server
的端口转发到电脑
adb forward tcp:27042 tcp:27042
编写 hook 代码
以下使用的 python 环境来运行 frida,记录了使用 frida 的学习过程,可能会不定期更新
目录结构:
hook.py
intent.js
入口代码:
import frida
import sys
import os
packageName = "com.xxx.xxx"
def messagesCallback(message, data):
if message['type'] == 'send':
print(message['payload'])
elif message['type'] == 'error':
print(message['stack'])
hookCode = None
with open(os.path.dirname(os.path.realpath(__file__)) + '/intent.js') as f:
hookCode = f.read()
process = frida.get_remote_device().attach(packageName)
print(process)
process.enable_debugger()
script = process.create_script(hookCode)
script.on('message', messagesCallback)
script.load()
sys.stdin.read()
其中packageName
是你要 hook 的 app 包名
intent.js
是用 js编写的 hook 代码,注意这个是文件路径。我自己是用读取hook代码文件的方式,这样就不必把 js 代码混在 python 里,比较清晰明了。
先来写一个简单的 hook, 用来读取 intent 的传值
Java.perform(function () {
var act = Java.use("android.app.Activity");
var process = Java.use("android.os.Process");
act.getIntent.overload().implementation = function () {
send("act:" + this.getIntent().getExtras());
return this.getIntent();
};
process.start.overload('java.lang.String', 'java.lang.String', 'int', 'int', '[I', 'int', 'int', 'int', 'java.lang.String', 'java.lang.String', 'java.lang.String', 'java.lang.String', 'java.lang.String', '[Ljava.lang.String;').implementation = function (a, b, c, d, e, f, g, h, j, k, l, m, n, o) {
var id = 5;
var flags = arguments[id];
send("before arg:" + flags);
arguments[5] = 1;
send("after arg:" + arguments[id]);
return this.start(a, b, c, d, e, f, g, h, j, k, l, m, n, o);
};
})
Java.use
用来寻找要 hook 的类act.getIntent.overload().implementation = function () {}
是重写该hook类的getIntent()
方法如果要 hook 的方法带参数,需要在
overload
里传对应类型
function
传自定义的参数名字. 例如上面例子里的process.start.overload
或者可以不写 overload,但是function
里面的参数个数需要和 hook 的函数一样
process.start.implementation = function (a, b, c, d, e, f, g, h, j, k, l, m, n, o) {}
- 参数为基本类型可以简写,比如byte -> B, int -> I, boolean -> Z
对于数组类型,要添加前缀[
,例如int[] -> [I, String[] -> [Ljava.lang.String
- 获取 hook 回调里对象的普通field 字段值
this.myField.value
如果字段名字和函数名重复,需要加_访问
class Test{
public int a;
public void a(){
return 0;
}
}
this._a.value
- 获取 hook 回调里对象的Map类型 field 字段值
https://github.com/frida/frida/issues/488
var HashMapNode = Java.use('java.util.HashMap$Node');
var iterator = this.myMap.value.entrySet().iterator();
while (iterator.hasNext()) {
var entry = Java.cast(iterator.next(), HashMapNode);
console.log(entry.getKey());
console.log(entry.getValue());
}
- 打印一个类的方法和字段
https://github.com/frida/frida-java-bridge/issues/44
function describeJavaClass(className) {
var jClass = Java.use(className);
console.log(JSON.stringify({
_name: className,
_methods: Object.getOwnPropertyNames(jClass.__proto__).filter(function (m) {
return !m.startsWith('$') // filter out Frida related special properties
|| m == 'class' || m == 'constructor' // optional
}),
_fields: jClass.class.getFields().map(function (f) {
return f.toString()
})
}, null, 2));
}
- 构造一个对象
var array_list = Java.use("java.util.ArrayList");
var k = array_list.$new();
var hookCls = Java.use("java.util.Map");
var map = Java.cast(obj,hookCls)
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK