在客户端与服务端的交互链路中,签名算法是防篡改、防重放、鉴权校验的核心防线,也是逆向工程、协议分析领域最常遇到的防护手段。无论是 Web 前端的 JS 签名、移动端 App 的 Native 签名,还是小程序、桌面端的加密逻辑,其逆向思路都存在高度通用的套路与方法论。
本文系统梳理签名算法逆向的全流程技巧,覆盖定位、识别、还原、对抗四大阶段,总结可复用的实战套路。
一、签名算法快速定位:从入口到核心函数
逆向的第一步永远是定位,找不到签名生成的代码位置,后续分析无从谈起。主流定位手段按优先级排序如下:
1. 全局特征字符串搜索
这是成本最低、见效最快的定位方式,绝大多数签名代码都会留下可检索的特征。
- 直接搜索关键字:
sign、signature、encrypt、hash、md5、sha、hmac、token、timestamp、nonce、appkey、secret等,覆盖函数名、变量名、常量字符串。 - 搜索参数名:抓包获取请求参数后,直接搜索签名对应的字段名(如
sign、sig、_sign),顺着参数赋值回溯生成函数。 - 搜索算法常量:标准加密算法自带固定魔数,例如 MD5 的
0x67452301、SHA1 的0x67452301/0xEFCDAB89、AES 的 S 盒常量、RSA 的大质数特征,直接搜十六进制常量可秒级定位算法实现。
2. 网络请求堆栈回溯
签名一定生成在请求发出之前,顺着网络调用栈向上追溯是最精准的路径。
- Web 端:在浏览器 DevTools 的 Network 面板给目标请求下断点,查看 Call Stack,逐层向上找到参数组装、签名计算的函数。
- 移动端:用 Frida Hook 网络库(OkHttp、NSURLSession、curl 等),在请求发送前打印调用栈,定位签名生成的上层函数。
- 通用技巧:给常见的请求发送函数下断(如
fetch、XMLHttpRequest.send、okhttp3.Request.Builder.build),回溯参数构造逻辑。
3. 输入输出断点法
当代码混淆严重、字符串不可搜时,用已知输入反推位置。
- 构造固定输入(如固定的
timestamp、固定参数),在内存中搜索该字符串的引用,找到被传入的加密函数。 - 计算已知签名结果,在内存中搜索结果值,反向定位生成该结果的函数返回处。
二、算法类型识别:判断用了哪种签名方案
定位到函数后,第二步是快速判断算法类型,避免逐行分析汇编 / 混淆代码。
1. 经典哈希类签名
最常见的签名方案,通常是参数拼接 + 密钥 + 哈希计算。
- MD5/SHA1/SHA256:输出长度固定(32/40/64 位十六进制),输入相同则输出完全一致,无密钥时为纯哈希,带密钥则为 HMAC。
- 识别技巧:观察输出长度;查看代码中是否有 64 字节(HMAC)的密钥填充逻辑;是否存在标准的四轮循环、常量数组。
- 常见变体:参数按字典序排序后拼接、首尾拼接密钥、多次哈希(如 MD5 两次)、截取部分位数。
2. 非对称加密类签名
安全性更高,常用于核心接口、支付、登录等场景。
- RSA 签名:通常是 SHA1/RSA 或 SHA256/RSA,签名结果长度较长(128/256 字节对应 1024/2048 位密钥),公钥通常内置在客户端。
- ECC/ECDSA:椭圆曲线签名,密钥更短,常见于移动端、物联网设备,代码中会出现椭圆曲线参数、点运算逻辑。
- 识别技巧:查找大整数运算、模幂运算、曲线参数常量;搜索公钥字符串(如
-----BEGIN PUBLIC KEY-----)。
3. 对称加密与编码类签名
部分场景会用 AES、DES 加密后做签名,或 Base64 / 自定义编码混淆。
- 特征:输出可解码,密钥固定,输入变化时输出呈块级变化;常伴随 Base64、URL 编码、十六进制转换。
- 注意区分:编码不是加密,Base64、Hex 只是编码格式,真正的签名逻辑在编码之前。
4. 自定义混淆算法
厂商自研的签名逻辑,无标准常量,通常是位运算、置换、查表、循环哈希的组合。
- 识别特征:找不到标准算法常量;逻辑琐碎、大量异或移位;伴随自定义 S 盒、置换表。
- 应对思路:提取核心函数,输入多组样本,观察输入输出映射关系,逐步还原运算逻辑。
三、通用还原套路:从定位到可复现
定位并识别算法后,目标是完整还原签名逻辑,写出可独立运行的签名生成代码。
1. 参数提取与拼接规则还原
签名的核心往往不是算法本身,而是参数的选取、排序、拼接规则和密钥。
- 固定变量:确认哪些参数参与签名(是否包含时间戳、随机数、设备信息、版本号)。
- 排序规则:是否按 key 字典序排序、是否剔除空值、是否剔除 sign 字段本身。
- 拼接格式:键值对用
=还是直接拼接、是否用&分隔、首尾是否追加固定密钥。 - 实战技巧:Hook 签名函数的入参,直接打印拼接完成的原始字符串,是最快的还原方式。
2. 密钥与盐值提取
绝大多数签名都依赖固定密钥或盐值,找到密钥就完成了 80% 的工作。
- 硬编码密钥:直接在代码常量、字符串资源、配置文件中搜索,JS 中常写死在配置对象里,Native 中常存于常量段。
- 动态生成密钥:密钥由设备信息、包签名、时间戳等派生,需追踪密钥的生成链路。
- 密钥分片:密钥拆分成多段存储,运行时拼接,需在内存中 Hook 最终拼接结果。
3. 动态 Hook 抓中间值
静态分析困难时,动态 Hook 是最高效的还原手段。
- Web 端:用 Tampermonkey 注入脚本,Hook 签名函数,打印入参、中间值、返回结果;对混淆 JS 可在关键位置插桩。
- Android 端:Frida Hook 目标方法,打印参数和返回值;Native 层 Hook 加密函数地址,抓取明文输入和密文输出。
- iOS 端:Frida / Monolith Hook 加密相关函数,利用 Mach-O 符号表或字符串交叉引用定位。
- 核心思路:不纠结内部实现,先抓输入输出,验证算法类型,再补全细节。
4. 等价移植与验证
还原后必须做一致性验证,确保和原生结果完全一致。
- 取多组相同输入,分别用原生和还原代码计算,对比输出是否完全一致。
- 注意大小写、编码格式(UTF-8/GBK)、填充方式(PKCS5/PKCS7)、字节序等细节差异。
- 存在随机数、时间戳时,固定随机种子和时间,验证确定性部分是否一致。
四、常见对抗场景与破解套路
实际逆向中很少遇到裸奔的标准算法,通常伴随代码混淆、反调试、环境检测等防护。
1. JS 签名对抗
Web 端签名常见混淆手段:控制流平坦化、字符串加密、无限 debugger、域名绑定、虚拟机保护。
- 无限 debugger:替换 debugger 关键字、Hook
Function.prototype、禁用断点、定时器置空。 - 控制流平坦化:使用 AST 工具还原结构,或直接 Hook 关键函数跳过内部逻辑。
- JS 虚拟机(如 JSC、VM2、自定义解释器):定位解释器入口,Hook 字节码执行,抓取关键运算的输入输出。
- webpack 打包场景:定位
__webpack_require__,通过模块导出特征找到签名模块,直接导出函数调用。
2. Native 签名对抗
移动端 SO 库常见防护:加壳、UPX 压缩、反调试、指令混淆、VMP 虚拟化。
- 脱壳先行:先处理加固壳(梆梆、爱加密、360 加固等),拿到原始 SO 再分析。
- 反调试绕过:Hook
ptrace、syscall、android.os.Debug.isDebuggerConnected等检测点。 - 指令混淆 / VMP:优先 Hook 函数出入口抓参数,不硬杠内部逻辑;必要时用 Unicorn 模拟执行。
- JNI 动态注册:通过
RegisterNativesHook 获取函数地址,映射到 Java 层方法。
3. 签名校验对抗
部分服务端不仅校验签名,还会校验客户端环境、证书、设备指纹。
- 优先还原纯签名逻辑,不要上来就改客户端,避免触发风控。
- 遇到签名与设备绑定的情况,提取设备指纹参数,模拟固定设备信息。
- 存在签名时效时,同步校准时间戳,确保请求时间在合法窗口内。
五、效率提升:工具链与惯用技巧
1. 常备工具集
- Web 逆向:Chrome DevTools、Fiddler/Charles、AST Explorer、js-beautify、Tampermonkey。
- 移动端逆向:Frida、Objection、IDA Pro、Ghidra、jadx、Apktool、LLDB。
- 通用辅助:CyberChef(加解密编码转换)、Python(复现算法、写脚本)、Unicorn(模拟执行)。
2. 优先级原则
- 先抓包看参数,再定位代码,不盲目反编译全量分析。
- 先搜字符串常量,再看函数名,最后才读汇编 / 混淆代码。
- 先动态 Hook 抓输入输出,再静态还原细节,能 Hook 就不硬读。
- 先验证算法类型,再抠具体实现,避免南辕北辙。
3. 常见坑点提醒
- 注意编码差异:UTF-8 与 GBK、字节与字符串、Hex 与 Base64。
- 注意字节序:大端小端在跨平台移植时极易出错。
- 注意填充规则:哈希类的填充、对称加密的填充方式直接影响结果。
- 注意多轮加密:一次签名可能包含多次哈希、多次加密、编码嵌套。
六、总结
签名算法逆向的本质,是在层层防护中找到「输入参数 + 密钥 + 算法 + 编码」四个要素,再通过等价复现实现签名逻辑的移植。整个过程遵循「定位 → 识别 → 提取 → 验证」的标准化流程,绝大多数场景都可以套用上述套路解决。
对于逆向从业者而言,熟练掌握通用套路、建立工具化思维,远比死磕单个算法更重要。真正的难点往往不在加密本身,而在混淆对抗、环境检测、风控策略等外围防护,这也是后续持续深入的方向。