WechatDecrypt源码逐行精读:wechat.cpp解密算法的完整实现细节
【免费下载链接】WechatDecrypt微信消息解密工具项目地址: https://gitcode.com/gh_mirrors/we/WechatDecrypt
🔓WechatDecrypt是一个开源的微信消息解密工具:它的核心就是单个 C++ 源文件 wechat.cpp,实现了把微信加密数据库(如ChatMsg.db)逐页解密为可直接打开的 SQLite 文件(dec_ChatMsg.db)的完整算法。本文将带你逐段读懂 wechat.cpp 中的密钥派生、HMAC 校验与 AES-256-CBC 解密流程,零基础也能看懂。
项目结构与快速上手 🚀
整个仓库只有 3 个文件,结构极其精简:
| 文件 | 说明 |
|---|---|
| wechat.cpp | 解密工具的全部源码(约 150 行) |
| README.md | 编译与使用说明 |
| LICENSE | 开源许可协议 |
按照 README.md 的教程,使用方式很简单:
- 编译出可执行文件,拷贝到微信数据库目录(一般是
C:\Users\用户名\Documents\WeChat Files\微信ID\Msg); - 在 CMD 中执行
dewechat ChatMsg.db; - 得到
dec_ChatMsg.db,用任意 SQLite 工具打开即可查询聊天记录。
💡 提示:程序要求 Windows 环境(使用了
Windows.h和strcpy_s等 API),并依赖 OpenSSL 库。
第一步:程序入口与文件读取
程序入口在 wechat.cpp:
int main(int argc, char* argv[]) { if (argc >= 2) strcpy_s(dbfilename, argv[1]); else { cout << "请输入文件名:" << endl; cin >> dbfilename; } Decryptdb(); return 0; }逻辑非常朴素:命令行第 2 个参数是数据库文件名,没传就交互式提示输入,然后调用真正的解密函数Decryptdb()。
Decryptdb() 开头做了三件事:
- 以二进制读写模式
rb+打开目标数据库,失败则提示"打开文件错"退出; - 用
fseek/ftell获取文件大小,把整个文件一次性读入内存缓冲区pDbBuffer; - 准备后续逐页解密的内存环境。
第二步:盐值与双密钥派生(核心算法上半段)🧂
微信数据库的头部 16 字节就是盐值(salt):
unsigned char salt[16] = { 0 }; memcpy(salt, pDbBuffer, 16); // 取自数据库文件最前面16字节紧接着是本项目一个非常巧妙的设计——派生一个"变异盐"用于 MAC 密钥(wechat.cpp):
memcpy(mac_salt, salt, 16); for (int i = 0; i < sizeof(salt); i++) mac_salt[i] ^= 0x3a; // 每一位异或 0x3a也就是说,同一个 salt 通过XOR 0x3a变换出mac_salt,分别用于派生两把 32 字节密钥:
| 密钥 | 派生方式 | 用途 |
|---|---|---|
key(AES 密钥) | PBKDF2-HMAC-SHA1(口令, salt,64000 次迭代) | AES-256-CBC 解密数据页 |
mac_key | PBKDF2-HMAC-SHA1(key, mac_salt,2 次迭代) | 逐页 HMAC-SHA1 完整性校验 |
对应的核心代码见 wechat.cpp。
这里有个关键前提:32 字节的"口令"并不是用户输入的密码,而是通过调试工具 OllyDbg 从 PC 端微信进程中静态提取出来的,写死在 wechat.cpp 的pass[]数组里。不同微信版本/安装环境得到的 pass 可能不同,需要重新抓取——这也是使用本工具最大的注意点。
第三步:理解 4096 字节的数据页结构 📦
整个数据库被切分成固定大小的"页",PC 端每页 4096 字节,页内布局是:
┌────────────┬──────────┬──────────┬──────┐ │ 加密数据 │ 16字节IV │ 20字节HMAC│ 12字节 │ │ (4048) │ (CBC初始值)│ (校验码) │ (填充) │ └────────────┴──────────┴──────────┴──────┘ 共 4096 字节源码中这个"尾部保留区"的计算逻辑在 wechat.cpp:reserve = IV_SIZE(16) + HMAC_SHA1_SIZE(20) = 36,再向上对齐到 AES 分组(16 字节)的整数倍,得到 48。页头还定义了 SQLITE_FILE_HEADER "SQLite format 3",为后面恢复文件头做准备。
第四步:HMAC-SHA1 逐页完整性校验 ✅
解密之前先"验签"。每一页都会用mac_key计算 HMAC:
对
页内密文部分 + 4字节页码做 HMAC-SHA1,结果应与页尾存储的 20 字节哈希一致(wechat.cpp)。
这段代码体现了两个细节:
- 校验数据包含页码(
HMAC_Update(&hctx, &nPage, 4)),所以页顺序不能乱,缺一页就会报错; - 校验失败会直接打印"哈希值错误!"并终止——这保证了解密结果不会被静默损坏,密钥或口令不匹配也能第一时间暴露。
第五步:AES-256-CBC 逐页解密 🔐
每页的解密流程(wechat.cpp):
- 第 1 页特殊处理:解出来的页首 16 字节会被替换回
"SQLite format 3"文件头,因为原始 SQLite 文件头同样被加密了,不还原就无法被数据库工具识别; - 初始化
aes-256-cbc算法并关闭填充(EVP_CIPHER_CTX_set_padding(ectx, 0),因为页大小已固定,不需要标准 padding); - IV 取自该页尾部 16 字节(
pTemp + (DEFAULT_PAGESIZE - reserve)),即每页独立 IV; - 对页内密文执行
EVP_CipherUpdate+EVP_CipherFinal_ex完成解密。
每页解完 4096 字节后,以追加模式ab+写入dec_前缀的输出文件(wechat.cpp),循环直到遍历完整个文件,最后打印"解密成功!"。
🎯 小结:盐值派生双密钥 → 逐页 HMAC 验签 → 逐页 AES 解密 → 拼接落盘,四步构成了 wechat.cpp 微信数据库解密算法的全部。
PC 端与 Android 端的参数差异 📱
wechat.cpp 用宏区分了两套参数:
| 参数 | PC 端 | Android 端 |
|---|---|---|
页大小DEFAULT_PAGESIZE | 4096 | 1024 |
迭代次数DEFAULT_ITER | 64000 | 4000 |
| HMAC-SHA1 校验 | 启用 | 关闭(NO_USE_HMAC_SHA1) |
编译时若定义ANDROID_WECHAT,就会走 Android 分支:页更小、迭代更少、且不做哈希校验。这解释了为什么同一份代码可以兼顾两个平台的加密策略差异。
解密产物与注意事项 ⚠️
- 输入
ChatMsg.db,输出dec_ChatMsg.db(dec_+ 原文件名),是一个标准 SQLite 数据库,可直接查询聊天记录表; - 口令
pass写死在源码中,更换微信版本或重装微信后可能失效,需要用调试工具重新获取并修改 wechat.cpp 中的数组; - 程序一次性把整个数据库读入内存,数据库很大时注意内存占用;
- 请务必仅对本人合法持有的数据使用本工具,遵守当地法律法规与平台服务协议,尊重他人隐私。
结语
WechatDecrypt 用不到 150 行 C++ 代码完整演示了"PBKDF2 密钥派生 + HMAC 完整性校验 + AES-256-CBC 分组解密"这套工程化加密方案的逆过程。读懂 wechat.cpp 后,你对 SQLite 数据库结构、对称加密的 IV/盐值设计以及完整性校验的意义,都会有非常具体的认识——这正是它作为学习样例的最大价值。📚
【免费下载链接】WechatDecrypt微信消息解密工具项目地址: https://gitcode.com/gh_mirrors/we/WechatDecrypt
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考