1. 逆向工程中的加密算法解析
最近在分析某理财平台的网络请求时,遇到了典型的SHA256withRSA加密方案。这种非对称加密组合在金融类应用中非常普遍,今天就来拆解下具体实现原理和逆向方法。
当我们需要分析这类请求时,通常会遇到两个核心问题:一是如何识别加密类型,二是如何模拟加密过程。通过浏览器开发者工具的Network面板,可以清晰看到请求参数被加密成密文字符串,而响应数据同样经过加密处理。这种保护措施在涉及资金交易的场景中尤为重要。
2. 加密方案技术拆解
2.1 SHA256哈希算法特点
SHA256作为安全哈希算法家族的一员,具有以下关键特性:
- 固定输出256位(32字节)哈希值
- 抗碰撞性强,难以找到两个不同输入产生相同哈希
- 单向不可逆,无法从哈希值反推原始数据
在JavaScript中的典型实现方式:
javascript复制async function sha256(message) {
const msgBuffer = new TextEncoder().encode(message);
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
return Array.from(new Uint8Array(hashBuffer)).map(b => b.toString(16).padStart(2, '0')).join('');
}
2.2 RSA非对称加密机制
RSA算法的工作流程包含几个关键步骤:
- 密钥生成:选择两个大质数p和q,计算n=pq
- 计算欧拉函数φ(n)=(p-1)(q-1)
- 选择整数e使得1<e<φ(n)且e与φ(n)互质
- 计算d使得ed ≡ 1 mod φ(n)
加密过程使用公钥(n,e):
c ≡ m^e mod n
解密使用私钥(n,d):
m ≡ c^d mod n
3. 逆向分析实战步骤
3.1 加密定位方法
在Chrome开发者工具中,可以通过以下方式定位加密点:
- 搜索关键词如"encrypt"、"SHA256"、"RSA"等
- 查看网络请求的initiator调用栈
- 对关键参数名进行XHR断点
典型的关键代码特征:
javascript复制function encryptData(data) {
const hash = CryptoJS.SHA256(data);
const encrypted = RSA.encrypt(hash.toString(), publicKey);
return encrypted.toString();
}
3.2 密钥获取技巧
RSA加密需要获取公钥,常见存储位置包括:
- 页面源码中的JavaScript变量
- 单独的接口返回(通常为XHR请求)
- WebSocket通信中的密钥交换
- 硬编码在app的配置文件中
找到的密钥通常以PEM格式存储:
code复制-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1SU1LfVLPHCozMxH2Mo
...
-----END PUBLIC KEY-----
4. Python模拟实现方案
4.1 加密流程还原
使用Python的cryptography库实现相同加密:
python复制from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.serialization import load_pem_public_key
def rsa_encrypt(message, public_key_pem):
public_key = load_pem_public_key(public_key_pem)
sha256_hash = hashes.Hash(hashes.SHA256())
sha256_hash.update(message.encode())
digest = sha256_hash.finalize()
ciphertext = public_key.encrypt(
digest,
padding.PKCS1v15()
)
return ciphertext.hex()
4.2 请求重放验证
使用requests库模拟加密请求:
python复制import requests
def make_encrypted_request(url, params):
encrypted = rsa_encrypt(str(params), PUBLIC_KEY)
headers = {
'Content-Type': 'application/encrypted-json',
'X-Encrypted': 'true'
}
response = requests.post(url, json={'data': encrypted}, headers=headers)
return response.json()
5. 常见问题排查指南
5.1 加密结果不一致
可能原因及解决方案:
- 哈希编码问题:确保使用相同的字符编码(通常UTF-8)
- 填充方案差异:检查是PKCS1v15还是OAEP填充
- 密钥格式错误:验证PEM格式是否正确包含头尾标记
5.2 请求被拒绝
典型反爬措施应对:
- 添加必要的请求头(如User-Agent、Referer)
- 模拟完整的会话流程(先访问首页获取cookies)
- 控制请求频率,添加随机延迟
- 处理动态token(可能需要先请求获取token)
6. 进阶技巧与优化
6.1 性能优化方案
当需要高频调用时可以考虑:
- 预加载公钥避免重复解析
- 使用更快的哈希实现如xxHash(需确保服务端兼容)
- 实现请求批处理减少加密次数
6.2 自动化检测机制
编写自动识别加密类型的脚本:
python复制def detect_encryption(response):
if len(response.content) % 128 == 0:
return 'RSA'
elif len(response.content) == 64:
return 'SHA256'
# 其他检测逻辑...
在实际操作中发现,金融类应用通常会采用多层加密方案。除了基础的SHA256withRSA,还可能组合使用AES对报文体加密,这种情况下需要先解密外层才能获得真正的请求参数。