GetDbHandles.cpp 5.1 KB
Newer Older
L
ljc545w 已提交
1 2
#include "pch.h"

L
ljc545w 已提交
3
// 联系人相关库偏移
L
ljc545w 已提交
4
#define SqlHandleMicroMsgOffset 0x2366934
L
ljc545w 已提交
5
// 公众号相关库偏移
L
ljc545w 已提交
6
#define SqlHandlePublicMsgOffset 0x239E3C8
L
ljc545w 已提交
7
// 聊天记录相关库偏移
L
ljc545w 已提交
8
#define SqlHandleMSGOffset 0x239FF68
L
ljc545w 已提交
9

L
ljc545w 已提交
10
// 保存数据库信息的容器
L
ljc545w 已提交
11
vector<DbInfoStruct> dbs;
12
map<wstring, DbInfoStruct> dbmap;
L
ljc545w 已提交
13

L
ljc545w 已提交
14
/*
15
 * 根据数据库名从`dbmap`中检索数据库句柄
L
ljc545w 已提交
16 17 18
 * dbname:数据库名
 * return:DWORD,如果检索成功,返回数据库句柄,否则返回`0`
 */
L
ljc545w 已提交
19 20
DWORD GetDbHandleByDbName(wchar_t *dbname)
{
21
    if (dbmap.size() == 0)
L
ljc545w 已提交
22
        GetDbHandles();
23 24 25 26 27 28 29 30 31 32 33
    if (dbmap.find(dbname) != dbmap.end())
        return dbmap[dbname].handle;
    return 0;
}

unsigned int GetLocalIdByMsgId(ULONG64 msgid, int &dbIndex)
{
    char sql[260] = {0};
    sprintf_s(sql, "select localId from MSG where MsgSvrID=%llu;", msgid);
    wchar_t dbname[20] = {0};
    for (int i = 0;; i++)
L
ljc545w 已提交
34
    {
35 36 37 38 39 40 41 42 43
        swprintf_s(dbname, L"MSG%d.db", i);
        DWORD handle = GetDbHandleByDbName(dbname);
        if (handle == 0)
            return 0;
        vector<vector<string>> result = SelectData(handle, (const char *)sql);
        if (result.size() == 0)
            continue;
        dbIndex = i + 1;
        return stoi(result[1][0]);
L
ljc545w 已提交
44 45
    }
    return 0;
L
ljc545w 已提交
46 47
}

L
ljc545w 已提交
48
/*
L
ljc545w 已提交
49 50 51
 * 供外部调用的获取数据库信息接口
 * return:DWORD,`dbs`首个成员地址
 */
52
#ifndef USE_SOCKET
L
ljc545w 已提交
53 54 55 56 57
DWORD GetDbHandlesRemote()
{
    if (dbs.size() == 0)
        GetDbHandles();
    return (DWORD)dbs.data();
L
ljc545w 已提交
58
}
59
#endif
L
ljc545w 已提交
60

L
ljc545w 已提交
61
/*
L
ljc545w 已提交
62 63 64
 * 获取数据库信息的具体实现
 * return:void
 */
L
ljc545w 已提交
65 66 67
vector<void *> GetDbHandles()
{
    dbs.clear();
L
ljc545w 已提交
68
    dbmap.clear();
L
ljc545w 已提交
69 70 71 72 73 74 75
    DWORD WeChatWinBase = GetWeChatWinBase();
    DWORD SqlHandleBaseAddr = WeChatWinBase + SqlHandleMicroMsgOffset;
    DWORD SqlHandleBeginAddr = 0x0;
    DWORD SqlHandleEndAddr = 0x0;
    DWORD SqlHandlePublicMsgAddr = *(DWORD *)(WeChatWinBase + SqlHandlePublicMsgOffset);
    DWORD SqlHandleMSGAddr = *(DWORD *)(WeChatWinBase + SqlHandleMSGOffset);
    __asm {
L
ljc545w 已提交
76 77
		mov eax, [SqlHandleBaseAddr];
		mov ecx, [eax];
L
ljc545w 已提交
78
		add ecx, 0x1428;
L
ljc545w 已提交
79 80 81 82
		mov eax, [ecx];
		mov SqlHandleBeginAddr, eax;
		mov eax, [ecx + 0x4];
		mov SqlHandleEndAddr, eax;
L
ljc545w 已提交
83 84 85 86 87 88 89 90 91
    }
    DWORD dwHandle = 0x0;
    // 获取联系人数据库句柄
    while (SqlHandleBeginAddr < SqlHandleEndAddr)
    {
        dwHandle = *(DWORD *)SqlHandleBeginAddr;
        SqlHandleBeginAddr += 0x4;
        if (SqlHandleBeginAddr == SqlHandleEndAddr)
            break;
92 93
        wstring dbname = wstring((wchar_t *)(*(DWORD *)(dwHandle + 0x50)));
        if (dbmap.find(dbname) != dbmap.end())
L
ljc545w 已提交
94 95 96 97 98 99 100
            continue;
        DbInfoStruct db = {0};
        db.dbname = (wchar_t *)(*(DWORD *)(dwHandle + 0x50));
        db.l_dbname = wcslen(db.dbname);
        db.handle = *(DWORD *)(dwHandle + 0x3C);
        ExecuteSQL(*(DWORD *)(dwHandle + 0x3C), "select * from sqlite_master where type=\"table\";", (DWORD)GetDbInfo, &db);
        dbs.push_back(db);
101
        dbmap[dbname] = db;
L
ljc545w 已提交
102 103 104 105 106
    }
    // 获取公众号数据库句柄
    for (int i = 1; i < 4; i++)
    {
        dwHandle = *((DWORD *)(SqlHandlePublicMsgAddr + i * 0x4));
107 108
        wstring dbname = wstring((wchar_t *)(*(DWORD *)(dwHandle + 0x50)));
        if (dbmap.find(dbname) != dbmap.end())
L
ljc545w 已提交
109 110 111 112 113 114 115
            continue;
        DbInfoStruct db = {0};
        db.dbname = (wchar_t *)(*(DWORD *)(dwHandle + 0x50));
        db.l_dbname = wcslen(db.dbname);
        db.handle = *(DWORD *)(dwHandle + 0x3C);
        ExecuteSQL(*(DWORD *)(dwHandle + 0x3C), "select * from sqlite_master where type=\"table\";", (DWORD)GetDbInfo, &db);
        dbs.push_back(db);
116
        dbmap[dbname] = db;
L
ljc545w 已提交
117 118 119 120 121 122 123 124 125
    }
    // 获取聊天记录数据库句柄
    int msgdb_count = *(int *)(SqlHandleMSGAddr + 0x4);
    DWORD MsgdwHandle = *(DWORD *)(SqlHandleMSGAddr + 0x1C);
    for (int i = 0; i < msgdb_count; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            dwHandle = *(DWORD *)(MsgdwHandle + 0x14 + j * 4);
126 127
            wstring dbname = wstring((wchar_t *)(*(DWORD *)(dwHandle + 0x50)));
            if (dbmap.find(dbname) != dbmap.end())
L
ljc545w 已提交
128 129 130 131 132 133 134
                continue;
            DbInfoStruct db = {0};
            db.dbname = (wchar_t *)(*(DWORD *)(dwHandle + 0x50));
            db.l_dbname = wcslen(db.dbname);
            db.handle = *(DWORD *)(dwHandle + 0x3C);
            ExecuteSQL(*(DWORD *)(dwHandle + 0x3C), "select * from sqlite_master where type=\"table\";", (DWORD)GetDbInfo, &db);
            dbs.push_back(db);
135
            dbmap[dbname] = db;
L
ljc545w 已提交
136 137 138 139 140 141
        }
        MsgdwHandle += 0x68;
    }
    // 添加一个空结构体,作为读取结束标志
    DbInfoStruct db_end = {0};
    dbs.push_back(db_end);
L
ljc545w 已提交
142
#ifdef _DEBUG
L
ljc545w 已提交
143 144 145 146 147 148 149 150 151 152 153 154 155
    for (unsigned int i = 0; i < dbs.size() - 1; i++)
    {
        printf("dbname = %ws,handle = 0x%08X,table_count:%d\n", dbs[i].dbname, dbs[i].handle, dbs[i].tables.size());
        for (unsigned int j = 0; j < dbs[i].tables.size(); j++)
        {
            cout << "name     = " << dbs[i].tables[j].name << endl;
            cout << "tbl_name = " << dbs[i].tables[j].tbl_name << endl;
            cout << "rootpage = " << dbs[i].tables[j].rootpage << endl;
            cout << "sql      = " << dbs[i].tables[j].sql << endl;
            cout << endl;
        }
        cout << endl;
    }
L
ljc545w 已提交
156
#endif
L
ljc545w 已提交
157
    vector<void *> ret_array;
L
ljc545w 已提交
158 159
    for (unsigned int i = 0; i < dbs.size() - 1; i++)
        ret_array.push_back(&dbs[i]);
L
ljc545w 已提交
160 161
    return ret_array;
}