AI 逆向 App 接口逆向实战:某瓣推荐流 _sig 是怎么还原出来的?
AI 逆向 App 接口逆向实战:某瓣推荐流 _sig 是怎么还原出来的?
很多同学学了 Frida、Jadx、IDA 之后,卡在同一个问题上:
“工具都会用,但怎么把它们串成一条完整的分析链路?”
这篇文章我就用一个真实练习案例,把这条链路完整走一遍:目标是豆瓣 Android 客户端 recommend_feed 接口中的 _sig 参数。
我会重点讲三件事:
-
_sig到底怎么生成(算法、拼串、密钥来源) -
为什么很多人算出来总是错(常见误区)
-
遇到 native 反调试时,如何稳定拿到运行期证据
声明:本文仅用于授权环境下的安全研究与逆向学习,不用于任何未授权用途。
一、目标接口与问题定义
目标接口是:
GET https://frodo.douban.com/api/v2/elendil/recommend_feed
请求里有两个关键参数:
-
_sig -
_ts
如果 _sig 不对,服务端会直接拒绝或返回异常数据。所以问题就很明确:还原 _sig 生成逻辑并实现自动化请求。
二、先定策略:静态 + 动态 + 复现
我这次的思路是三段式:
-
Jadx 静态追调用链先找到业务 API 到签名函数的完整路径。
-
Frida 动态抓关键变量把“猜测”变成“证据”,拿到运行期的
secret / sign_text / sig。 -
Python 落地复现实现一份能自动生成
_sig/_ts并拉到真实数据的请求脚本。
这三段缺一不可。只做静态,容易被混淆误导;只做动态,没有全局上下文;不落地脚本,价值不稳定。
三、Jadx 里最关键的调用链
1)业务入口
在业务 API 里能定位到:
-
e6.e.Q(...)组装了elendil/recommend_feed请求。
2)签名注入点
进一步追到网络层拦截器:
-
q9.c会在请求发出前自动追加_sig和_ts。
这一步很关键:说明不是每个业务接口自己算签名,而是统一网络层处理。
3)签名核心逻辑
最终到 q9.b:
-
q9.b.b(Request):从请求头取Authorization -
去掉
Bearer前缀,把 token 传给q9.b.a(...) -
q9.b.a(...)拼出签名原文,再调用lb.c.a(...)
而 lb.c.a(...) 里就是标准:
-
HmacSHA1 -
Base64.encodeToString(..., NO_WRAP)
到这里算法基本就明牌了。
四、最容易踩坑的点:密钥不是 apikey
很多人第一反应是拿 apikey 去做 HMAC,这会直接算错。真实链路里用于 HMAC 的是 n1.c()(client_secret)。
在初始化阶段能看到:
-
网络配置注入了
n1.a()和n1.c() -
其中
n1.c()被签名逻辑使用
结论:
-
apikey:普通公共参数 -
apiSecret(n1.c()):HMAC 密钥
这也是为什么很多“看起来只差一点”的脚本始终过不去。
五、_sig 真实公式(可直接复现)
设:
-
method = GET -
path = /api/v2/elendil/recommend_feed -
enc_path = Uri.encode(path)=>%2Fapi%2Fv2%2Felendil%2Frecommend_feed -
token = Authorization 去掉 Bearer 前缀 -
ts = 秒级时间戳
签名原文:
sign_text = method + "&" + enc_path + "&" + token + "&" + ts
签名值:
_sig = Base64( HMAC_SHA1(secret, sign_text) )_ts = ts
六、对拍:把猜测变成证据
我拿了一组固定样本对拍:
sign_text:GET&%2Fapi%2Fv2%2Felendil%2Frecommend_feed&42c40114121c2cc6c84c033c36548652&1774482261
复算结果:
qwj/PE66ctfqRqEbSZv48N8RSQQ=
与抓包 _sig 完全一致。这说明算法、拼串规则、密钥来源全部闭环。
七、反调试分析:为什么一挂 Frida 就闪退
继续分析 libmsaoaidsec.so,能看到典型反调试痕迹:
-
ptrace -
prctl -
/proc/self/maps -
/proc/%d/cmdline -
/proc/%d/task
动态时也能观察到高频 prctl(15) 和 /proc 路径访问。所以不处理 anti-frida,脚本经常刚挂上就掉。
我的处理策略是 libc 层统一拦截:
-
ptrace/prctl -
open/openat/fopen/opendir/readlink -
strstr/strcmp
把“检测输入”改掉,比硬 patch 某个函数偏移更稳。
八、最终落地成果
这次练习最后产出了两类可复用资产:
1)请求复现脚本
-
main.py -
自动生成
_sig/_ts -
发起
recommend_feed请求并解析数据
实测结果:
-
HTTP 200 -
成功拿到
items数据并打印标题/摘要/链接
2)动态分析脚本
-
一体化脚本(anti-frida +
_sighook + probe) -
可用于后续版本回归验证(升级后看看签名链路是否变化)
九、这次实战的几个关键经验
-
先找统一拦截器,再看业务 API很多签名不在业务层,而在网络层统一处理。
-
“能跑通”不等于“分析对了”一定要做固定样本对拍,才能确认每一步都正确。
-
密钥来源比算法更重要HMAC 算法常见,真正难点在 secret 的来源和初始化时机。
-
anti-frida 要做成策略,不要做成魔法偏移偏移会变,行为特征更稳定。
十、结语
这次案例本质上不是“会不会写 HMAC”,而是:
你能不能把静态、动态、复现三条线真正闭环。
如果你也在做 App 协议逆向,建议你给每次练习都做一份“可执行报告”:
-
链路图
-
核心证据
-
对拍样本
-
可运行脚本
长期坚持,进步会非常快。
夜雨聆风