提交 655f43b7 编写于 作者: L ljc545w

支持获取更多数据库句柄

上级 5a2f4f11
......@@ -26,7 +26,6 @@ BOOL __stdcall ForwardMessage(wchar_t *wxid, unsigned long long msgid)
int localId = GetLocalIdByMsgId(msgid, dbIndex);
if (localId == 0)
return FALSE;
dbIndex = 0x5000000 + (dbIndex << 8);
WxString p_wxid(wxid);
int isSuccess = 0;
__asm {
......
......@@ -6,6 +6,13 @@
#define SqlHandlePublicMsgOffset 0x239E3C8
// 聊天记录相关库偏移
#define SqlHandleMSGOffset 0x239FF68
// 企业微信相关库偏移
#define SqlHandleOpenIMOffset1 0x239E6E0
#define SqlHandleOpenIMOffset2 0x239FF6C
// 朋友圈数据库偏移
#define SqlHandleSnsOffset 0x23A1744
// 收藏数据库偏移
#define SqlHandleFavoriteOffset 0x23A03B0
// 保存数据库信息的容器
vector<DbInfoStruct> dbs;
......@@ -39,7 +46,7 @@ unsigned int GetLocalIdByMsgId(ULONG64 msgid, int &dbIndex)
vector<vector<string>> result = SelectData(handle, (const char *)sql);
if (result.size() == 0)
continue;
dbIndex = i + 1;
dbIndex = dbmap[dbname].extrainfo;
return stoi(result[1][0]);
}
return 0;
......@@ -67,53 +74,31 @@ vector<void *> GetDbHandles()
dbs.clear();
dbmap.clear();
DWORD WeChatWinBase = GetWeChatWinBase();
DWORD SqlHandleBaseAddr = WeChatWinBase + SqlHandleMicroMsgOffset;
DWORD SqlHandleBeginAddr = 0x0;
DWORD SqlHandleEndAddr = 0x0;
DWORD SqlHandleBaseAddr = *(DWORD *)(WeChatWinBase + SqlHandleMicroMsgOffset) + 0x1428;
DWORD SqlHandleBeginAddr = *(DWORD *)SqlHandleBaseAddr;
DWORD SqlHandleEndAddr = *(DWORD *)(SqlHandleBaseAddr + 0x4);
DWORD SqlHandlePublicMsgAddr = *(DWORD *)(WeChatWinBase + SqlHandlePublicMsgOffset);
DWORD SqlHandleMSGAddr = *(DWORD *)(WeChatWinBase + SqlHandleMSGOffset);
__asm {
mov eax, [SqlHandleBaseAddr];
mov ecx, [eax];
add ecx, 0x1428;
mov eax, [ecx];
mov SqlHandleBeginAddr, eax;
mov eax, [ecx + 0x4];
mov SqlHandleEndAddr, eax;
}
DWORD SqlHandleOpenIMAddr1 = *(DWORD *)(WeChatWinBase + SqlHandleOpenIMOffset1);
DWORD SqlHandleOpenIMAddr2 = *(DWORD *)(WeChatWinBase + SqlHandleOpenIMOffset2);
DWORD SqlHandleSnsAddr = *(DWORD *)(WeChatWinBase + SqlHandleSnsOffset);
DWORD SqlHandleFavoriteAddr = *(DWORD *)(WeChatWinBase + SqlHandleFavoriteOffset);
vector<DWORD> dbaddrs;
DWORD dwHandle = 0x0;
// 获取联系人数据库句柄
while (SqlHandleBeginAddr < SqlHandleEndAddr)
{
dwHandle = *(DWORD *)SqlHandleBeginAddr;
dbaddrs.push_back(dwHandle);
SqlHandleBeginAddr += 0x4;
if (SqlHandleBeginAddr == SqlHandleEndAddr)
break;
wstring dbname = wstring((wchar_t *)(*(DWORD *)(dwHandle + 0x50)));
if (dbmap.find(dbname) != dbmap.end())
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);
dbmap[dbname] = db;
}
// 获取公众号数据库句柄
for (int i = 1; i < 4; i++)
{
dwHandle = *((DWORD *)(SqlHandlePublicMsgAddr + i * 0x4));
wstring dbname = wstring((wchar_t *)(*(DWORD *)(dwHandle + 0x50)));
if (dbmap.find(dbname) != dbmap.end())
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);
dbmap[dbname] = db;
dbaddrs.push_back(dwHandle);
}
// 获取聊天记录数据库句柄
int msgdb_count = *(int *)(SqlHandleMSGAddr + 0x4);
......@@ -123,19 +108,42 @@ vector<void *> GetDbHandles()
for (int j = 0; j < 4; j++)
{
dwHandle = *(DWORD *)(MsgdwHandle + 0x14 + j * 4);
wstring dbname = wstring((wchar_t *)(*(DWORD *)(dwHandle + 0x50)));
if (dbmap.find(dbname) != dbmap.end())
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);
dbmap[dbname] = db;
dbaddrs.push_back(dwHandle);
}
MsgdwHandle += 0x68;
}
// 获取企业微信数据库句柄
dbaddrs.push_back(*(DWORD *)(SqlHandleOpenIMAddr1 + 0x8));
for (int i = 0; i < 3; i++)
{
dwHandle = *(DWORD *)(SqlHandleOpenIMAddr2 + 0xC + i * 4);
dbaddrs.push_back(dwHandle);
}
// 获取朋友圈数据库句柄
dbaddrs.push_back(*(DWORD *)(SqlHandleSnsAddr + 0x64));
// 获取收藏数据库句柄
dbaddrs.push_back(*(DWORD *)(SqlHandleFavoriteAddr + 0x8));
// 获取数据库信息
for (auto dbaddr : dbaddrs)
{
wstring dbname = wstring((wchar_t *)(*(DWORD *)(dbaddr + 0x50)));
if (dbmap.find(dbname) != dbmap.end())
continue;
DbInfoStruct db = {0};
wstring tablename((wchar_t *)(*(DWORD *)(dbaddr + 0x64)));
if (tablename == L"MSG")
{
db.extrainfo = *(DWORD *)(dbaddr + 0x17C);
}
db.dbname = (wchar_t *)(*(DWORD *)(dbaddr + 0x50));
db.l_dbname = wcslen(db.dbname);
db.handle = *(DWORD *)(dbaddr + 0x3C);
ExecuteSQL(*(DWORD *)(dbaddr + 0x3C), "select * from sqlite_master where type=\"table\";", (DWORD)GetDbInfo, &db);
dbs.push_back(db);
dbmap[dbname] = db;
}
// 添加一个空结构体,作为读取结束标志
DbInfoStruct db_end = {0};
dbs.push_back(db_end);
......
......@@ -176,6 +176,7 @@ static void dealMessage(DWORD messageAddr)
jMsg["extrainfo"] = "";
}
jMsg["time"] = unicode_to_utf8((wchar_t *)GetTimeW(*(DWORD *)(messageAddr + 0x44)).c_str());
jMsg["timestamp"] = *(DWORD *)(messageAddr + 0x44);
jMsg["self"] = unicode_to_utf8((wchar_t *)GetSelfWxid().c_str());
string jstr = jMsg.dump() + '\n';
// 为保证线程安全,需要手动管理内存
......
......@@ -104,8 +104,20 @@ string gb2312_to_utf8(const char *strGB2312)
return strTemp;
}
wstring gb2312_to_unicode(const char *buffer)
{
int c_size = MultiByteToWideChar(CP_ACP, 0, buffer, -1, 0, 0);
wchar_t *temp = new wchar_t[c_size + 1];
MultiByteToWideChar(CP_ACP, 0, buffer, -1, temp, c_size);
temp[c_size] = L'\0';
wstring ret(temp);
delete[] temp;
temp = NULL;
return ret;
}
/*
* 将UTF8编码数据转换为GBK编码
* 将UTF8编码数据转换为UNICODE编码
*/
wstring utf8_to_unicode(const char *buffer)
{
......@@ -221,17 +233,15 @@ wstring wreplace(wstring source, wchar_t replaced, wstring replaceto)
*/
wstring GetTimeW(long long timestamp)
{
wchar_t *wstr = new wchar_t[20];
memset(wstr, 0, 20 * 2);
// time_t cTime = time(NULL);
tm tm_out;
localtime_s(&tm_out, &timestamp);
swprintf_s(wstr, 20, L"%04d-%02d-%02d %02d:%02d:%02d",
1900 + tm_out.tm_year, tm_out.tm_mon + 1, tm_out.tm_mday,
tm_out.tm_hour, tm_out.tm_min, tm_out.tm_sec);
wstring strTimeW(wstr);
delete[] wstr;
return strTimeW;
char time_buf[20] = {0};
memset(time_buf, 0, 20);
tm tm_out = {0};
gmtime_s(&tm_out, &timestamp);
// localtime_s(tm_out, &timestamp);
tm_out.tm_hour += 8;
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &tm_out);
string strTime(time_buf);
return utf8_to_unicode(strTime.c_str());
}
void PrintProcAddr()
......
......@@ -16,6 +16,7 @@
#include <string>
#include <string>
#include <sstream>
#include <time.h>
#include "wxdata.h"
#include "wxapi.h"
#include "base64/base64.h"
......
......@@ -44,10 +44,14 @@ using namespace std;
BOOL CreateConsole(void);
DWORD GetWeChatWinBase();
string unicode_to_gb2312(wchar_t *wchar);
string utf8_to_gb2312(const char *strUTF8);
string gb2312_to_utf8(const char *strGB2312);
string unicode_to_utf8(wchar_t *wstr);
string utf8_to_gb2312(const char *strUTF8);
wstring utf8_to_unicode(const char *buffer);
string gb2312_to_utf8(const char *strGB2312);
wstring gb2312_to_unicode(const char *buffer);
void HookAnyAddress(DWORD dwHookAddr, LPVOID dwJmpAddress, char *originalRecieveCode);
void UnHookAnyAddress(DWORD dwHookAddr, char *originalRecieveCode);
DLLEXPORT void UnHookAll();
......@@ -71,3 +75,19 @@ vector<T1> split(T1 str, T2 letter)
arr.push_back(str);
return arr;
}
template <typename T1, typename T2>
T1 replace(T1 source, T2 replaced, T1 replaceto)
{
vector<T1> v_arr = split(source, replaced);
if (v_arr.size() < 2)
return source;
T1 temp;
for (unsigned int i = 0; i < v_arr.size() - 1; i++)
{
temp += v_arr[i];
temp += replaceto;
}
temp += v_arr[v_arr.size() - 1];
return temp;
}
......@@ -141,11 +141,12 @@ struct TableInfoStruct
*/
struct DbInfoStruct
{
DWORD handle;
wchar_t *dbname;
DWORD l_dbname;
DWORD handle = 0;
wchar_t *dbname = NULL;
DWORD l_dbname = 0;
vector<TableInfoStruct> tables;
DWORD count;
DWORD count = 0;
DWORD extrainfo = 0;
};
/*
......
......@@ -148,6 +148,8 @@ CWeChatRobot.exe /unregserver
## 2022.09.22
1. 新增获取a8key功能
2. 修复了一个bug,该bug曾导致获取数据库句柄接口只能生效一次
## 2022.09.27
1. 优化转发消息接口、获取数据库句柄接口,实时消息添加原始时间戳
# 打赏作者
请给作者一个star,感谢感谢
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册