首页
社区
课程
招聘
[原创]1.企业微信数据库解密
发表于: 2025-11-28 22:25 799

[原创]1.企业微信数据库解密

2025-11-28 22:25
799

基本信息介绍:

企业微信所使用的数据库的WCDB,基本介绍自己AI

简单讲讲sqlite3,sqlCipher,WCDB三者的关系:

图片描述
目前pc端使用的是C++,也就是类似于SQLCipher,而且是内联,将sqlite3.dll内联进去主程序中,会导致很多sql的函数都需要你通过特征码去定位,当然你可以自己编译出合理的dll,注入进行调用

数据库存储位置:

C:\Users\Administrator\Documents\WXWork\<账号id>
主要关注的数据库db:C:\Users\Administrator\Documents\WXWork\<账号id>\Data
里面主要有:
user.db:主要关注user_table(员工,客户), external_user_relation_v3(外部客户)
图片描述
message.db:主要关注message_table(消息),
图片描述
company.db:
图片描述
session.db: conversation_table(群聊,私聊等), conversation_user_table(群成员)
图片描述

关键sql函数

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
//AI写的代码
#include <stdio.h>
#include <Windows.h>
#include "sqlite3.h"
 
#include <time.h>
 
int main() {
    printf("SQLite版本: %s\n", sqlite3_libversion());
 
    sqlite3* db;
    int rc = sqlite3_open("message.db", &db);  // 创建物理数据库文件
//   sqlcipher需要设置加密密钥
//   const char* key = "CreateSun";
//   rc = sqlite3_key(db, key, strlen(key));
    if (rc != SQLITE_OK) {
        printf("打开数据库失败: %s\n", sqlite3_errmsg(db));
        return 1;
    }
    printf("成功打开数据库\n");
 
    // 创建消息表
    const char* create_table_sql =
        "CREATE TABLE IF NOT EXISTS message_table ("
        "message_id INTEGER PRIMARY KEY AUTOINCREMENT,"
        "server_id INTEGER DEFAULT 0 NOT NULL,"
        "sequence INTEGER DEFAULT 0 NOT NULL,"
        "sender_id INTEGER DEFAULT 0 NOT NULL,"
        "conversation_id TEXT DEFAULT '' NOT NULL,"
        "content_type INTEGER DEFAULT 0 NOT NULL,"
        "send_time INTEGER DEFAULT 0 NOT NULL,"
        "flag INTEGER DEFAULT 0 NOT NULL,"
        "content TEXT,"
        "devinfo INTEGER DEFAULT 0 NOT NULL,"
        "from_app_id TEXT DEFAULT '' NOT NULL,"
        "msg_from_devinfo INTEGER DEFAULT 0 NOT NULL,"
        "extra_content TEXT,"
        "local_extra_content TEXT,"
        "client_id TEXT DEFAULT '',"
        "local_extra_content_translate_info TEXT,"
        "local_extra_content_time_nlp TEXT,"
        "local_extra_content_approval_nlp TEXT);";
 
    char* err_msg = 0;
    rc = sqlite3_exec(db, create_table_sql, 0, 0, &err_msg);
     
    if (rc != SQLITE_OK) {
        printf("创建表失败: %s\n", err_msg);
        sqlite3_free(err_msg);
    } else {
        printf("消息表创建成功\n");
    }
 
    // 插入几条聊天记录
    time_t now = time(0);
     
    const char* insert_sql[] = {
        "INSERT INTO message_table (server_id, sequence, sender_id, conversation_id, "
        "content_type, send_time, flag, content, devinfo, from_app_id, msg_from_devinfo) "
        "VALUES (1001, 1, 10001, 'C_GROUP_123', 1, %ld, 0, "
        "'CreateSun是最聪明的人!!!!!!!!!!!!!!!!!', 0, 'com.example.app', 0);",
         
        "INSERT INTO message_table (server_id, sequence, sender_id, conversation_id, "
        "content_type, send_time, flag, content, devinfo, from_app_id, msg_from_devinfo) "
        "VALUES (1001, 2, 10002, 'C_GROUP_123', 1, %ld, 0, "
        "'我也同意,CreateSun太厉害了!', 0, 'com.example.app', 0);",
         
        "INSERT INTO message_table (server_id, sequence, sender_id, conversation_id, "
        "content_type, send_time, flag, content, devinfo, from_app_id, msg_from_devinfo) "
        "VALUES (1001, 3, 10003, 'C_GROUP_123', 1, %ld, 0, "
        "'向CreateSun学习编程技巧', 0, 'com.example.app', 0);"
    };
     
    char sql_buffer[1024];
    for (int i = 0; i < 3; i++) {
        snprintf(sql_buffer, sizeof(sql_buffer), insert_sql[i], now + i);
        rc = sqlite3_exec(db, sql_buffer, 0, 0, &err_msg);
         
        if (rc != SQLITE_OK) {
            printf("插入记录失败: %s\n", err_msg);
            sqlite3_free(err_msg);
        } else {
            printf("成功插入记录 %d\n", i+1);
        }
    }
 
    // 查询并打印所有记录
    printf("\n数据库中的消息记录:\n");
    const char* select_sql = "SELECT message_id, sender_id, content FROM message_table;";
    sqlite3_stmt *stmt;
     
    rc = sqlite3_prepare_v2(db, select_sql, -1, &stmt, 0);
    if (rc != SQLITE_OK) {
        printf("查询准备失败: %s\n", sqlite3_errmsg(db));
    } else {
        while (sqlite3_step(stmt) == SQLITE_ROW) {
            int mid = sqlite3_column_int(stmt, 0);
            int sid = sqlite3_column_int(stmt, 1);
            const char* content = (const char*)sqlite3_column_text(stmt, 2);
            printf("[消息ID:%d] [发送者:%d] 内容: %s\n", mid, sid, content);
        }
        sqlite3_finalize(stmt);
    }
 
    sqlite3_close(db);
    printf("\n数据库操作完成,数据已保存到 message.db 文件\n");
    system("pause");
    return 0;
}

主要的几个关键函数:
sqlite3_open:打开数据库
sqlite3_exec:执行sql
sqlite3_prepare_v2:相当于预编译,重复执行
sqlite3_step:执行sqlite3_stmt*,里面包含sqlite*句柄及其sql

两种解密企业微信数据库的方法

  1. 使用加密数据库的key直接进行解密
    找到这个函数的特征码:sqlite3_key,将其进行hook获取密钥
    企业微信的密钥是由一个总key,根据数据库db文件等的不同派发出不同的分key
    也就是每个db文件的key都是不一样的,不同电脑的同一个账号也是不一样的
  2. Hook获取sql句柄,执行解密sql进行解密
    Hook函数:sqlite3_step,sqlite3_prepare_v2,sqlite3_exec等基本上就可以获取所有的数据库句柄
    sqlite3_db_filename:通过句柄获取数据库的路径
1
2
3
//使用这写sql可以清除sqlcipher的密码
const char* sql_SetKeyNull = "PRAGMA rekey = '';";
const char* sql_SaveDB = "PRAGMA wal_checkpoint(FULL);";

你甚至可以设置一个回调函数,写入一条数据,执行一次回调导出数据

找特征码可以通过下载DB Browser for SQLite.exe,DB Browser for SQLCipher.exe着两个软件,里面包含两个dll,自己通过IDA去找特征码定位
咨询一次888(开玩笑):
图片描述
鹅群:749050322


[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

最后于 2025-11-28 22:28 被CreateSun编辑 ,原因:
上传的附件:
收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 4236
活跃值: (3116)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
2
挺多绕过官方收费的会话留痕,sqlite支持多进程同时读数据,拿到密钥就可以直接打开数据库。企微最简单,微信抹了密钥,qq自定义sqlite。
2025-11-29 18:04
0
游客
登录 | 注册 方可回帖
返回