吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 43190|回复: 148
收起左侧

[原创] PC版XX数据库解密详细教程

    [复制链接]
newxccg 发表于 2019-5-12 21:36
本帖最后由 Kido 于 2019-6-6 18:11 编辑

【 原创文章,转载请注明出处。 】
       在电子取证过程中,也会遇到提取PC版微信数据的情况,看雪、52破解和CSDN等网上的PC版微信数据库破解文章实在是太简略了,大多数只有结果没有过程。经过反复试验终于成功解密了数据库,现在把详细过程记录下来,希望大家不要继续在已经解决的问题上过度浪费时间,以便更投入地研究尚未解决的问题。通过查阅资料得知,与安卓手机版微信的7位密码不同,PC版微信的密码是32字节(64位),加密算法没有说明,但是可以通过OllyDbg工具从内存中获取到这个密码,然后通过一段C++代码进行解密。
       首先下载OllyDbg 2.01汉化版,我用的版本如下图所示:
ollydbg2.png
       运行OllyDbg,然后运行PC版微信(需要下载客户端的,不是网页版)。先不要点击登录按钮。
微信登录.jpg
       切换到Ollydbg界面:
ollydbg菜单.png
       点击文件菜单,选择“附加”,在弹出的对话框中找到名称为WeChat的进程,其窗口名称为“登录”。然后点击“附加”。
附加微信.png
       附加成功后OllyDbg开始加载,成功加载后可以看到最上面OllyDbg后面有WeChat.exe的字样:
附加成功.png
       在查看菜单中选择“可执行模块”:
可执行模块.png
       找到名称为WeChatWin的模块,双击选中。为了方便观察,在窗口菜单中选择水平平铺。在CPU窗口标题栏可以看到“模块WeChatWin”字样。
水平平铺后CPU窗口.png
       在插件中选择“StrFinder字符查找”中的“查找ASCII字符串”(注意如果下载的OllyDbg版本不对,可能没有相关插件,因此一定要找对版本),要稍微等一会儿,会出现搜索结果的窗口。
插件查找ASCII字符串.png
       在此窗口点击鼠标右键,选择“Find”,在搜索框中输入“DBFactory::encryptDB”。
查找encryptDB.png
       会自动定位在第一处,但我们需要的是第二处,即“encryptDB %s DBKey can’t be null”下面这一处。可以用鼠标点击滚动条向下,找到第二处,用鼠标双击此处。
定位字符串.png
       在CPU窗口中可以看到已经定位到了相应的位置。用鼠标点击滚动条向下翻。
找到断点.png
       下面第六行应该是TEST EDX,EDX,就是用来比对密码的汇编语言代码。在最前面地址位置(本文中是0F9712BA)双击设置断点(设置断点成功则地址会被标红,而且可以在断点窗口中看到设置成功的断点)
       点击“运行”按钮(或者在调试菜单中选择“运行”),这时寄存器窗口中的EDX的值应该是00000000。
       切换到微信登录页面,点击登录,然后到手机端确认登录。这是OllyDbg界面中的数据不断滚动,直到EDX不再为全0并且各个窗口内容停止滚动为止。
寄存器.png
       在EDX的值上面点击鼠标右键,在弹出的菜单里面选择“数据窗口中跟随”,则数据窗口中显示的就是EDX的内容。
EDX值.png
       图示中从0B946A80(这个数值是变化的,不但每台电脑不同,每次调试也可能完全不同)到0B946A9F共32个字节就是微信的加密密码,本图中就是:“53E9BFB23B724195A2BC6EB5BFEB0610DC2164756B9B4279BA32157639A40BB1”
      一共32个字节,共64位。
       得到这个之后,就可以关闭OllyDbg了,微信也会自动被关闭。
       接下来就是解密过程。在看雪、52破解等多个论坛中都有相关的C++源码,开始企图使用Dev-C++或者C-Free等轻量级IDE进行编译,也使用过Visual C++ 6.0绿色精简版,结果多次尝试出现各种错误,反复失败,最终不得已使用Visual Studio,并对代码进行了一定的修正,终于调试成功。正好Visual Studio 2019刚刚发布直接到官方网站下载了社区版。
       根据查到的资料,需要先安装openssl,为了省事直接下载了最新的Win64OpenSSL-1_1_1b,安装后发现各种报错,继续查找资料发现原来sqlcipher使用的是低版本的openssl,之后找到了一个Win64OpenSSL-1_0_2r也报错,最后发现还是官方这个直接解压缩的版本靠谱:https://www.openssl.org/source/openssl-1.0.2r.tar.gz
       把压缩包直接解压到任意目录,比如c:\openssl-1.0.2r
       启动Visual Studio 2019社区版(估计Visual Studio 2008以后的都应该可以,懒得找就直接官网下载最新的吧)
       在启动界面右下方选择“创建新项目”
创建新项目.png
       滚动下拉条,在窗口中选择C++控制台应用:
控制台应用.png
       给项目随便起个名字,选择保存位置:
项目名称.png
       然后点击“创建”,即可完成新项目创建。生成默认的Hello World代码:
默认代码.png
       先要做好项目的基础配置,之前调试失败主要问题就出在这里了。
       在项目菜单中最下面选择项目属性“dewechat属性”(这个跟设置的项目名称一致)
属性页.png
       对话框最左上角的配置后面,可以选择配置的是Debug模式还是Release模式(Release模式不包含调试信息,编译完成的exe文件更小一些,但如果是自己用,这两个模式没有区别,配置了哪个,后面就要用哪个模式编译,否则会报错)
       先选择C/C++下面的“常规”选项:
cpp常规.png
       右边第一条是“附加包含目录”,点击右侧空白处。在下拉框里选择“编辑…”,在对话框中点击四个图标按钮最左侧的“新行”按钮,会生成一个空白行,点击右侧的“…”:
附加包含.png
       在弹出的对话框里选择刚刚安装的openssl目录(本文是c:\openssl-1.0.2r)中的include目录。
包含目录.png
     设置完成后如下:
包含设置完毕.png
       然后选择左侧“链接器”下面的“常规”:
链接器常规.png
       在中间位置,有一个“附加库目录”,点击右侧空白处,选择openssl目录下的lib目录,设置完成后如下:
附加库完成.png
       最后点击链接器下面的“输入”:
输入附加依赖项.png
       右侧最上面有“附加依赖项”,默认已经有一些系统库,点击右侧内容,选择“编辑…”
依赖库完成.png
       这个没有增加新行的按钮,只能手工录入或者拷贝文件名进去,需要增加上图所示的两个库名称。       设置完成后如下:
依赖库设置好.png
       现在所有的设置都OK了,可以把代码放进来编译了。       由于太多网站转载,而且很多有错漏,已经搞不清原始代码是哪位大神写的了,其中有一些已经被废弃的代码,根据系统报错提示进行了替换,另外做了一个主要的变化就是之前的代码是把数据库名写在变量中,但由于需要解密很多库,为了灵活,改为输入参数的方法,即在运行时带参数运行或者根据提示输入需要解密的数据库文件名。
[C++] 纯文本查看 复制代码
using namespace std;
#include <Windows.h>
#include <iostream>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/hmac.h>

#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得到的32位pass。
unsigned char pass[] = { 0x53,0xE9,0xBF,0xB2,0x3B,0x72,0x41,0x95,0xA2,0xBC,0x6E,0xB5,0xBF,0xEB,0x06,0x10,0xDC,0x21,0x64,0x75,0x6B,0x9B,0x42,0x79,0xBA,0x32,0x15,0x76,0x39,0xA4,0x0B,0xB1 };
char dbfilename[50];
int Decryptdb();
int CheckKey();
int CheckAESKey();
int main(int argc, char* argv[])
{
        if (argc >= 2)    //第二个参数argv[1]是文件名
                strcpy_s(dbfilename, argv[1]);  //复制    
                   //没有提供文件名,则提示用户输入
        else {
                cout << "请输入文件名:" << endl;
                cin >> dbfilename;
        }
        Decryptdb();
        return 0;
}

int Decryptdb()
{
        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
        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");
        return 0;
}

       将之前默认的代码全部清除,将以上代码拷贝进去,保存。然后在工具条栏中选择是Debug还是Release模式,是x86还是x64(需要跟之前配置匹配,如果选了没配置的模式会报错。测试发现几个选项没有太大区别,建议默认),之后点击“本地windows调试器”(或者按F5键),如果前面的步骤操作都正确,应该可以完成编译并自动运行,弹出一个命令行窗口,提示需要输入文件名:

调试成功.png
       最下方显示了生成的exe文件路径,将这个文件拷贝到微信数据库所在的目录,一般是:C:\Users\Administrator\Documents\WeChat Files\********\Msg
       其中********位置为需要解密的微信id,目录内容如下:
微信数据库目录.png
       如果要解密ChatMsg.db,则在命令行窗口输入指令dewechat ChatMsg.db回车即可。
解密成功.png
       解密成功后,会在目录中生成de_ChatMsg.db,用sqlite数据库管理软件打开即可。
       本文主要是个验证过程,没有做什么突破工作,目前的解密只能算是半自动过程,密码算法部分的获得是下一步需要研究的内容,希望大家共同努力!
       作者:newx
【 原创文章,转载请注明出处。 】

openssl-include-lib.zip

643.16 KB, 下载次数: 662, 下载积分: 吾爱币 -1 CB

包含文件

免费评分

参与人数 51威望 +2 吾爱币 +54 热心值 +49 收起 理由
小云哥哥 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
xianr12 + 1 只看懂前面的,后面有点懵
愛你壹萬年 + 1 + 1 谢谢@Thanks!
臣本布衣 + 1 + 1 谢谢@Thanks!
deber + 1 + 1 谢谢@Thanks!
moon1981911 + 1 + 1 我很赞同!
崔万宇 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
kylinpapa + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
nauh + 1 + 1 谢谢@Thanks!
贝德曼 + 1 + 1 谢谢@Thanks!
luojinfang + 1 + 1 我很赞同!
Hmily + 2 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
cwjalsy + 1 + 1 谢谢@Thanks!
小小学生 + 1 + 1 这是一篇可以置顶加精的帖子
yozorano + 1 + 1 我很赞同!
Jixun069 + 1 + 1 用心讨论,共获提升!
freetan + 1 + 1 谢谢@Thanks!
xiaoqingren + 1 我很赞同!
abc220 + 1 + 1 谢谢@Thanks!
Ftimes + 2 火前留名
w蓝魔 + 1 + 1 用心讨论,共获提升!
笙若 + 1 + 1 谢谢@Thanks!
萌新与小白 + 1 + 1 热心回复!
红黑之橙 + 1 + 1 用心讨论,共获提升!
fanvalen + 1 + 1 热心回复!
zjjyl + 1 + 1 谢谢@Thanks!
N9loveyou + 1 + 1 谢谢@Thanks!
winderqy + 1 牛皮,支持!!
wcb0414 + 1 + 1 我很赞同!
conosc + 1 + 1 用心讨论,共获提升!
thepassion + 1 热心回复!
solsun + 1 + 1 用心讨论,共获提升!
x1aozeyuu + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
smk418 + 1 + 1 谢谢@Thanks!
毛新航 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
yunfeilu + 1 + 1 我很赞同!
马化腾之父 + 1 + 1 此为违规行为,请遵守论坛版规!
Monitor + 3 + 1 鼓励转贴优秀软件安全工具和文档!
cxyelu + 1 + 1 666,最喜欢技术贴!
少尉_lib + 1 + 1 我很赞同!
bigbirdl + 1 谢谢@Thanks!
ggbb6688 + 1 + 1 楼主厉害!支持一下!
j8250347 + 1 + 1 期待有成品出现;跨入了一大步;
海天一色001 + 1 + 1 谢谢@Thanks!
迷失自我 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
JuncoJet + 1 + 1 编译好的程序来一发
hongge + 1 + 1 热心回复!
忆江南 + 1 + 1 谢谢@Thanks!
wxue + 1 + 1 谢谢@Thanks!
我为52pojie狂 + 1 + 1 谢谢@Thanks!
砸七砸八 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

耳大啊飒飒的 发表于 2019-5-13 08:25
哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈好东西

免费评分

参与人数 4吾爱币 -4 收起 理由
92013 -1 请勿灌水,提高回帖质量是每位会员应尽的义务!
lijie2love -1 请勿灌水,提高回帖质量是每位会员应尽的义务!
LeoSky -1 请勿灌水,提高回帖质量是每位会员应尽的义务!
adsllikk -1 请勿灌水,提高回帖质量是每位会员应尽的义务!

查看全部评分

weiya909 发表于 2019-5-15 00:21
无法定位序数2572于动态链接库LIBEAY32.DLL上 求解
SN1t2lO 发表于 2019-5-13 14:59
那些被废弃的代码不是真正废弃了,而是我用作搜索密钥的测试代码。当时有个坛友只要解密部分,所以实现代码没复制。int CheckKey();和int CheckAESKey();可以删除。这个代码的原始版本来自飘雪的大神。
gimisky 发表于 2019-5-12 22:26
图片都挂了,请更新一下图床,感谢楼主分享
zmolli775 发表于 2019-5-12 22:35
图片提示盗链被屏蔽了·请更新图床...
bjruiwangm 发表于 2019-5-12 22:48
学习了,大师的文章
 楼主| newxccg 发表于 2019-5-12 23:10
图片太多,重新上传了。感谢各位兄弟捧场。
Stillthekid 发表于 2019-5-13 01:55
楼主牛&#128046;
sutramusic 发表于 2019-5-13 01:55
厉害,基本看了一下,原理不懂,只能膜拜。
deadbeef 发表于 2019-5-13 02:09
请问为何链接下载来的openssl文件夹里没有lib文件夹?
lyghost 发表于 2019-5-13 07:19
很棒,过程很详细
小豆丁 发表于 2019-5-13 08:21
请问这个解密出来的数据是什么?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-22 16:11

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表