协议分析与重放:从抓包到定位签名,别一上来就硬伪造
协议分析最容易把人带进一个坑:看见请求包了,就忍不住立刻开始写重放脚本。结果写半天发现不是少 header,就是少签名,再不然就是时间戳、nonce、设备信息、会话上下文全都不对。最后陷入一种很熟悉的状态:我觉得我已经很接近了,但就是过不去。
先说结论:重放不是先伪造,而是先还原约束
一个请求能不能成功,往往不只取决于“URL + body”。真实系统里常见的约束包括:
- Cookie / token
- 时间戳
- nonce
- 签名
- 设备标识
- 会话顺序
- 前置接口返回值
所以更稳的打法是:先弄清楚请求为什么成立,再考虑怎么重放。
第一步:先抓“稳定样本”
抓包不是抓到就算完,最重要的是抓到可对比的样本。我更建议至少准备两到三组:
- 同一操作重复两次
- 改一个字段再请求一次
- 不同账号做同一动作
有了对照,你才看得出哪些字段是稳定的,哪些字段是动态的。
第二步:把字段先粗分,不要急着全解释
很多人一上来就想知道每个字段什么意思,这其实没必要。更高效的做法是先粗分:
- 明显业务字段
- 明显会话字段
- 明显设备字段
- 明显签名相关字段
- 暂时看不懂但会变的字段
先把字段按角色分层,比一开始就死磕每个字节更划算。
第三步:优先判断谁在“约束请求合法性”
这才是重头戏。通常最需要重点盯的有:
- 签名字段
- 时间戳/nonce
- token/cookie
- 设备摘要或指纹
因为这些字段不是“业务内容”,而是在决定“服务器认不认你这次请求”。
怎么判断某个字段更像签名?
- 长度固定
- 十六进制 / Base64 风格明显
- 同样参数改一点,它就整体变化
- 它通常放在 header、query 或 body 的固定位置
- 代码里它生成前常伴随排序、拼接、摘要、加密等动作
如果一个字段同时符合这些特征,那它大概率值得优先追。
第四步:别只盯请求包,得回到客户端里找生成路径
只靠抓包能知道“长什么样”,但很难知道“为什么这样长”。所以最终还是得回到客户端逻辑:
- 谁在组装参数
- 谁在排序
- 谁在拼接字符串
- 谁在做 hash / HMAC / AES / 自定义混淆
这时候你会发现,很多你在抓包里看起来像玄学的字段,一回到代码里就突然变得非常具体。
最常见的误区
误区 1:看到 403 / 401 就只会补 header
header 确实重要,但很多失败真正缺的不是 header,而是签名链路没复现对。
误区 2:以为 token 正确就万事大吉
很多请求还依赖时间窗、一次性随机数、设备状态或前置步骤。token 只是其中一个条件,不是全部条件。
误区 3:盲猜加密算法
如果你连输入是什么、输出是什么、调用顺序是什么都没搞清楚,就开始猜 AES、RSA、SM4,这种效率一般都很差。
误区 4:一失败就怀疑服务器有风控
风控当然可能存在,但在那之前,先把本地链路确认干净。很多“疑似风控”其实只是参数没对齐。
我更推荐的协议分析路径
- 抓几组稳定样本做对照
- 把字段分成业务字段和约束字段
- 优先锁定签名/时间戳/nonce/token
- 回到客户端找生成路径
- 最后才写自动化重放脚本
这套顺序的核心思想是:先搞懂请求为什么能成立,再写程序去复现它。
什么时候该用动态手段?
一旦你遇到这些情况,就别光靠抓包死扛了:
- 签名字段完全看不出规律
- 同样输入每次结果都变
- 请求发送前有一串本地处理链
- 关键参数似乎来自内存中的运行时对象
这时候更有效的做法通常是:
- 在组包函数前后下断点
- hook 签名函数输入输出
- 观察排序、拼接、摘要的真实顺序
- 对比发送前后的最终 header/body
什么叫“真正完成一次重放”?
不是“偶尔碰巧成功一次”,而是你已经知道:
- 哪些字段是固定的
- 哪些字段是动态生成的
- 它们分别从哪里来
- 最小成功条件是什么
只有到这个程度,你的重放才算有工程价值,而不是一次撞大运。
给新手的一句最实在的话
如果你现在卡在“包长得差不多,但就是过不去”,先别急着继续补字段。回头问自己这几个问题:
- 我分清业务字段和约束字段了吗?
- 我知道哪个字段真正决定合法性吗?
- 我验证过它的生成路径,而不只是猜吗?
结尾
协议分析和重放,说到底是一件很工程化的事。它不神秘,也不靠玄学,真正难的是把一堆零散现象——抓包结果、动态参数、签名逻辑、会话状态——整理成一条清晰链路。
你只要把这个顺序守住:
- 先抓稳定样本
- 再拆字段角色
- 再定位约束字段
- 最后复现生成逻辑
很多本来很像黑箱的东西,最后都会被拆成几个非常具体、可以逐项验证的问题。