watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(74.86 KB, 下载次数: 16)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
所有的数据库文件都是经过AES加密的,AES的密钥是32位,而且所有数据库文件共用一个密钥,我们需要找到那个AES密钥才能进行解密,然后才能对数据库文件进行操作。
定位数据库密钥的思路
微信在登录时肯定要从数据库文件中获取历史聊天记录加载到程序中,然后我们才能看到之前的聊天记录。那么在微信读取数据库文件之前肯定要先打开数据库文件,所以CreateFile这个API就是我们的切入点。
在API断下之后怎么去找数据库的密码呢?可以根据AES的密钥长度为32位这个线索,32也就是十六进制的20,时刻注意20这个数字!
另外,在解密数据库的call中至少需要两个参数,一个是AES的密钥,另外一个是需要解密的数据库文件的路径。
还有一种方法是在内存中搜索数据库文件的名字,然后下访问断点。这种方案也是可行的。
获取数据库密钥的实战分析
CreateFileW断点
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(252.09 KB, 下载次数: 15)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(528.4 KB, 下载次数: 15)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(18.6 KB, 下载次数: 13)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(54.02 KB, 下载次数: 13)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
CreateFileW断点断下来,那么现在应该怎么跟呢?肯定不能一直往下单步,虽然单步也能达到目标。
分析一下现在的状况,这个时候微信的数据库处于一个还未初始化,但是即将初始化的状态,我们可以在堆栈或者堆栈附近的地址找到关于数据库初始化相关的函数。然后在微信初始化完数据库之后单步往下跟。这样能省去很多麻烦
排查堆栈地址
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(42.85 KB, 下载次数: 19)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(146.11 KB, 下载次数: 11)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(98.85 KB, 下载次数: 11)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(162.74 KB, 下载次数: 11)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(86.86 KB, 下载次数: 17)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(135.9 KB, 下载次数: 12)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(216.41 KB, 下载次数: 12)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(115.26 KB, 下载次数: 16)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(146.48 KB, 下载次数: 10)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(41.51 KB, 下载次数: 14)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
工程需要包含OpenSSL的相关文件
解密代码
这份代码原作者是谁我已经不记得了 反正被拷来拷去拷了很多次了
#include "pch.h"
#include <iostream>
#include <Windows.h>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/hmac.h>
using namespace std;
#pragma comment(lib, "ssleay32.lib")
#pragma comment(lib, "libeay32.lib")
#if _MSC_VER>=1900
#include "stdio.h"
_ACRTIMP_ALT FILE* __cdecl __acrt_iob_func(unsigned);
#ifdef __cplusplus
extern "C"
#endif
FILE* __cdecl __iob_func(unsigned i) {
return __acrt_iob_func(i);
#endif /* _MSC_VER>=1900 */
#undef _UNICODE
#define SQLITE_FILE_HEADER "SQLite format 3"
#define IV_SIZE 16
#define HMAC_SHA1_SIZE 20
#define KEY_SIZE 32
#define SL3SIGNLEN 20
#ifndef ANDROID_WECHAT
#define DEFAULT_PAGESIZE 4096 //4048数据 + 16IV + 20 HMAC + 12
#define DEFAULT_ITER 64000
#else
#define NO_USE_HMAC_SHA1
#define DEFAULT_PAGESIZE 1024
#define DEFAULT_ITER 4000
#endif
//pc端密码是经过OllyDbg得到的64位pass,是64位,不是网上传的32位,这里是个坑
unsigned char pass[] = { 0xc7,0x99,0x26,0xc0,0x36,0x6b,0x4f,0xee,0xb8,0xc7,0x48,0x83,0xaa,0xc9,0x6c,0x7e,0x0b,0x0a,0xda,0x3a,0x56,0x71,0x48,0xac,0xb9,0xda,0x4f,0x37,0x5c,0x4d,0x0b,58};
int Decryptdb();
int main() {
Decryptdb();
return 0;
int Decryptdb() {
const char* dbfilename = "ChatMsg.db";
FILE* fpdb;
fopen_s(&fpdb, dbfilename, "rb+");
if (!fpdb) {
printf("打开文件错!");
getchar();
return 0;
fseek(fpdb, 0, SEEK_END);
long nFileSize = ftell(fpdb);
fseek(fpdb, 0, SEEK_SET);
unsigned char* pDbBuffer = new unsigned char[nFileSize];
fread(pDbBuffer, 1, nFileSize, fpdb);
fclose(fpdb);
unsigned char salt[16] = { 0 };
memcpy(salt, pDbBuffer, 16);
#ifndef NO_USE_HMAC_SHA1
unsigned char mac_salt[16] = { 0 };
memcpy(mac_salt, salt, 16);
for (int i = 0; i < sizeof(salt); i++) {
mac_salt[i] ^= 0x3a;
#endif
int reserve = IV_SIZE; //校验码长度,PC端每4096字节有48字节
#ifndef NO_USE_HMAC_SHA1
reserve += HMAC_SHA1_SIZE;
#endif
reserve = ((reserve % AES_BLOCK_SIZE) == 0) ? reserve : ((reserve / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE;
unsigned char key[KEY_SIZE] = { 0 };
unsigned char mac_key[KEY_SIZE] = { 0 };
OpenSSL_add_all_algorithms();
PKCS5_PBKDF2_HMAC_SHA1((const char*)pass, sizeof(pass), salt, sizeof(salt), DEFAULT_ITER, sizeof(key), key);
#ifndef NO_USE_HMAC_SHA1
//此处源码,怀凝可能有错,pass 数组才是密码
//PKCS5_PBKDF2_HMAC_SHA1((const char*)key, sizeof(key), mac_salt, sizeof(mac_salt), 2, sizeof(mac_key), mac_key);
PKCS5_PBKDF2_HMAC_SHA1((const char*)key, sizeof(key), mac_salt, sizeof(mac_salt), 2, sizeof(mac_key), mac_key);
#endif
unsigned char* pTemp = pDbBuffer;
unsigned char pDecryptPerPageBuffer[DEFAULT_PAGESIZE];
int nPage = 1;
int offset = 16;
while (pTemp < pDbBuffer + nFileSize) {
printf("解密数据页:%d/%d \n", nPage, nFileSize / DEFAULT_PAGESIZE);
#ifndef NO_USE_HMAC_SHA1
unsigned char hash_mac[HMAC_SHA1_SIZE] = { 0 };
unsigned int hash_len = 0;
HMAC_CTX hctx;
HMAC_CTX_init(&hctx);
HMAC_Init_ex(&hctx, mac_key, sizeof(mac_key), EVP_sha1(), NULL);
HMAC_Update(&hctx, pTemp + offset, DEFAULT_PAGESIZE - reserve - offset + IV_SIZE);
HMAC_Update(&hctx, (const unsigned char*)& nPage, sizeof(nPage));
HMAC_Final(&hctx, hash_mac, &hash_len);
HMAC_CTX_cleanup(&hctx);
if (0 != memcmp(hash_mac, pTemp + DEFAULT_PAGESIZE - reserve + IV_SIZE, sizeof(hash_mac))) {
printf("\n 哈希值错误! \n");
getchar();
return 0;
#endif
if (nPage == 1) {
memcpy(pDecryptPerPageBuffer, SQLITE_FILE_HEADER, offset);
EVP_CIPHER_CTX* ectx = EVP_CIPHER_CTX_new();
EVP_CipherInit_ex(ectx, EVP_get_cipherbyname("aes-256-cbc"), NULL, NULL, NULL, 0);
EVP_CIPHER_CTX_set_padding(ectx, 0);
EVP_CipherInit_ex(ectx, NULL, NULL, key, pTemp + (DEFAULT_PAGESIZE - reserve), 0);
int nDecryptLen = 0;
int nTotal = 0;
EVP_CipherUpdate(ectx, pDecryptPerPageBuffer + offset, &nDecryptLen, pTemp + offset, DEFAULT_PAGESIZE - reserve - offset);
nTotal = nDecryptLen;
EVP_CipherFinal_ex(ectx, pDecryptPerPageBuffer + offset + nDecryptLen, &nDecryptLen);
nTotal += nDecryptLen;
EVP_CIPHER_CTX_free(ectx);
memcpy(pDecryptPerPageBuffer + DEFAULT_PAGESIZE - reserve, pTemp + DEFAULT_PAGESIZE - reserve, reserve);
char decFile[1024] = { 0 };
sprintf_s(decFile, "dec_%s", dbfilename);
FILE * fp;
fopen_s(&fp, decFile, "ab+");
fwrite(pDecryptPerPageBuffer, 1, DEFAULT_PAGESIZE, fp);
fclose(fp);
nPage++;
offset = 0;
pTemp += DEFAULT_PAGESIZE;
printf("\n 解密成功! \n");
system("pause");
return 0;
}
实际效果
运行程序
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(238.23 KB, 下载次数: 18)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(146.31 KB, 下载次数: 15)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(53.92 KB, 下载次数: 12)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(30.6 KB, 下载次数: 11)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(23.65 KB, 下载次数: 15)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(94.38 KB, 下载次数: 15)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
可以看到所有的表数据已经出现了。解密完成
动态获取数据库密钥
找到了密钥之后就结束了吗?这个密钥目前是写死的,如果变化的话,我们又要重新找,然后再次输入。所以我们需要动态获取到数据库密钥。想要动态获取数据库密钥,就必须定位到数据库密钥的基址。步骤如下:
直接在CE中搜索之前找到的密钥
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(60.27 KB, 下载次数: 17)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(56.34 KB, 下载次数: 14)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
这个基址以指针的形式保存了微信数据库的密钥,这个地址就是我们要的微信密钥的基址了。
动态获取数据库密钥的代码如下:
char databasekey[0x20] = { 0 };
//获取WeChatWin的基址
DWORD dwKeyAddr = (DWORD)GetModuleHandle(L"WeChatWin.dll")+ WxDatabaseKey;
LPVOID* pAddr =(LPVOID*)(*(DWORD*)dwKeyAddr);
DWORD dwOldAttr = 0;
VirtualProtect(pAddr, 0x20, PAGE_EXECUTE_READWRITE, &dwOldAttr);
memcpy(databasekey, pAddr, 0x20);
VirtualProtect(pAddr, 0x20, dwOldAttr, &dwOldAttr);
定位数据库文件句柄
在拿到数据库密码之后,我们还需要对数据库文件进行解密,解密完成之后才能查询数据库。那么有没有更好的方法可以不需要获取密码也不需要解密数据库文件就能直接进行数据库的查询操作呢?当然是有的,就是通过微信的数据库句柄!
关于微信数据库句柄
微信的数据库句柄在一些地方会经常用到,比如查询好友的详细信息的时候,需要传入一个数据库的句柄。然后通过句柄去查询信息,最后返回好友详细信息。
如果我们直接拿到密码,然后对数据库进行解密,再查询好友信息,这种方法当然也是可以的。但是拿到的数据并不是实时的。
如果我们拿到这个数据库的句柄,就能实时的去查询好友的详细信息了,而且也不需要进行解密和获取数据库密码的操作了。
获取微信数据库句柄的思路
找微信数据库句柄的思路和找数据库密码的思路是一样的,微信在点击登录的时候,肯定是要打开本地的数据库,然后获得一个句柄,所以我们可以通过在CreateFileW下断点,接着单步跟踪,就能找到数据库的句柄
定位微信的数据库句柄
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(214.62 KB, 下载次数: 12)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(66.58 KB, 下载次数: 14)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(21.39 KB, 下载次数: 15)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(224.48 KB, 下载次数: 9)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(195.56 KB, 下载次数: 11)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDc0NTcw,size_16,color_FFFFFF,t_70.jpg
(78.6 KB, 下载次数: 14)
PC微信逆向:两种姿势教你解密数据库文件
2020-6-9 01:14 上传
单步步过这个call,发现缓冲区里写入了一个地址,那么就可以确定这个就是我们要找的call,只要我们HOOK这个地址,那么就能拿到所有的数据库文件的句柄了。而数据库的名称就在堆栈里,可以自己去找到偏移然后获取数据。
至于代码,等我研究下怎么调用SQlite再告诉你们,最后附上用代码解密数据库的工程。
[外链图片转存中…(img-bkvnRcVG-1563613749040)]
程序断下,此时ecx指向数据库文件的路径
[外链图片转存中…(img-ZLt43xxD-1563613749045)]
edx指向一个空的缓冲区,那么这个就非常像我们要找的call
[外链图片转存中…(img-xzU5iL5H-1563613749048)]
单步步过这个call,发现缓冲区里写入了一个地址,那么就可以确定这个就是我们要找的call,只要我们HOOK这个地址,那么就能拿到所有的数据库文件的句柄了。而数据库的名称就在堆栈里,可以自己去找到偏移然后获取数据。
至于代码,等我研究下怎么调用SQlite再告诉你们,最后附上用代码解密数据库的工程。
链接:YPSuperKey Unlocked
https://pan.baidu.com/s/14fqLn8qUt2qr34UIb6Qd1Q
提取码:t48w
目前微信机器人的成品已经发布,需要代码请移步Github。还请亲们帮忙点个star
https://github.com/TonyChen56/WeChatRobot
温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的认可,还可以获得学币奖励,请尊重他人的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【
投诉建议
】板块发帖举报。
微信
,
逆向
,
两种
,
姿势
,
解密