转载自:https://bbs.pediy.com/thread-251303.htm,写得比较详细,未测试,备查!

在电子取证过程中,也会遇到提取PC版微信数据的情况,看雪、52破解和CSDN等网上的PC版微信数据库破解文章实在是太简略了,大多数只有结果没有过程。经过反复试验终于成功解密了数据库,现在把详细过程记录下来,希望大家不要继续在已经解决的问题上过度浪费时间,以便更投入地研究尚未解决的问题。

通过查阅资料得知,与安卓手机版微信的7位密码不同,PC版微信的密码是32字节(64位),加密算法没有说明,但是可以通过OllyDbg工具从内存中获取到这个密码,然后通过一段C++代码进行解密。

首先下载OllyDbg 2.01汉化版,我用的版本如下图所示:

运行OllyDbg,然后运行PC版微信(需要下载客户端的,不是网页版)。先不要点击登录按钮。

切换到Ollydbg界面:

点击文件菜单,选择“附加”,在弹出的对话框中找到名称为WeChat的进程,其窗口名称为“登录”。然后点击“附加”。

附加成功后OllyDbg开始加载,成功加载后可以看到最上面OllyDbg后面有WeChat.exe的字样:

在查看菜单中选择“可执行模块”:

找到名称为WeChatWin的模块,双击选中。为了方便观察,在窗口菜单中选择水平平铺。在CPU窗口标题栏可以看到“模块WeChatWin”字样。

在插件中选择“StrFinder字符查找”中的“查找ASCII字符串”(注意如果下载的OllyDbg版本不对,可能没有相关插件,因此一定要找对版本),要稍微等一会儿,会出现搜索结果的窗口。

在此窗口点击鼠标右键,选择“Find”,在搜索框中输入“DBFactory::encryptDB”。

会自动定位在第一处,但我们需要的是第二处,即“encryptDB %s DBKey can’t be null”下面这一处。可以用鼠标点击滚动条向下,找到第二处,用鼠标双击此处。

在CPU窗口中可以看到已经定位到了相应的位置。用鼠标点击滚动条向下翻。

下面第六行应该是TEST EDX,EDX,就是用来比对密码的汇编语言代码。在最前面地址位置(本文中是0F9712BA)双击设置断点(设置断点成功则地址会被标红,而且可以在断点窗口中看到设置成功的断点)

点击“运行”按钮(或者在调试菜单中选择“运行”),这时寄存器窗口中的EDX的值应该是00000000。

切换到微信登录页面,点击登录,然后到手机端确认登录。这是OllyDbg界面中的数据不断滚动,直到EDX不再为全0并且各个窗口内容停止滚动为止。

在EDX的值上面点击鼠标右键,在弹出的菜单里面选择“数据窗口中跟随”,则数据窗口中显示的就是EDX的内容。

图示中从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以后的都应该可以,懒得找就直接官网下载最新的吧)

在启动界面右下方选择“创建新项目”

滚动下拉条,在窗口中选择C++控制台应用:

给项目随便起个名字,选择保存位置:

然后点击“创建”,即可完成新项目创建。生成默认的Hello World代码:

先要做好项目的基础配置,之前调试失败主要问题就出在这里了。

在项目菜单中最下面选择项目属性“dewechat属性”(这个跟设置的项目名称一致)

对话框最左上角的配置后面,可以选择配置的是Debug模式还是Release模式(Release模式不包含调试信息,编译完成的exe文件更小一些,但如果是自己用,这两个模式没有区别,配置了哪个,后面就要用哪个模式编译,否则会报错)

先选择C/C++下面的“常规”选项:

右边第一条是“附加包含目录”,点击右侧空白处。在下拉框里选择“编辑…”,在对话框中点击四个图标按钮最左侧的“新行”按钮,会生成一个空白行,点击右侧的“…”:

在弹出的对话框里选择刚刚安装的openssl目录(本文是c:\openssl-1.0.2r)中的include目录。

设置完成后如下:

然后选择左侧“链接器”下面的“常规”:

在中间位置,有一个“附加库目录”,点击右侧空白处,选择openssl目录下的lib目录,设置完成后如下:

最后点击链接器下面的“输入”:

右侧最上面有“附加依赖项”,默认已经有一些系统库,点击右侧内容,选择“编辑…”

这个没有增加新行的按钮,只能手工录入或者拷贝文件名进去,需要增加上图所示的两个库名称。

设置完成后如下:

现在所有的设置都OK了,可以把代码放进来编译了。

由于太多网站转载,而且很多有错漏,已经搞不清原始代码是哪位大神写的了,其中有一些已经被废弃的代码,根据系统报错提示进行了替换,另外做了一个主要的变化就是之前的代码是把数据库名写在变量中,但由于需要解密很多库,为了灵活,改为输入参数的方法,即在运行时带参数运行或者根据提示输入需要解密的数据库文件名。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

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键),如果前面的步骤操作都正确,应该可以完成编译并自动运行,弹出一个命令行窗口,提示需要输入文件名:

最下方显示了生成的exe文件路径,将这个文件拷贝到微信数据库所在的目录,一般是:

C:\Users\Administrator\Documents\WeChat Files\********\Msg

其中********位置为需要解密的微信id,目录内容如下:

如果要解密ChatMsg.db,则在命令行窗口输入指令dewechat ChatMsg.db回车即可。

解密成功后,会在目录中生成de_ChatMsg.db,用sqlite数据库管理软件打开即可。

本文主要是个验证过程,没有做什么突破工作,目前的解密只能算是半自动过程,密码算法部分的获得是下一步需要研究的内容,希望大家共同努力!

作者:newx

QQ:2337242

【 原创文章,转载请注明出处。 】

PC版微信数据库解密详细教程相关推荐

  1. 解密PC版微信数据库ChatMsg.db

    最近发现用Python生成词云图挺有意思的,于是想着生成微信和某个人的聊天记录的词云应该挺好玩. 在网上找了好多解密微信数据库的文章,但大多数都是解密Android版的,好不容易找到些解密PC版的还写 ...

  2. 读取PC版微信数据库(电脑版微信数据库)内容

    原始网址   https://www.cnblogs.com/Charltsing/p/WeChatPCdb.html 联系QQ:564955427 1.PC版微信的密钥是32位byte,不同于安卓版 ...

  3. Java中通过JNI技术开发一款PC端微信数据库解密备份工具

    一.前言 在之前已经介绍了如何使用VS2017编写C++代码解密微信数据库文件了,但是这个不是最终的目的,因为要想让一个工具可以给别人使用,必须要有界面交互才是完美的,所以我们本文主要来进行解密编写, ...

  4. PC版微信加密图片解密思路与代码实现_Python

    PC版微信加密图片解密思路与代码实现_Python 前言 PC版的微信会加密存储用户接受到的所有图片信息. 存储路径为 C:\Users\用户名\Documents\WeChat Files\微信号\ ...

  5. 详细解读:远程线程注入DLL到PC版微信

    一.远程线程注入的原理 1.其基础是在 Windows 系统中,每个 .exe 文件在双击打开时都会加载 kernel32.dll 这个系统模块,该模块中有一个 LoadLibrary() 函数,可以 ...

  6. win七系统如何卸载MySQL_win7系统卸载SQL2008R2数据库的详细教程

    用过SQL2008R2数据库的朋友都知道,安装起来容易卸起来麻烦,可是在win7 32位旗舰版系统就不知道怎么卸载SQL2008R2数据库了.其实卸载SQL2008R2数据库的方法也很简单,可直接通过 ...

  7. HOOK准备--PC版微信初试

    HOOK准备–PC版微信初试 以下关于钩子的介绍来自百度百科 钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程序以监视指定窗口的某种消息,而且所监视的窗口可以是其他 ...

  8. 远程线程注入DLL到PC版微信

    一.远程线程注入的原理 1.其基础是在 Windows 系统中,每个 .exe 文件在双击打开时都会加载 kernel32.dll 这个系统模块,该模块中有一个 LoadLibrary() 函数,可以 ...

  9. python 贴吧自动回复机-Python实现微信自动回复机器人详细教程

    首先,我们需要安装并配置好Python环境,并安装requests和itchat包,我用的是Windows7环境! https://www.python.org/ python官网 下载 然后直接打开 ...

  10. PC版微信,也终于上线了这个超赞的功能

    微信有3个超赞的免打扰功能,能大大提升你微信使用效率. 一个是消息免打扰. 不管是群聊,还是单聊,都可以开启免打扰. 只要是给我发过广告的微商或类微商,我都开启免打扰.会清净一些. 另一个是「折叠置顶 ...

最新文章

  1. Matlab与线性代数--矩阵的LU分解
  2. R语言使用gt包和gtExtras包漂亮地显示表格数据:gtExtras包的gt_hulk_col_numeric函数对单列、多列数据进行着色、使用不同的调色板(color palette)对列着色
  3. 009_Redis的事物
  4. 【图论】【二叉树】以先序字符串方式建立二叉树
  5. 编译错误 错误:PL/SQL: ORA-00932: 数据类型不一致: 应为 DATE, 但却获得 NUMBER 行
  6. 登入Github、Git本地上传及Visual Studio Code上传教程
  7. “Word自动更改后的内容保存到通用文档模板上。是否加载该模板?“的解决办法...
  8. CMD-CMD命令之新建一个用户!
  9. Vquery PHP 简单爬虫类
  10. java的本质_Java线程本质
  11. Axure RP 9 使用详解视频教程-真实操作步骤
  12. PC-DMIS 2019 CAD 模型坐标系的转换
  13. arcmap武汉市各个行政区域的森林覆盖率和水体覆盖率
  14. 多 UI 版本网页五子棋实现
  15. android 脚本swipe,appium1.1 版本使用 swipe 方法报错
  16. 自动化测试之-测试用例设计方法总结
  17. 数据库重构工具 LiquiBase(5 Liquibase被锁)
  18. linux命令详解及软件安装(全)
  19. Android平台安全分析
  20. 极简科普 1:什么是 VOIP

热门文章

  1. Object.defineProperty()详解
  2. requestAnimationFrame运动框架实现-果冻效果
  3. 520情人节告白❤HTML+CSS+JavaScript实现抖音流动爱心
  4. 2020icpc沈阳打铁记
  5. 登录界面BootStramp模板
  6. 苹果11蓝牙配对不成功怎么办_iphone11蓝牙搜不到设备怎么办
  7. 网站性能优化之DNS Prefetch
  8. 互联网大厂的如厕自由
  9. php cms下载地址,PHPCMS v9.6.1 GBK
  10. 从概念到代码在6个小时内:交付我的第一个Windows Phone应用