WeChatFerry/spy/receive_msg.cpp
2023-02-19 05:34:10 +08:00

136 lines
4.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma execution_character_set("utf-8")
#include "framework.h"
#include <queue>
#include "load_calls.h"
#include "receive_msg.h"
#include "util.h"
// Defined in rpc_server.cpp
extern bool gIsListening;
extern HANDLE g_hEvent;
extern queue<WxMsg_t> gMsgQueue;
// Defined in spy.cpp
extern WxCalls_t g_WxCalls;
extern DWORD g_WeChatWinDllAddr;
static DWORD reg_buffer = 0;
static DWORD recvMsgHookAddr = 0;
static DWORD recvMsgCallAddr = 0;
static DWORD recvMsgJumpBackAddr = 0;
static CHAR recvMsgBackupCode[5] = { 0 };
MsgTypes_t GetMsgTypes()
{
const MsgTypes_t m = { { 0x01, "文字" },
{ 0x03, "图片" },
{ 0x22, "语音" },
{ 0x25, "好友确认" },
{ 0x28, "POSSIBLEFRIEND_MSG" },
{ 0x2A, "名片" },
{ 0x2B, "视频" },
{ 0x2F, "石头剪刀布 | 表情图片" },
{ 0x30, "位置" },
{ 0x31, "共享实时位置、文件、转账、链接" },
{ 0x32, "VOIPMSG" },
{ 0x33, "微信初始化" },
{ 0x34, "VOIPNOTIFY" },
{ 0x35, "VOIPINVITE" },
{ 0x3E, "小视频" },
{ 0x270F, "SYSNOTICE" },
{ 0x2710, "红包、系统消息" },
{ 0x2712, "撤回消息" } };
return m;
}
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;
DWORD *p = (DWORD *)reg; // 消息结构基址
wxMsg.type = GET_DWORD(*p + g_WxCalls.recvMsg.type);
wxMsg.is_self = GET_DWORD(*p + g_WxCalls.recvMsg.isSelf);
wxMsg.id = GetStringByAddress(*p + g_WxCalls.recvMsg.msgId);
wxMsg.xml = GetStringByAddress(*p + g_WxCalls.recvMsg.msgXml);
// 群里的系统消息xml 为空;或者包含 <membercount>
if ((wxMsg.xml.empty()) || (wxMsg.xml.find("<membercount>") != string::npos)) {
wxMsg.is_group = true;
wxMsg.sender = GetStringByAddress(*p + g_WxCalls.recvMsg.wxId);
wxMsg.roomid = GetStringByAddress(*p + g_WxCalls.recvMsg.roomId);
} else {
wxMsg.is_group = false;
wxMsg.sender = GetStringByAddress(*p + g_WxCalls.recvMsg.roomId);
}
wxMsg.content = GetStringByAddress(*p + g_WxCalls.recvMsg.content);
// 推送到队列
gMsgQueue.push(wxMsg);
// 通知各方消息就绪
SetEvent(g_hEvent);
}
__declspec(naked) void RecieveMsgFunc()
{
__asm {
mov reg_buffer, edi // 把值复制出来
}
DispatchMsg(reg_buffer);
__asm
{
call recvMsgCallAddr // 这个为被覆盖的call
jmp recvMsgJumpBackAddr // 跳回被HOOK指令的下一条指令
}
}
void ListenMessage()
{
// OutputDebugString(L"ListenMessage\n");
// MessageBox(NULL, L"ListenMessage", L"ListenMessage", 0);
if (gIsListening || (g_WeChatWinDllAddr == 0)) {
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;
}