type
status
date
slug
summary
tags
category
icon
password
原文链接: https://kevinspider.github.io/fridahookso/
1、frida-env
2、IDA判断Thumb指令集和Arm指令集
- IDA - Options - General - number of opcode bytes - 设置为 4
- 此时查看 IDA VIew 中 opcode 的长度, 如果出现 2 个字节和 4 个字节的, 说明为 thumb 指令集
- 如果都是 4 个字节的, 说明是 arm 指令集;
- 在 Thumb 指令集下, inline hook 的偏移地址需要进行 +1 操作;
3、枚举内存中的so文件
用于查看目标 module 是否被正常加载, 使用
Process.enumerateModules()
将当前加载的所有 so 文件打印出来4、获取指定 so 文件的基地址
5、获取指定 so 文件的函数
通过导出函数名定位 native 方法
通过 symbols 符号定位 native 方法
通过地址偏移 inline-hook 任意函数
6、通过 Intercept 拦截器打印 native 方法参数和返回值, 并修改返回值
onEnter
: 函数(args) : 回调函数, 给定一个参数 args, 用于读取或者写入参数作为NativePointer
对象的指针;
onLeave
: 函数(retval) : 回调函数给定一个参数 retval, 该参数是包含原始返回值的 NativePointer 派生对象; 可以调用retval.replace(1234)
以整数 1234 替换返回值, 或者调用retval.replace(ptr("0x1234"))
以替换为指针;
- 注意:
retval
对象会在onLeave
调用中回收, 因此不要将其存储在回调之外使用, 如果需要存储包含的值, 需要制作深拷贝, 如ptr(retval.toString())
7、通过 Intercept 拦截器替换原方法
8、so 层方法注册到 js 中, 主动调用
address
: 函数地址
returnType
: 指定返回类型
argTypes
: 数组指定参数类型
- 类型可选: void, pointer, int, uint, long, ulong, char, uchar, float, double, int8, uint8, int16, int32, uint32, int64, uint64; 参照函数所需的 type 来定义即可;
9、hook libart 中的 jni 方法
jni
全部定在在 /system/lib(64)/libart.so
文件中, 通过枚举 symbols
筛选出指定的方法10、hook libc 中的系统方法
/system/lib(64)/libc.so
导出的符号没有进行 namemanline
, 直接过滤筛选即可libc.so
中方法替换11、hook native 调用栈
12、jnitrace
1、安装
jnitrace
: https://github.com/chame1eon/jnitrace2、基础用法
ndk
开发是没有办法脱离 [libc.so](http://libc.so)
和 [libart.so](http://libart.so)
进行开发, 所以只要降维打击, 通过 trace
的方式就可以监控到 so
层3、启动命令
例如:
jnitrace -l [libnative-lib.so](http://libnative-lib.so) com.example.myapplication
必要参数
l libname
: 指定要trace
的.so
文件, 可以同时trace
多个.so
文件, 直接使用来
trace
所有的.so
文件; 如:l libnative-lib.so -l libanother-lib.so
orl *
packagename
: 指定要trace
的package name
可选参数
m
: 指定是spawn
还是attach
b
: 指定是fuzzy
还是accurate
i <regex>
: 指定一个正则表达式来过滤出方法名, 例如:i Get -i RegisterNatives
就只会打印出名字里包含Get
或者RegisterNatives
的JNI methods
e <regex>
和i
相反,同样通过正则表达式来过滤,但这次会将指定的内容忽略掉
I <string>
trace导出的方法,jnitrace认为导出的函数应该是从Java端能够直接调用的函数,所以可以包括使用RegisterNatives来注册的函数,例如I stringFromJNI -I nativeMethod([B)V
,就包括导出名里有stringFromJNI,以及使用RegisterNames来注册,并带有nativeMethod([B)V签名的函数。
o path/output.json
,导出输出到文件里。
p path/to/script.js
,用于在加载jnitrace脚本之前将指定路径的Frida脚本加载到目标进程中,这可以用于在jnitrace启动之前对抗反调试。
a path/to/script.js
,用于在加载jnitrace脚本之后将指定路径的Frida脚本加载到目标进程中
ignore-env
,不打印所有的JNIEnv函数
ignore-vm
,不打印所有的JavaVM函数
启动方式
默认使用
spawn
启动, 可以通过 -m attach
设置通过 attach
启动设置回溯器
默认情况下使用
accurate
的精确模式来进行回溯, 可以通过 -b fuzzy
修改为模糊模式监控指定规则的方法
用于指定应该跟踪的方法名, 该选项可以多次提供;
只过滤出
RegisterNatives
相关的内容忽略指定规则的方法
用于指定在跟踪中应被忽略的方法名, 这个选项可以被多次提供;
忽略以
Find
开头的所有方法;4、jnitace 计算偏移地址
0x8e4f3b1
是方法 initSN
方法的绝对地址0xd8e4e000
是 [libmyjni.so](http://libmyjni.so)
基地址使用使用
initSN()V
的绝对地址 0xd8e4f3b1
减去 [libmyjni.so](http://libmyjni.so)
的基地址 0xd8e4e000
, 得到偏移 0x13B1
g
进行跳转到 0x13B1
即可进入方法13、frida-trace
options
基础使用
启动模式
默认使用
attach
模式, 可以指定 -f packageName
使用 spawn
模式启动文件输出
o filepath
指定输出的文件路径, 方便内容过多时进行查看
trace 任意 function
trace 任意 module
根据地址进行 trace
批量 trace
ps: 需要切换到 frida14 版本
1.将traceNatives.py丢进IDA plugins目录中
- 在ida 的python console中运行如下命令即可找到plugins目录:
os.path.join(idaapi.get_user_idadir(), "plugins")
2.IDA中,Edit-Plugins-traceNatives –> IDA输出窗口就会显示如下字眼:使用方法如下: frida-trace -UF -O C:\Users\Lenovo\Desktop\2021\mt\libmtguard.txt
14、frida-hook-libart
hook art
hook_RegisterNatives
hook_artmethod
init libext first time
use hook_artmethod.js
frida-fart-hook
首先拷贝fart.so和fart64.so到/data/app目录下,并使用chmod 777 设置好权限,然后就可以使用了。
如果目标 app 没有 sdcard 权限则需要手动添加; 或者可以修改 frida_fart_hook.js 中的源码, 将 savepath 改为
/data/data/应用包名/
;该frida版fart是使用hook的方式实现的函数粒度的脱壳,仅仅是对类中的所有函数进行了加载,但依然可以解决绝大多数的抽取保护
需要以spawn方式启动app,等待app进入Activity界面后,执行fart()函数即可。如app包名为com.example.test,则
frida -U -f com.example.test -l frida_fart_hook.js --no-pause
,然后等待app进入主界面,执行fart()高级用法:如果发现某个类中的函数的CodeItem没有dump下来,可以调用dump(classname),传入要处理的类名,完成对该类下的所有函数体的dump,dump下来的函数体会追加到bin文件当中。
15、frida 文件写入(frida/hook libc)
frida api
写入文件frida 定义 NativeFunction
写入文件16、hook 读写 std::string
17、hook so 文件加载后马上 hook
18、hook libc kill
19、hook init_array
20、frida dump
frida dump so
frida dump dex
frida dump dex class
21、指针运算符和读写 API
hook so readPointer()
hook so writePointer()
hook so readS32(), readU32()
从指定内存地址读取有符号或者无符号 8/16/21/etc 或浮点数/双精度值, 并将其作为数字返回;
hook so writeS32(), writeU32()
将有符号或无符号8/16/32/等或浮点数/双精度值写入此内存位置
hook so readByteArray(), writeByteArray()
hook so readCString(), writeUtf8String()
22、hook 获取 jni array
23、jni_helper
- 进入目录
~/androidFxxk/idaTools/jni_helper
java -jar JadxFindJNI/JadxFindJNI.jar <apk.path> <output.json>
- ida 中
Script File
运行jni_help
脚本, 路径~/androidFxxk/idaTools/jni_helper/ida/jni_helper.py
- 导入刚才生成的
output.json
文件即可自动识别
- 作者:404False
- 链接:https://blog.404nofoundx.top//article/ded4f89d-044b-4af2-a218-6d9ec638fde3
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。