Frida 是一个知名的移动端 Hook 框架
环境配置
分别在 PC 和目标 Android 上配置 Frida:
1 | # 我使用 UV 管理 Python,因此没有一个全局的 Python |
记住 Frida 版本:
1 | $ pip show frida |
在 ADB shell 中查看 Android 设备架构:
1 | $ uname -m |
一般来讲,模拟器采用 x86-64,真机采用 arm64(即此处的 aarch64)
在 Releases · frida/frida 下载对应版本的 Frida-server,例如此处应下 frida-server-17.5.1-android-arm64.xz。
解压得到的文件传输到 Android 上:
1 | adb push frida-server-17.5.1-android-arm64 /data/local/tmp/ |
在 Android 上启动服务端:
1 | adb shell |
现在就可以用 Frida 了 😊
Frida 调试基础
两种模式:Spawn(生成)和 Attach(附加)。Spawn 模式是从头启动应用并调试,Attach 模式是在应用运行时才开始调试。
Spawn 模式:
1 | frida -U -f <TARGET> -l <SCRIPT> |
TARGET:APP 包名或可执行文件名SCRIPT:用于调试的 Python, JS 或 TS 脚本。自己写或者用已有的。如果不附带脚本,则进入交互式调试。
TARGET 需要的包名可以通过 frida-ps -Ua(运行中的应用)/frida-ps -Uai(安装的应用)得到。
Spawn 方式启动后,会立刻暂停运行。需要继续运行,需要手动输入:%resume
旧版本有一个 --no-pause 会自动运行,但新版本已不支持。
Attach 模式:
1 | frida -U -N TARGET -l SCRIPT |
怎么写好一个调试脚本
脚本主要有三类内容:
Interceptor(拦截器):实现 Hook 函数、打印参数等调试操作。每次匹配到(对应函数),都会触发执行代码。ApiResolver(解析器):模糊查找相关函数。只有第一次(解析时)匹配到,才会执行。Stalker(跟踪器):跟踪代码的实际运行的过程。期间可以打印和查看对应的值,便于实现调试真正代码运行的逻辑。
对于 JS 脚本,一个简单的 CTF 示例如下:
1 | // 所有 Java API 调用必须在 Java.perform() 回调中执行 |
这个的脚本的目的是直接获取 Vault 类下的 get_flag() 方法的输出,得到 flag。
一些常用方法:
绕过检测
要用 Frida-server 调试的前提就是 Root,但显然大部分应用都不希望自己被 Frida 或者 Root 调戏,因此会做 Root 检测,一检测到特征就停止程序运行。
但是,代码总是有执行顺序的,只要我在检测前就把特征检测方法给 Hook 掉,你不就检查不出来了吗?另一种就是 “打入内部”,将 Frida-gadget 植入程序,可以实现免 Root 的 Hook。
1 | package com.heroctf.freeda2.utils; |
1 | Java.perform(function() { |
RootBeer 是一个简单的 Root 权限检查库。作者也在 README 中坦陈 RootBeer 可以被绕过(查看 Bypassing Android’s RootBeer Library — Part 1)
本题仅使用 RootBeer 的综合检测方法 isRooted() 来检测 Root,这倒是为我们省去了不少麻烦,因为我们只需要 Hook isRooted() 就行了。