Frida in CTF Android Reverse Engineering
原理
Frida是一款跨平台的动态代码插桩框架,核心原理是向目标进程注入包含 Frida Runtime 的代码库。该 Runtime 在进程内构建轻量级 JavaScript 环境,并利用底层引擎(Gum)动态修改目标函数的内存指令。通过插入跳转指令(Inline Hook)等,将执行流重定向到代理函数(trampoline/thunk),代理函数负责调用用户编写的 JavaScript 回调,实现拦截、修改参数/返回值或追踪逻辑
Frida 通过多种方式(例如 Android 的 ptrace,Windows 的 DLL 注入,iOS 的 Dylib)将自己的动态库注入到目标进程地址空间中,核心思想是在目标进程内存中加载 Frida 动态库并初始化 Gum 插桩引擎,最终建立双向通信通道,使 JavaScript 脚本能动态操控原生代码执行流
组成
frida-server (目标端): 在目标设备或模拟器上运行的后台服务
frida-gadget (嵌入式): 核心功能与frida-server相同,存在形式为动态链接库 (*.so/*.dylib/*.dll),可静态嵌入到目标应用程序中,无需每次注入,适合在无 root 环境中使用
frida-core: 由 server 或 gadget 加载的核心库,包含 Frida运行最重要的组件gum,提供了将 Native 与 JavaScript连接起来的桥梁
frida-gum:实现代码插桩,其中Interceptor提供hook主要功能,Stalker提供代码追踪功能
frida CLI / Python Bindings / Node.js Bindings (客户端): 开发者使用的工具或库,通过进程间通信(IPC)与目标端的 server 或 gadget 通信,Python/Node.js Bindings允许开发者在 Python 或 Node.js 环境中直接调用 Frida 的功能,frida CLI提供快速交互式操作,需提前写入 .js 文件,依赖命令行参数
环境
电脑模拟器
本地环境:雷电模拟器Android9 x64
root
先安装Magisk(面具),这里把模拟手机型号从PCLM10改为PCLM9发现就有直接安装选项
安装MagiskHidePropsConfig模块
共享文件夹在shared/Pictures目录
连接设备
windows上的模拟器选择下载frida-server-16.2.1-android-x86_64.xz,双击解压出二进制文件,然后通过adb push到/data/local/tmp
报错10061说明模拟器没开
adb devices查看设备,adb root获取root权限,adb shell`连接到远程
进入frida-server安装目录cd /data/local/tmp,然后运行frida-server
进行端口转发监听,使电脑上的 Frida 客户端能够访问模拟器里的 frida-server,如果用的是 libfrida-gadget.so 就需要adb forward tcp:27042 tcp:27042
经验总结
1.打开的方式安装不了可以拖动或者adb install
2.可通过下面路径查找日志
3.如果处于开发者模式一直未被调试
可以关闭开发者模式
4.如果是多开的模拟器需要先找到对应端口再连接:.\nox_adb -s 127.0.0.1:62026 shell
手机真机
root
方式主要有:
- Magisk修补Boot
- KernelSU/APatch内核层root
- 内置root功能的第三方或 userdebug ROM(包含 Android 操作系统及相关分区文件的系统固件或刷机包),例如LineageOS userdebug
设备用的是Google的pixel手机
在手机开发者模式下打开OEM解锁+USB调试
进入Bootloader Mode找不到设备需要在设备管理器选择带黄色感叹号的设备更新驱动
解锁 Bootloader
获取与设备号和版本号一致的Factory Image,连续解压得到boot.img
https://developers.google.com/android/images?utm_source=chatgpt.com#bonito
手机安装Magisk,Magisk安装boot.img,生成magisk_patched_xxx.img
在Bootloader Mode下临时从img镜像启动:fastboot boot xxx.img
临时root正常后永久刷入Magisk patched boot:fastboot flash boot magisk_patched_xxx.img
连接设备
同一网段下手机开启开发者模式,允许usb/无线调试
无线调试Android11及以上需要先配对,手机选择使用配对码配对设备
查看手机架构,下载对应架构frida-server
Objection
Objection 在 Frida 上增加了一层命令封装
/data/local/tmp目录下用root权限启动frida-server
搜索特定进程:frida-ps -U | grep -i settings
查看进程对应真正包名:frida-ps -Ua
输入空格键会有提示与补全
静态
模拟器上启动软件后再去注入mobile包:objection -g mobilego explore
有时候进程名用空格隔开,用引号标注
在内存中所有已加载的类中搜索包含game的类:android hooking search classes game
查看com.android.settings.DisplaySettings类有哪些方法:android hooking list class_methods com.android.settings.DisplaySettings
直接生成代码但可能没参数:android hooking generate simple com.android.settings.DisplaySettings
进入显示设置,软件如果没有做校验,可以直接使用这个命令跳过注册登录:android intent launch_activity com.android.settings.DisplaySettings
动态
hook类:android hooking watch class android.bluetooth.BluetoothDevice
hook方法,查看参数、返回值和调用栈:**android hooking watch class_method game.Game.checkflag --dump-args --dump-return --dump-backtrace**
在模拟器输入符合题目要求的字符串后,再Called game.Game.checkflag(java.lang.String),得到return值
还可以import js代码,效果和直接frida类似
基本用法
包名通过frida-ps -Ua查看
Frida两种启动方式的区别:
1 | spawn` 模式:frida 重新打开一个进程并挂起,在启动的同时注入frida代码 `frida -U -f 包名 -l js路径 |
以下代码基于frida16
java层
hook自定义函数
hook native方法
1 | function main() { |
hook模拟器检测和调试检测函数
1 | Java.perform(function(){ |
hook系统函数
1 | Java.perform(function () { |
主动调用
hook InMemoryDexClassLoader.loadClass()方法,Checker 不是当前默认 ClassLoader 加载的类,需要反射调用getKey获取密钥
1 | function main() { |
native层
hook自定义函数
_Z10murmur3_32PKcjj是真实导出表的名字,murmur3_32是demangle后的名字
1 | var func_addr = Module.findExportByName("libmidand.so" , "_Z10murmur3_32PKcjj"); |
hook之后在模拟器输入字符然后点login
发现能看到返回值
hook系统函数
v6参数(账号)会经过好几次加密,需要hook strcmp函数查看s2(密码)和比较的值
!
1 | function hook_strcmp(chall) { |
主动调用主函数中未被调用的方法
1 | function hook(){ |
frida-dump
通过 Frida 注入脚本到目标进程,动态获取进程运行时内存信息,包括已加载的 DEX 文件、Native 库以及关键内存区域,并根据内存映射信息将其导出为原始文件(如 .dex、.so)。对于经过加固、混淆或运行时解密后的代码,通常需要结合动态分析进一步恢复
在 ART 类加载过程中,FindClassDef 会遍历当前 ClassLoader 关联的 DexFile 集合,根据目标类描述符查找对应的 ClassDef。当找到目标类所在的 DexFile 及 ClassDef 后,ClassLinker::DefineClass 使用这些信息创建对应的 Class 对象,并继续完成字段解析、方法加载以及代码链接
frida-dump 的核心思想是在 ART 类加载关键路径上 Hook ClassLinker::DefineClass,获取正在加载类对应的 DexFile 对象,通过读取 DexFile 中保存的 begin 地址和 size 信息定位内存中的完整 dex 数据,并将其导出
frida-dexdump
frida-dexdump 支持在 App 启动阶段注入,通过捕获运行时已经解密并加载到内存中的 dex 文件,可以直接导出动态加载后的 dex
连接frida-server之后用 adb shell pm list packages找到真正的包名(有时候和jadx里面显示的不太一样)
frida-dexdump -U -f com.example.wyy直接dump出动态解密的dex,会自动修复
-d开启深度搜索模式
进阶用法
2024CISCN-first_game-rust_baby
字符串比较循环次数侧信道
0x140003E8是循环比较,每一个字符成功都会进行下一轮循环
因此考虑用frida插桩爆破
1 | var number = 0 |
验证发现可行
1 | import subprocess |
可以采取一点点增加的方式,每次报错都要去掉最后一个候选字符,中间有四次爆破得不到新字符,默认从当前字符往后遍历
2023NCTF-ez_VM
opcode执行次数侧信道
其中hook的两个位置分别为opcode分发和putchar
尝试的脚本,发现可以hook
调用exit函数在获取发送过来的number之后结束程序,可以得到更快的爆破速度
1 | var number = 0 |
自动化脚本,遇到报错时需要往flag字符串里添加已知正确字符才能继续爆破
1 | import subprocess |
最后一个字符需要爆破,不过可以根据前面内容先猜#
2024ZJCTF-Re3
题目提示debug,函数里面有tls得到1.exe
v4像key,后面是分组加密
一眼aes但是无法解密
用frida尝试去hook输入,密文,key等,执行frida -l .\hook.js -n 1.exe
1 | var inter=setInterval(function () { |
input flag有变化说明进入aes加密的明文有偏移,总共33次调用sub_140001380,对应3组密文,所以密文长度为48
输入0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&’()*+,-./:;<=>?@[\]^_得到新的映射表
修改后的密文
最终脚本,PlainText1和PlainText2都是用来存放中间变量
1 |
|
最后三段flag合并得到:flag{fc6b0f5a-8f78-4d68-86bc-fe10662969fb}
2023巅峰极客-m1_read
RFID的门禁卡程序
识别出来是AES
白盒加密是一种特殊的加密方法,它允许加密数据在不受信任的环境中被解密而无需暴露密钥本身,不会直接保存一个明显的16字节 key,而是把密钥融合进大量查表、轮函数和编码变换中
针对白盒加密可以使用DFA攻击,在倒数第一轮列混淆和倒数第二轮列混淆之间修改中间结果的一个字节,会导致最终密文和正确密文有4个字节不同。通过多次的修改,得到多组错误的密文,然后通过正确密文和这些错误密文推算出加密模式下第10轮的密钥,从而能推算出原始密钥
aes+异或0x66
1 | import frida |
用frida hook key,在第9轮时随机修改中间状态的1个字节,第一次输出可以看作正确密文,后面多次输出是在第9轮随机改一个字节后的错误密文
1 | var baseAddr = Module.findBaseAddress("m1_read.exe") |
利用phoenixAES实现DFA
1 | # s1是前文中的33轮数据,以字符串形式存储(包含换行,否则无法识别) |
用Stark提供一轮密钥暴力破解AES-128
在提供的out.bin里根据M1卡的存储格式,第一行中,4B为校验位,剩下为厂商信息,需要解密的部分为第三行
1 | from Crypto.Cipher import AES |
flag{cddc8d28dabb4ea9}
2024ByteCTF-first_game-极限逃脱
搜索ViewController发现有两个按钮,第一个按钮是输入的数要和随机数相同
第二关限制格式为uuid,之后去掉ByteCTF{},再按 - 切 5 段
{a67be199da4b-b092-bd3e-e777-a67be199da4b}调用CC_SHA256,最后是一些字符映射
需要越狱iPhone运行ipa文件才能hook最终比较的字符串
1 | const moduleName = 'ByteCTFDemo' |
参考链接:
https://bbs.kanxue.com/thread-280758.htm
https://bbs.kanxue.com/thread-280812.htm#msg_header_h2_1
https://blog.csdn.net/Ruaki/article/details/135580772
- 标题: Frida in CTF Android Reverse Engineering
- 作者: j1ya
- 创建于 : 2024-10-28 18:15:48
- 更新于 : 2026-10-05 21:57:39
- 链接: https://j1ya-22.github.io/2024/10/28/frida/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。