Impl refresh pyq
This commit is contained in:
parent
e7aad958c8
commit
9101b37162
@ -23,9 +23,14 @@ namespace fs = std::filesystem;
|
|||||||
|
|
||||||
extern bool gIsListeningPyq;
|
extern bool gIsListeningPyq;
|
||||||
extern WxCalls_t g_WxCalls;
|
extern WxCalls_t g_WxCalls;
|
||||||
extern UINT64 g_WeChatWinDllAddr;
|
extern QWORD g_WeChatWinDllAddr;
|
||||||
|
|
||||||
int IsLogin(void) { return (int)GET_UINT64(g_WeChatWinDllAddr + g_WxCalls.login); }
|
typedef QWORD (*funcGetSNSDataMgr_t)();
|
||||||
|
typedef QWORD (*funcGetSnsTimeLineMgr_t)();
|
||||||
|
typedef QWORD (*funcGetSNSFirstPage_t)(QWORD, QWORD, QWORD);
|
||||||
|
typedef QWORD (*funcGetSNSNextPageScene_t)(QWORD, QWORD);
|
||||||
|
|
||||||
|
int IsLogin(void) { return (int)GET_QWORD(g_WeChatWinDllAddr + g_WxCalls.login); }
|
||||||
|
|
||||||
static string get_key(uint8_t header1, uint8_t header2, uint8_t *key)
|
static string get_key(uint8_t header1, uint8_t header2, uint8_t *key)
|
||||||
{
|
{
|
||||||
@ -114,56 +119,34 @@ string DecryptImage(string src, string dir)
|
|||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static int GetFirstPage()
|
static int GetFirstPage()
|
||||||
{
|
{
|
||||||
int rv = -1;
|
int status = -1;
|
||||||
DWORD pyqCall1 = g_WeChatWinDllAddr + g_WxCalls.pyq.call1;
|
|
||||||
DWORD pyqCall2 = g_WeChatWinDllAddr + g_WxCalls.pyq.call2;
|
|
||||||
|
|
||||||
char buf[0xB44] = { 0 };
|
funcGetSNSDataMgr_t GetSNSDataMgr = (funcGetSNSDataMgr_t)(g_WeChatWinDllAddr + 0x22A91C0);
|
||||||
__asm {
|
funcGetSNSFirstPage_t GetSNSFirstPage = (funcGetSNSFirstPage_t)(g_WeChatWinDllAddr + 0x2ED9080);
|
||||||
pushad;
|
|
||||||
call pyqCall1;
|
QWORD buff[16] = { 0 };
|
||||||
push 0x1;
|
QWORD mgr = GetSNSDataMgr();
|
||||||
lea ecx, buf;
|
status = (int)GetSNSFirstPage(mgr, (QWORD)buff, 1);
|
||||||
push ecx;
|
|
||||||
mov ecx, eax;
|
return status;
|
||||||
call pyqCall2;
|
|
||||||
mov rv, eax;
|
|
||||||
popad;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
static int GetNextPage(QWORD id)
|
||||||
}
|
|
||||||
|
|
||||||
static int GetNextPage(uint64_t id)
|
|
||||||
{
|
{
|
||||||
int rv = -1;
|
int status = -1;
|
||||||
DWORD pyqCall1 = g_WeChatWinDllAddr + g_WxCalls.pyq.call1;
|
|
||||||
DWORD pyqCall3 = g_WeChatWinDllAddr + g_WxCalls.pyq.call3;
|
|
||||||
|
|
||||||
RawVector_t tmp = { 0 };
|
funcGetSnsTimeLineMgr_t GetSnsTimeLineMgr = (funcGetSnsTimeLineMgr_t)(g_WeChatWinDllAddr + 0x2E6B110);
|
||||||
|
funcGetSNSNextPageScene_t GetSNSNextPageScene = (funcGetSNSNextPageScene_t)(g_WeChatWinDllAddr + 0x2EFEC00);
|
||||||
|
|
||||||
__asm {
|
QWORD mgr = GetSnsTimeLineMgr();
|
||||||
pushad;
|
status = (int)GetSNSNextPageScene(mgr, id);
|
||||||
call pyqCall1;
|
|
||||||
lea ecx, tmp;
|
return status;
|
||||||
push ecx;
|
|
||||||
mov ebx, dword ptr [id + 0x04];
|
|
||||||
push ebx;
|
|
||||||
mov edi, dword ptr [id]
|
|
||||||
push edi;
|
|
||||||
mov ecx, eax;
|
|
||||||
call pyqCall3;
|
|
||||||
mov rv, eax;
|
|
||||||
popad;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
int RefreshPyq(QWORD id)
|
||||||
}
|
|
||||||
|
|
||||||
int RefreshPyq(uint64_t id)
|
|
||||||
{
|
{
|
||||||
if (!gIsListeningPyq) {
|
if (!gIsListeningPyq) {
|
||||||
LOG_ERROR("没有启动朋友圈消息接收,参考:enable_receiving_msg");
|
LOG_ERROR("没有启动朋友圈消息接收,参考:enable_receiving_msg");
|
||||||
@ -177,10 +160,11 @@ int RefreshPyq(uint64_t id)
|
|||||||
return GetNextPage(id);
|
return GetNextPage(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
int DownloadAttach(uint64_t id, string thumb, string extra)
|
#if 0
|
||||||
|
int DownloadAttach(QWORD id, string thumb, string extra)
|
||||||
{
|
{
|
||||||
int status = -1;
|
int status = -1;
|
||||||
uint64_t localId;
|
QWORD localId;
|
||||||
uint32_t dbIdx;
|
uint32_t dbIdx;
|
||||||
|
|
||||||
if (fs::exists(extra)) { // 第一道,不重复下载
|
if (fs::exists(extra)) { // 第一道,不重复下载
|
||||||
@ -279,10 +263,10 @@ int DownloadAttach(uint64_t id, string thumb, string extra)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RevokeMsg(uint64_t id)
|
int RevokeMsg(QWORD id)
|
||||||
{
|
{
|
||||||
int status = -1;
|
int status = -1;
|
||||||
uint64_t localId;
|
QWORD localId;
|
||||||
uint32_t dbIdx;
|
uint32_t dbIdx;
|
||||||
if (GetLocalIdandDbidx(id, &localId, &dbIdx) != 0) {
|
if (GetLocalIdandDbidx(id, &localId, &dbIdx) != 0) {
|
||||||
LOG_ERROR("Failed to get localId, Please check id: {}", to_string(id));
|
LOG_ERROR("Failed to get localId, Please check id: {}", to_string(id));
|
||||||
@ -325,7 +309,7 @@ int RevokeMsg(uint64_t id)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
string GetAudio(uint64_t id, string dir)
|
string GetAudio(QWORD id, string dir)
|
||||||
{
|
{
|
||||||
string mp3path = (dir.back() == '\\' || dir.back() == '/') ? dir : (dir + "/");
|
string mp3path = (dir.back() == '\\' || dir.back() == '/') ? dir : (dir + "/");
|
||||||
mp3path += to_string(id) + ".mp3";
|
mp3path += to_string(id) + ".mp3";
|
||||||
|
@ -24,11 +24,15 @@ extern QWORD g_WeChatWinDllAddr;
|
|||||||
|
|
||||||
typedef QWORD (*funcRecvMsg_t)(QWORD, QWORD);
|
typedef QWORD (*funcRecvMsg_t)(QWORD, QWORD);
|
||||||
typedef QWORD (*funcWxLog_t)(QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD);
|
typedef QWORD (*funcWxLog_t)(QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD, QWORD);
|
||||||
|
typedef QWORD (*funcRecvPyq_t)(QWORD, QWORD, QWORD);
|
||||||
|
|
||||||
static funcRecvMsg_t funcRecvMsg = nullptr;
|
static funcRecvMsg_t funcRecvMsg = nullptr;
|
||||||
static funcRecvMsg_t realRecvMsg = nullptr;
|
static funcRecvMsg_t realRecvMsg = nullptr;
|
||||||
static funcWxLog_t funcWxLog = nullptr;
|
static funcWxLog_t funcWxLog = nullptr;
|
||||||
static funcWxLog_t realWxLog = nullptr;
|
static funcWxLog_t realWxLog = nullptr;
|
||||||
|
static funcRecvPyq_t funcRecvPyq = nullptr;
|
||||||
|
static funcRecvPyq_t realRecvPyq = nullptr;
|
||||||
|
static bool isMH_Initialized = false;
|
||||||
|
|
||||||
MsgTypes_t GetMsgTypes()
|
MsgTypes_t GetMsgTypes()
|
||||||
{
|
{
|
||||||
@ -140,6 +144,38 @@ static QWORD PrintWxLog(QWORD a1, QWORD a2, QWORD a3, QWORD a4, QWORD a5, QWORD
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void DispatchPyq(QWORD arg1, QWORD arg2, QWORD arg3)
|
||||||
|
{
|
||||||
|
QWORD startAddr = *(QWORD *)(arg2 + 0x30);
|
||||||
|
QWORD endAddr = *(QWORD *)(arg2 + 0x38);
|
||||||
|
|
||||||
|
if (startAddr == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (startAddr < endAddr) {
|
||||||
|
WxMsg_t wxMsg;
|
||||||
|
|
||||||
|
wxMsg.type = 0x00; // 朋友圈消息
|
||||||
|
wxMsg.is_self = false;
|
||||||
|
wxMsg.is_group = false;
|
||||||
|
wxMsg.id = GET_QWORD(startAddr);
|
||||||
|
wxMsg.ts = GET_DWORD(startAddr + 0x38);
|
||||||
|
wxMsg.xml = GetStringByWstrAddr(startAddr + 0x9B8);
|
||||||
|
wxMsg.sender = GetStringByWstrAddr(startAddr + 0x18);
|
||||||
|
wxMsg.content = GetStringByWstrAddr(startAddr + 0x48);
|
||||||
|
|
||||||
|
{
|
||||||
|
unique_lock<mutex> lock(gMutex);
|
||||||
|
gMsgQueue.push(wxMsg); // 推送到队列
|
||||||
|
}
|
||||||
|
|
||||||
|
gCV.notify_all(); // 通知各方消息就绪
|
||||||
|
|
||||||
|
startAddr += 0x1618;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EnableLog()
|
void EnableLog()
|
||||||
{
|
{
|
||||||
MH_STATUS status = MH_UNKNOWN;
|
MH_STATUS status = MH_UNKNOWN;
|
||||||
@ -149,11 +185,14 @@ void EnableLog()
|
|||||||
}
|
}
|
||||||
funcWxLog_t funcWxLog = (funcWxLog_t)(g_WeChatWinDllAddr + 0x26DA2D0);
|
funcWxLog_t funcWxLog = (funcWxLog_t)(g_WeChatWinDllAddr + 0x26DA2D0);
|
||||||
|
|
||||||
|
if (!isMH_Initialized) {
|
||||||
status = MH_Initialize();
|
status = MH_Initialize();
|
||||||
if (status != MH_OK) {
|
if (status != MH_OK) {
|
||||||
LOG_ERROR("MH_Initialize failed: {}", to_string(status));
|
LOG_ERROR("MH_Initialize failed: {}", to_string(status));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
isMH_Initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
status = MH_CreateHook(funcWxLog, &PrintWxLog, reinterpret_cast<LPVOID *>(&realWxLog));
|
status = MH_CreateHook(funcWxLog, &PrintWxLog, reinterpret_cast<LPVOID *>(&realWxLog));
|
||||||
if (status != MH_OK) {
|
if (status != MH_OK) {
|
||||||
@ -182,13 +221,14 @@ void DisableLog()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gIsLogging = false;
|
||||||
|
if (isMH_Initialized and !gIsLogging and !gIsListening and !gIsListeningPyq) {
|
||||||
status = MH_Uninitialize();
|
status = MH_Uninitialize();
|
||||||
if (status != MH_OK) {
|
if (status != MH_OK) {
|
||||||
LOG_ERROR("MH_Uninitialize failed: {}", to_string(status));
|
LOG_ERROR("MH_Uninitialize failed: {}", to_string(status));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
gIsLogging = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListenMessage()
|
void ListenMessage()
|
||||||
@ -200,11 +240,14 @@ void ListenMessage()
|
|||||||
}
|
}
|
||||||
funcRecvMsg = (funcRecvMsg_t)(g_WeChatWinDllAddr + g_WxCalls.recvMsg.call);
|
funcRecvMsg = (funcRecvMsg_t)(g_WeChatWinDllAddr + g_WxCalls.recvMsg.call);
|
||||||
|
|
||||||
|
if (!isMH_Initialized) {
|
||||||
status = MH_Initialize();
|
status = MH_Initialize();
|
||||||
if (status != MH_OK) {
|
if (status != MH_OK) {
|
||||||
LOG_ERROR("MH_Initialize failed: {}", to_string(status));
|
LOG_ERROR("MH_Initialize failed: {}", to_string(status));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
isMH_Initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
status = MH_CreateHook(funcRecvMsg, &DispatchMsg, reinterpret_cast<LPVOID *>(&realRecvMsg));
|
status = MH_CreateHook(funcRecvMsg, &DispatchMsg, reinterpret_cast<LPVOID *>(&realRecvMsg));
|
||||||
if (status != MH_OK) {
|
if (status != MH_OK) {
|
||||||
@ -241,208 +284,73 @@ void UnListenMessage()
|
|||||||
}
|
}
|
||||||
|
|
||||||
gIsListening = false;
|
gIsListening = false;
|
||||||
}
|
if (isMH_Initialized and !gIsLogging and !gIsListening and !gIsListeningPyq) {
|
||||||
|
status = MH_Uninitialize();
|
||||||
void ListenPyq() { }
|
if (status != MH_OK) {
|
||||||
|
LOG_ERROR("MH_Uninitialize failed: {}", to_string(status));
|
||||||
void UnListenPyq() { }
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// static DWORD reg_buffer = 0;
|
|
||||||
// static DWORD recvMsgHookAddr = 0;
|
|
||||||
// static DWORD recvMsgCallAddr = 0;
|
|
||||||
// static DWORD recvMsgJumpBackAddr = 0;
|
|
||||||
// static CHAR recvMsgBackupCode[5] = { 0 };
|
|
||||||
|
|
||||||
// static DWORD recvPyqHookAddr = 0;
|
|
||||||
// static DWORD recvPyqCallAddr = 0;
|
|
||||||
// static DWORD recvPyqJumpBackAddr = 0;
|
|
||||||
// static CHAR recvPyqBackupCode[5] = { 0 };
|
|
||||||
|
|
||||||
void HookAddress(DWORD hookAddr, LPVOID funcAddr, CHAR recvMsgBackupCode[5])
|
|
||||||
{
|
|
||||||
// 组装跳转数据
|
|
||||||
BYTE jmpCode[5] = { 0 };
|
|
||||||
jmpCode[0] = 0xE9;
|
|
||||||
|
|
||||||
// 计算偏移
|
|
||||||
*(DWORD *)&jmpCode[1] = (DWORD)funcAddr - hookAddr - 5;
|
|
||||||
|
|
||||||
// 备份原来的代码
|
|
||||||
ReadProcessMemory(GetCurrentProcess(), (LPVOID)hookAddr, recvMsgBackupCode, 5, 0);
|
|
||||||
// 写入新的代码
|
|
||||||
WriteProcessMemory(GetCurrentProcess(), (LPVOID)hookAddr, jmpCode, 5, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnHookAddress(DWORD hookAddr, CHAR restoreCode[5])
|
|
||||||
{
|
|
||||||
WriteProcessMemory(GetCurrentProcess(), (LPVOID)hookAddr, restoreCode, 5, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DispatchMsg(DWORD reg)
|
|
||||||
{
|
|
||||||
WxMsg_t wxMsg;
|
|
||||||
try {
|
|
||||||
wxMsg.id = GET_QWORD(reg + g_WxCalls.recvMsg.msgId);
|
|
||||||
wxMsg.type = GET_DWORD(reg + g_WxCalls.recvMsg.type);
|
|
||||||
wxMsg.is_self = GET_DWORD(reg + g_WxCalls.recvMsg.isSelf);
|
|
||||||
wxMsg.ts = GET_DWORD(reg + g_WxCalls.recvMsg.ts);
|
|
||||||
wxMsg.content = GetStringByWstrAddr(reg + g_WxCalls.recvMsg.content);
|
|
||||||
wxMsg.sign = GetStringByStrAddr(reg + g_WxCalls.recvMsg.sign);
|
|
||||||
wxMsg.xml = GetStringByStrAddr(reg + g_WxCalls.recvMsg.msgXml);
|
|
||||||
|
|
||||||
string roomid = GetStringByWstrAddr(reg + g_WxCalls.recvMsg.roomId);
|
|
||||||
if (roomid.find("@chatroom") != string::npos) { // 群 ID 的格式为 xxxxxxxxxxx@chatroom
|
|
||||||
wxMsg.is_group = true;
|
|
||||||
wxMsg.roomid = roomid;
|
|
||||||
if (wxMsg.is_self) {
|
|
||||||
wxMsg.sender = GetSelfWxid();
|
|
||||||
} else {
|
|
||||||
wxMsg.sender = GetStringByStrAddr(reg + g_WxCalls.recvMsg.wxid);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
wxMsg.is_group = false;
|
|
||||||
if (wxMsg.is_self) {
|
|
||||||
wxMsg.sender = GetSelfWxid();
|
|
||||||
} else {
|
|
||||||
wxMsg.sender = roomid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wxMsg.thumb = GetStringByStrAddr(reg + g_WxCalls.recvMsg.thumb);
|
|
||||||
if (!wxMsg.thumb.empty()) {
|
|
||||||
wxMsg.thumb = GetHomePath() + wxMsg.thumb;
|
|
||||||
replace(wxMsg.thumb.begin(), wxMsg.thumb.end(), '\\', '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
wxMsg.extra = GetStringByStrAddr(reg + g_WxCalls.recvMsg.extra);
|
|
||||||
if (!wxMsg.extra.empty()) {
|
|
||||||
wxMsg.extra = GetHomePath() + wxMsg.extra;
|
|
||||||
replace(wxMsg.extra.begin(), wxMsg.extra.end(), '\\', '/');
|
|
||||||
}
|
|
||||||
} catch (const std::exception &e) {
|
|
||||||
LOG_ERROR(GB2312ToUtf8(e.what()));
|
|
||||||
} catch (...) {
|
|
||||||
LOG_ERROR("Unknow exception.");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
unique_lock<mutex> lock(gMutex);
|
|
||||||
gMsgQueue.push(wxMsg); // 推送到队列
|
|
||||||
}
|
|
||||||
|
|
||||||
gCV.notify_all(); // 通知各方消息就绪
|
|
||||||
}
|
|
||||||
|
|
||||||
__declspec(naked) void RecieveMsgFunc()
|
|
||||||
{
|
|
||||||
__asm {
|
|
||||||
pushad
|
|
||||||
pushfd
|
|
||||||
push ecx
|
|
||||||
call DispatchMsg
|
|
||||||
add esp, 0x4
|
|
||||||
popfd
|
|
||||||
popad
|
|
||||||
call recvMsgCallAddr // 这个为被覆盖的call
|
|
||||||
jmp recvMsgJumpBackAddr // 跳回被HOOK指令的下一条指令
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListenMessage()
|
|
||||||
{
|
|
||||||
// DbgMsg("ListenMessage");
|
|
||||||
// OutputDebugString(L"ListenMessage\n");
|
|
||||||
// MessageBox(NULL, L"ListenMessage", L"ListenMessage", 0);
|
|
||||||
if (gIsListening || (g_WeChatWinDllAddr == 0)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
recvMsgHookAddr = g_WeChatWinDllAddr + g_WxCalls.recvMsg.hook;
|
|
||||||
recvMsgCallAddr = g_WeChatWinDllAddr + g_WxCalls.recvMsg.call;
|
|
||||||
recvMsgJumpBackAddr = recvMsgHookAddr + 5;
|
|
||||||
|
|
||||||
HookAddress(recvMsgHookAddr, RecieveMsgFunc, recvMsgBackupCode);
|
|
||||||
gIsListening = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnListenMessage()
|
|
||||||
{
|
|
||||||
if (!gIsListening) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
UnHookAddress(recvMsgHookAddr, recvMsgBackupCode);
|
|
||||||
gIsListening = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DispatchPyq(DWORD reg)
|
|
||||||
{
|
|
||||||
DWORD startAddr = *(DWORD *)(reg + g_WxCalls.pyq.start);
|
|
||||||
DWORD endAddr = *(DWORD *)(reg + g_WxCalls.pyq.end);
|
|
||||||
|
|
||||||
if (startAddr == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (startAddr < endAddr) {
|
|
||||||
WxMsg_t wxMsg;
|
|
||||||
|
|
||||||
wxMsg.type = 0x00; // 朋友圈消息
|
|
||||||
wxMsg.is_self = false;
|
|
||||||
wxMsg.is_group = false;
|
|
||||||
wxMsg.id = GET_QWORD(startAddr);
|
|
||||||
wxMsg.ts = GET_DWORD(startAddr + g_WxCalls.pyq.ts);
|
|
||||||
wxMsg.xml = GetStringByWstrAddr(startAddr + g_WxCalls.pyq.xml);
|
|
||||||
wxMsg.sender = GetStringByWstrAddr(startAddr + g_WxCalls.pyq.wxid);
|
|
||||||
wxMsg.content = GetStringByWstrAddr(startAddr + g_WxCalls.pyq.content);
|
|
||||||
|
|
||||||
{
|
|
||||||
unique_lock<mutex> lock(gMutex);
|
|
||||||
gMsgQueue.push(wxMsg); // 推送到队列
|
|
||||||
}
|
|
||||||
|
|
||||||
gCV.notify_all(); // 通知各方消息就绪
|
|
||||||
|
|
||||||
startAddr += g_WxCalls.pyq.step;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__declspec(naked) void RecievePyqFunc()
|
|
||||||
{
|
|
||||||
__asm {
|
|
||||||
pushad
|
|
||||||
pushfd
|
|
||||||
push [esp + 0x24]
|
|
||||||
call DispatchPyq
|
|
||||||
add esp, 0x4
|
|
||||||
popfd
|
|
||||||
popad
|
|
||||||
call recvPyqCallAddr // 这个为被覆盖的call
|
|
||||||
jmp recvPyqJumpBackAddr // 跳回被HOOK指令的下一条指令
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListenPyq()
|
void ListenPyq()
|
||||||
{
|
{
|
||||||
|
MH_STATUS status = MH_UNKNOWN;
|
||||||
if (gIsListeningPyq || (g_WeChatWinDllAddr == 0)) {
|
if (gIsListeningPyq || (g_WeChatWinDllAddr == 0)) {
|
||||||
|
LOG_WARN("gIsListeningPyq || (g_WeChatWinDllAddr == 0)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
funcRecvPyq = (funcRecvPyq_t)(g_WeChatWinDllAddr + 0x2EFAA10);
|
||||||
|
|
||||||
|
if (!isMH_Initialized) {
|
||||||
|
status = MH_Initialize();
|
||||||
|
if (status != MH_OK) {
|
||||||
|
LOG_ERROR("MH_Initialize failed: {}", to_string(status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isMH_Initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = MH_CreateHook(funcRecvPyq, &DispatchPyq, reinterpret_cast<LPVOID *>(&realRecvPyq));
|
||||||
|
if (status != MH_OK) {
|
||||||
|
LOG_ERROR("MH_CreateHook failed: {}", to_string(status));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
recvPyqHookAddr = g_WeChatWinDllAddr + g_WxCalls.pyq.hook;
|
status = MH_EnableHook(funcRecvPyq);
|
||||||
recvPyqCallAddr = g_WeChatWinDllAddr + g_WxCalls.pyq.call;
|
if (status != MH_OK) {
|
||||||
recvPyqJumpBackAddr = recvPyqHookAddr + 5;
|
LOG_ERROR("MH_EnableHook failed: {}", to_string(status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
HookAddress(recvPyqHookAddr, RecievePyqFunc, recvPyqBackupCode);
|
|
||||||
gIsListeningPyq = true;
|
gIsListeningPyq = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnListenPyq()
|
void UnListenPyq()
|
||||||
{
|
{
|
||||||
|
MH_STATUS status = MH_UNKNOWN;
|
||||||
if (!gIsListeningPyq) {
|
if (!gIsListeningPyq) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UnHookAddress(recvPyqHookAddr, recvPyqBackupCode);
|
status = MH_DisableHook(funcRecvPyq);
|
||||||
gIsListeningPyq = false;
|
if (status != MH_OK) {
|
||||||
|
LOG_ERROR("MH_DisableHook failed: {}", to_string(status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = MH_Uninitialize();
|
||||||
|
if (status != MH_OK) {
|
||||||
|
LOG_ERROR("MH_Uninitialize failed: {}", to_string(status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gIsListeningPyq = false;
|
||||||
|
if (isMH_Initialized and !gIsLogging and !gIsListening and !gIsListeningPyq) {
|
||||||
|
status = MH_Uninitialize();
|
||||||
|
if (status != MH_OK) {
|
||||||
|
LOG_ERROR("MH_Uninitialize failed: {}", to_string(status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
@ -571,6 +571,24 @@ bool func_exec_db_query(char *db, char *sql, uint8_t *out, size_t *len)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool func_refresh_pyq(uint64_t id, uint8_t *out, size_t *len)
|
||||||
|
{
|
||||||
|
Response rsp = Response_init_default;
|
||||||
|
rsp.func = Functions_FUNC_REFRESH_PYQ;
|
||||||
|
rsp.which_msg = Response_status_tag;
|
||||||
|
|
||||||
|
rsp.msg.status = RefreshPyq(id);
|
||||||
|
|
||||||
|
pb_ostream_t stream = pb_ostream_from_buffer(out, *len);
|
||||||
|
if (!pb_encode(&stream, Response_fields, &rsp)) {
|
||||||
|
LOG_ERROR("Encoding failed: {}", PB_GET_ERROR(&stream));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*len = stream.bytes_written;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
bool func_accept_friend(char *v3, char *v4, int32_t scene, uint8_t *out, size_t *len)
|
bool func_accept_friend(char *v3, char *v4, int32_t scene, uint8_t *out, size_t *len)
|
||||||
{
|
{
|
||||||
@ -618,24 +636,6 @@ bool func_receive_transfer(char *wxid, char *tfid, char *taid, uint8_t *out, siz
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool func_refresh_pyq(uint64_t id, uint8_t *out, size_t *len)
|
|
||||||
{
|
|
||||||
Response rsp = Response_init_default;
|
|
||||||
rsp.func = Functions_FUNC_REFRESH_PYQ;
|
|
||||||
rsp.which_msg = Response_status_tag;
|
|
||||||
|
|
||||||
rsp.msg.status = RefreshPyq(id);
|
|
||||||
|
|
||||||
pb_ostream_t stream = pb_ostream_from_buffer(out, *len);
|
|
||||||
if (!pb_encode(&stream, Response_fields, &rsp)) {
|
|
||||||
LOG_ERROR("Encoding failed: {}", PB_GET_ERROR(&stream));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*len = stream.bytes_written;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool func_download_attach(AttachMsg att, uint8_t *out, size_t *len)
|
bool func_download_attach(AttachMsg att, uint8_t *out, size_t *len)
|
||||||
{
|
{
|
||||||
Response rsp = Response_init_default;
|
Response rsp = Response_init_default;
|
||||||
@ -934,6 +934,10 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len
|
|||||||
ret = func_exec_db_query(req.msg.query.db, req.msg.query.sql, out, out_len);
|
ret = func_exec_db_query(req.msg.query.db, req.msg.query.sql, out, out_len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Functions_FUNC_REFRESH_PYQ: {
|
||||||
|
ret = func_refresh_pyq(req.msg.ui64, out, out_len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
#if 0
|
#if 0
|
||||||
case Functions_FUNC_ACCEPT_FRIEND: {
|
case Functions_FUNC_ACCEPT_FRIEND: {
|
||||||
ret = func_accept_friend(req.msg.v.v3, req.msg.v.v4, req.msg.v.scene, out, out_len);
|
ret = func_accept_friend(req.msg.v.v3, req.msg.v.v4, req.msg.v.scene, out, out_len);
|
||||||
@ -943,10 +947,6 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len
|
|||||||
ret = func_receive_transfer(req.msg.tf.wxid, req.msg.tf.tfid, req.msg.tf.taid, out, out_len);
|
ret = func_receive_transfer(req.msg.tf.wxid, req.msg.tf.tfid, req.msg.tf.taid, out, out_len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Functions_FUNC_REFRESH_PYQ: {
|
|
||||||
ret = func_refresh_pyq(req.msg.ui64, out, out_len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Functions_FUNC_DOWNLOAD_ATTACH: {
|
case Functions_FUNC_DOWNLOAD_ATTACH: {
|
||||||
ret = func_download_attach(req.msg.att, out, out_len);
|
ret = func_download_attach(req.msg.att, out, out_len);
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user