Lazy loaded image
安卓逆向
安卓逆向Hook So(转)
字数 5076阅读时长 13 分钟
2021-12-17
2024-7-5
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、安装

2、基础用法

ndk 开发是没有办法脱离 [libc.so](http://libc.so) 和 [libart.so](http://libart.so) 进行开发, 所以只要降维打击, 通过 trace 的方式就可以监控到 so 层
notion image

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 or l *
  • packagename : 指定要tracepackage name

可选参数

  • m: 指定是spawn还是attach
  • b: 指定是fuzzy还是accurate
  • i <regex>: 指定一个正则表达式来过滤出方法名, 例如: i Get -i RegisterNatives 就只会打印出名字里包含Get或者RegisterNativesJNI 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 计算偏移地址

notion image
0x8e4f3b1 是方法 initSN 方法的绝对地址
0xd8e4e000 是 [libmyjni.so](http://libmyjni.so) 基地址
使用使用 initSN()V的绝对地址 0xd8e4f3b1 减去 [libmyjni.so](http://libmyjni.so) 的基地址 0xd8e4e000 , 得到偏移 0x13B1
notion image
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

 
notion image
notion image

hook so readPointer()

hook so writePointer()

hook so readS32(), readU32()

从指定内存地址读取有符号或者无符号 8/16/21/etc 或浮点数/双精度值, 并将其作为数字返回;
notion image

hook so writeS32(), writeU32()

将有符号或无符号8/16/32/等或浮点数/双精度值写入此内存位置

hook so readByteArray(), writeByteArray()

hook so readCString(), writeUtf8String()

22、hook 获取 jni array

23、jni_helper

  1. 进入目录 ~/androidFxxk/idaTools/jni_helper
  1. java -jar JadxFindJNI/JadxFindJNI.jar <apk.path> <output.json>
  1. ida 中Script File运行 jni_help脚本, 路径 ~/androidFxxk/idaTools/jni_helper/ida/jni_helper.py
  1. 导入刚才生成的 output.json 文件即可自动识别
上一篇
常见的几种DLL注入技术
下一篇
反制Unidbg

评论
Loading...