[App逆向]环境搭建下篇------逆向源码+hook
免责声明:本教程仅供技术学习和安全研究使用,禁止用于任何非法用途。逆向他人 App 前请获得授权。
环境搭建
1. 安装jadx------逆向代码
1.安装jadx
方式一:mac用户可直接通过brew安装
bash
brew install jadx
# jadx --version
1.5.1

方式二:如果不想通过brew安装的也可以直接下载zip包
访问Github:https://github.com/skylot/jadx/releases/tag/v1.5.5下载jadx zip包

- 解析apk源文件
bash
# 1. 启动jadx可视化页面
## mac/linux用户
jadx-gui
## Windows用户,双击即可启动
jadx-gui.bat
# 2. 将需要反编译的apk拖入jadx可视化页面即可

2. 安装Frida------Hook
Hook 是一种在程序运行时动态修改或拦截函数调用、参数或返回值的技术。在 Android 安全研究、逆向分析以及自动化测试中,Hook 技术扮演着至关重要的角色。
目前 Android 生态中主流的 Hook 框架主要有两种,而本文将重点介绍逆向中最常用的 Frida 框架。
Frida 采用 C/S 架构(客户端/服务端),安装分为 PC 端(客户端)和手机端(服务端)两部分。
1.安装 PC 端(客户端)
bash
# 确保已安装 Python 环境,使用 pip 安装:
# 推荐指定版本安装(PC 端和手机端版本保持一致,以保证稳定性):
pip install frida==17.6.2 frida-tools
# 安装最新版
# pip install frida frida-tools

- 安装手机端(服务端)
第一步:确认设备 CPU 架构
bash
adb shell getprop ro.product.cpu.abi

第二步 :下载对应版本的 frida-server
前往 Frida Releases 下载。
📌 下载原则:版本号与 PC 端一致,架构与手机匹配。 例如:手机为 arm64-v8a,PC 端 Frida 版本为 17.6.2,则下载 frida-server-17.6.2-android-arm64.xz。下载后直接双击解压即可。
第三步:部署到手机
bash
# 1. 推送到手机临时目录
adb push frida-server-17.6.2-android-arm64 /data/local/tmp/
# 2. 进入手机 Shell 并提权
adb shell
su
# 3. 赋予执行权限并后台运行
chmod +x /data/local/tmp/frida-server-17.6.2-android-arm64
/data/local/tmp/frida-server-17.6.2-android-arm64 &
## 如果要退出Frida hook,执行exit命令即可
💡 建议重命名 frida-server 文件(如 fs),既方便输入,也能规避部分 App 对 "frida-server" 文件名的字符串检测。

第四步:检查是否能hook
bash
# 本地mac执行下面命令,列出已连接的设备
frida-ls-devices
# 查看当前手机上活跃的进程
frida-ps -U

比如我就hook下我的设置应用,首先打开设置应用,然后编写js代码
main.js:
javascript
Java.perform(function () {
console.log("[*] Hook script loaded successfully!");
// Hook android.util.Log 的 d() 方法(调试日志输出函数)
var Log = Java.use("android.util.Log");
Log.d.overload("java.lang.String", "java.lang.String").implementation = function (tag, msg) {
console.log("[+] Log.d called");
console.log(" Tag: " + tag);
console.log(" Message: " + msg);
// 调用原始方法,保持原有日志输出
return this.d(tag, msg);
};
});
bash
# 终端执行下面命令,进行hook。然后点击任意子模块,比如【通知模块】等
frida -U -n "设置" -l main.js


出现有日志打印,表示hook没问题。
拓展:Frida Hook 有两种方式,分别是 附加模式(Attach) 和 孵化模式(Spawn)
bash
# 1. 附加模式 (Attach) -- 进程已运行时
#Frida 连接到已经在运行的进程,适合对已经打开的应用进行 Hook,或者需要动态注入脚本的场景。例如:
frida -U -n "设置" -l main.js
# 2. 孵化模式 (Spawn) -- 应用未启动时
#Frida 先启动应用(孵化进程),然后立即注入脚本,适合需要 Hook 应用启动过程中的初始化代码或 onCreate 等早期方法。
#-f 后跟包名,表示启动该应用。
#--no-pause 让应用自动继续运行(否则需要手动调用 resume())。
frida -U -f com.android.settings -l main.js --no-pause
| 特性 | Attach (附加) | Spawn (孵化) |
|---|---|---|
| 目标状态 | 进程已存在 | 进程未启动 |
| 能否 Hook 启动过程 | ❌ 可能错过早期方法 | ✅ 可 Hook 从 onCreate 开始的所有代码 |
| 命令标志 | -n 或 -p | -f |
| 常见用途 | 动态注入、调试已运行应用 | 分析应用启动流程、绕过反调试 |
实战案例
App逆向常规思路:从抓包找到可疑参数 → 静态分析定位代码 → 动态 Hook 验证猜想 → 编写脚本模拟请求。
| 术语 | 核心任务 | 典型应用场景 | 工具示例 |
|---|---|---|---|
| 抓包反编译 | 静态分析:通过抓包获取接口参数,再反编译APK找到对应的加密/签名代码逻辑 | 分析通信协议、查找硬编码密钥、理解功能实现 | Charles + Jadx |
| 抓包逆向 | 动态分析:在抓包基础上,通过Hook技术动态监控或修改加密算法、签名参数 | 破解加密参数、绕过签名校验、模拟请求、自动化脚本 | Charles + Frida |
下面我们将以"尿大夫"App登录接口为例,我们先用抓包反编译定位到 sign 字段的生成算法(静态分析),再用抓包逆向编写Frida脚本动态Hook该算法,验证其输入输出,甚至篡改签名(动态分析)。
1. 抓包反编译
尿大夫.apk,反编译破解登录接口
APK下载地址:https://apkpure.com/niao-da-fu/com.uulife.medical.activity/download
- 配置好Charles抓包,然后手机打开apk
- 输入用户名密码,点击登录,抓取对应接口

- 观察请求体,我们会发现主要是sign和devisetoken字段比较特殊,那么我们就需要挨个尝试,看哪些是需要我们逆向的

- 尝试Charles compose,移除部分字段,观察哪些字段是必须的
- 首先移除devisetoken字段

- 我们会发现移除devisetoken字段后,请求依然没问题

- 按照上面流程我们尝试移除sign字段,会发现移除之后状态码不一样了,出现了报错,那么说明sign字段是需要我们逆向的。
其他字段都是除了时间戳都是固定的,大家可以多请求几次观察

- 打开jadx,将apk包拖入jad中。进行逆向分析
- 主要是这个sign字段,所以我们全局搜索这个sign,这个sign字符是固定的,我们推测目标是一个map,且通过put方式设置到请求参数中

- 双击进入该代码文件

- 我们发现sign是通过SafeUtils.getSign方法获取到的,那么我们选中getSign方法,鼠标右键,点击跳转到方法声明处,查看底层实现逻辑

- 于是我们就找到了底层加密逻辑,接着直接复制给AI,让它给我们一个python版本


- 最后完善我们的python代码,实现登录逻辑
python
import requests
import time
import hashlib
from urllib.parse import parse_qsl
channel = "android"
def getSign(j):
try:
str1 = "niaodaifu" + str(j)
md5_1 = hashlib.md5(str1.encode('utf-8')).hexdigest()
part1 = md5_1[12:30]
str2 = channel + str(j)
md5_2 = hashlib.md5(str2.encode('utf-8')).hexdigest()
part2 = md5_2[12:26]
return part1 + part2
except Exception:
return ""
def query_to_dict(query_string):
return dict(parse_qsl(query_string))
phone = input('请输入手机号/邮箱:')
password = input('请输入密码:')
sign = getSign(int(time.time()))
print('----',sign)
q = 'password=%s&mobile=%s&channel=android&sign=%s&time=%s&mechanism=0&platform=1' % (
password, phone, sign,int(time.time()))
# 实现query转字典
data = query_to_dict(q)
res = requests.post('https://api.niaodaifu.cn/v4/site/loginnew', json=data, verify=False)
print(res.json())
- 运行代码,观察效果,成功逆向

2. 抓包逆向(动态Hook)
目标:使用 Frida 动态 Hook getSign 方法,验证其输入输出,甚至篡改签名。
- 基于上面的反编译,我们知道加密是通过SafeUtils.getSign方法实现的。于是可编写 Frida Hook 脚本 hook_sign.js

js
Java.perform(function () {
// 定位 SafeUtils 类
var SafeUtils = Java.use("com.uulife.medical.utils.SafeUtils");
// Hook getSign 方法(注意参数类型为 long)
SafeUtils.getSign.implementation = function (timestamp) {
console.log("[*] getSign 被调用");
console.log(" 参数 timestamp (long): " + timestamp);
// 调用原始方法,获取原始签名
var originalSign = this.getSign(timestamp);
console.log(" 原始签名: " + originalSign);
// 可选:篡改签名(例如在后面加 "hacked")
var fakeSign = originalSign + "hacked";
console.log(" 篡改签名: " + fakeSign);
// 返回篡改后的签名(演示修改返回值)
return fakeSign;
// 若想保持原逻辑,则返回 originalSign
};
console.log("[*] Hook 安装成功,等待登录操作...");
});
- 检查Frida-server是否运行,若没运行,则启动运行
bash
# 检查是否Android是否运行
adb shell
su
ps | grep frida
# 若未运行则运行Frida-server
/data/local/tmp/frida-server-17.6.2-android-arm64 &

检测到Android未运行Frida-server,则执行命令运行。
- 在手机上打开尿大夫 App,然后运行Hook
bash
# 通过应用名定位
frida -U -n "尿大夫" -l hook_sign.js
# 或者通过包名进行hook
frida -U -n com.uulife.medical.activity -l hook_sign.js

- 输入尿大夫App账号密码,点击登录,观察 Frida 控制台输出
bash
[*] getSign 被调用
参数 timestamp (long): 1775641135
原始签名: d9828d465a091f9bba31f28710172db3
篡改签名: d9828d465a091f9bba31f28710172db3hacked
由于我们篡改了签名,服务器会返回签名错误(如 401),证明 Hook 生效且成功修改了参数。基于此,我们可以确认apk登录后台确实调用了com.uulife.medical.utils.SafeUtils.getSign方法。

当然,验证猜想只是Hook最基础的功能。Hook 的真正威力在于动态篡改------可以让 App 做任何你想让它做的事,比如:
- 绕过支付校验
- 修改游戏金币
- 禁用广告
- 自动回复聊天消息
- 抓取加密数据
当然,这些行为都需要遵循相关法律法规。