https://frida.re/docs/functions/ 官方教程
https://learnfrida.info/ 挺好的教程
npm install @types/frida-gum
Java.perform(() => {
const Cipher = Java.use('javax.crypto.Cipher');
const Exception = Java.use('java.lang.Exception');
const Log = Java.use('android.util.Log');
const init = Cipher.init.overload('int', 'java.security.Key');
init.implementation = function (opmode, key) {
const result = init.call(this, opmode, key);
console.log('Cipher.init() opmode:', opmode, 'key:', key);
console.log(stackTraceHere());
return result;
};
function stackTraceHere() {
return Log.getStackTraceString(Exception.$new());
}
});
自定义载入 so 的情况可能会出现 hook 查不到函数的情况,这时要延时在 frida 命令行中重新载入 nativehook
> NativeHook()
native 模板
var so_name = "libUE4.so";
function dump_so() {
var libso = Process.getModuleByName(so_name);
console.log("[name]:", libso.name);
console.log("[base]:", libso.base);
console.log("[size]:", ptr(libso.size));
console.log("[path]:", libso.path);
var file_path = "/data/data/com.oacia.apk_protect/" + libso.name + "_" + libso.base + "_" + ptr(libso.size) + ".so";
var file_handle = new File(file_path, "wb");
if (file_handle && file_handle != null) {
Memory.protect(ptr(libso.base), libso.size, 'rwx');
var libso_buffer = ptr(libso.base).readByteArray(libso.size);
file_handle.write(libso_buffer);
file_handle.flush();
file_handle.close();
console.log("[dump]:", file_path);
}
}
function hook_open() {
console.log("attaching open...")
Interceptor.attach(Module.findExportByName(null, "open"),
{
onEnter: function (args) {
var pathptr = args[0];
if (pathptr !== undefined && pathptr != null) {
var path = ptr(pathptr).readCString();
console.log("open " + path);
if (path == "/proc/self/maps") {
console.log("find maps");
if (first_hook_open) {
first_hook_open = false;
return;
}
// redirect to noexits file
this.new_path = Memory.allocUtf8String("/proc/self/noexitsssss");
args[0] = this.new_path;
}
}
},
onLeave: function (ret) {
}
}
);
}
function hook_rotate() {
var lib = Module.findBaseAddress(so_name)
if (!lib) {
console.log("[x] cannot find lib");
}
var dest;
Interceptor.attach(lib.add(0x6044), {
onEnter: (args) => {
console.log("RC4 decrypt");
dest = args[0];
console.log(hexdump(args[0], {
offset: 0,
length: 0x40,
header: true,
ansi: false
}))
console.log(`len: ${args[1]}`);
},
onLeave: () => {
console.log("RC4 decrypt result:");
console.log(hexdump(dest, {
offset: 0,
length: 0x40,
header: true,
ansi: false
}))
}
})
Interceptor.attach(lib.add(0x05B30), {
onEnter: function (args) {
console.log("in the uncompress function, get v4:")
var v4 = this.context.x23;
console.log(hexdump(v4, {
offset: 0,
length: 0x140,
header: true,
ansi: false
}))
}
})
}
function hook_dlopen() {
Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
{
onEnter: function (args) {
var pathptr = args[0];
if (pathptr !== undefined && pathptr != null) {
var path = ptr(pathptr).readCString();
if (path.indexOf(so_name) >= 0) {
is_can_hook = true;
}
}
},
onLeave: function (retval) {
if (is_can_hook) {
main();
}
}
}
);
}
function main(){
}
setImmediate(hook_dlopen)
https://crifan.github.io/reverse_debug_frida/website/use_frida/frida_cli/
frida
/frida-trace
的调试目标方式 概述- 支持 2 种模式:
Spawn
和Attach
- Spawn 模式:只有一种写法
-f TARGET
- TARGET 是 app 包名 或 Executable 二进制文件名
- Attach 模式:有多种写法=针对 app 或 Executable 有不同写法
- 同时支持app 或 Executable的:
-p PID
- PID 是 app 或 Executable 的进程 ID
- 针对Executable的:
-n NAME
- NAME 是 Executable 的二进制文件名,比如
amsaccountsd
- NAME 是 Executable 的二进制文件名,比如
- 针对app的:
-N IDENTIFIER
- IDENTIFIER 是 app 的包名,比如
com.apple.Prefrences
- IDENTIFIER 是 app 的包名,比如
- 特殊的:针对当前手机中正在运行的
frontmost
最前台的:-F
- 由于是,当前最前台的正在运行的= 那只能是带页面显示的 app,且也无需再加额外参数指定 app
- 同时支持app 或 Executable的:
- Spawn 模式:只有一种写法
- 支持 2 种模式:
比较好用的 frida 代码仓库