前阵子分析一个 Android so 的校验逻辑,函数没符号,字符串表也被处理过,能追的线索有限。调用链走到后半段时,我发现目标代码在按固定块大小处理输入,桶里反复出现异或、循环右移和加法,最后往缓冲区里写了整整 32 字节。我把这段反汇编截图发出来,有经验的朋友第一反应就是 SHA-256。哈希算法在二进制里留下的静态特征实在太明显了,尤其 SHA 家族,成员之间看起来像,但只要掌握几个关键常量表和移位规律,基本能做到一眼锁定。
这篇内容围绕 SHA 家族展开,既讲 SHA-1、SHA-2、SHA-3 的版本差异和实现要点,也讲我在逆向样本里常用的辨别技巧。适合做安全分析、病毒分析、JS/App 逆向的朋友,也适合那些想彻底搞清楚摘要算法为什么这么设计、而不只是会调库的开发者。文里所有判断方法都来自实际样本,不是照搬文档。
1. 逆向里与哈希打交道的典型场景:先把算法认出来,后面的动作才有意义
1.1 哈希函数的那几条性质,决定了一开始该怎么找它
哈希算法的核心性质,我总结成对逆向有用的四句话:任意长度输入能变固定长度输出;输入变一点输出变化剧烈;从输出反推输入算不出来;两个不同输入找到同一个输出的难度有保证。第一点让你在调用链上看到“固定数量字节的写内存”,第二点让你能构造测试向量做验证,第三点决定了不能像解密 AES 那样去找逆算法,第四点关系到签名碰撞那些上层利用思路。
第二点在实际逆向里特别有意思。AES 解密会有 S-box、轮密钥加、列混合,即便不认识也能按分组操作的结构去推测。哈希函数同样不神秘:它处理的是“块”,几乎所有叫得上名字的摘要算法都是按 64 字节或者 128 字节一块推进。SHA-