ReceiveMessage.cpp 6.5 KB
Newer Older
1 2
#include "pch.h"
#include <vector>
L
ljc545w 已提交
3
#include <iostream>
4

L
ljc545w 已提交
5
// 接收消息的HOOK地址偏移
L
ljc545w 已提交
6
#define ReceiveMessageHookOffset 0x547C0F4C - 0x54270000
L
ljc545w 已提交
7
// 接收消息HOOK的CALL偏移
L
ljc545w 已提交
8
#define ReceiveMessageNextCallOffset 0x54D04E60 - 0x54270000
9

L
ljc545w 已提交
10 11 12 13 14
// 发送消息的HOOK地址偏移
#define SendMessageHookOffset 0x102C8E32 - 0x0FDE0000
// 发送消息HOOK的CALL偏移
#define SendMessageNextCallOffset 0x101E8170 - 0x0FDE0000

L
ljc545w 已提交
15 16 17 18 19 20 21 22
/*
* 保存单条信息的结构
* messagetype:消息类型
* sender:发送者wxid;l_sender:`sender`字符数
* wxid:如果sender是群聊id,则此成员保存具体发送人wxid,否则与`sender`一致;l_wxid:`wxid`字符数
* message:消息内容,非文本消息是xml格式;l_message:`message`字符数
* filepath:图片、文件及其他资源的保存路径;l_filepath:`filepath`字符数
*/
23 24
struct messageStruct {
	DWORD messagetype;
L
ljc545w 已提交
25
	BOOL isSendMessage;
26 27 28 29 30 31
	wchar_t* sender;
	DWORD l_sender;
	wchar_t* wxid;
	DWORD l_wxid;
	wchar_t* message;
	DWORD l_message;
L
ljc545w 已提交
32 33
	wchar_t* filepath;
	DWORD l_filepath;
L
ljc545w 已提交
34 35
	wchar_t* time;
	DWORD l_time;
36 37
};

L
ljc545w 已提交
38
// 保存多条信息的动态数组
39 40
vector<messageStruct> messageVector;

L
ljc545w 已提交
41
// 是否开启接收消息HOOK标志
42
BOOL ReceiveMessageHooked = false;
L
ljc545w 已提交
43
// 保存HOOK前的字节码,用于恢复
44
char OldReceiveMessageAsmCode[5] = { 0 };
L
ljc545w 已提交
45
char OldSendMessageAsmCode[5] = { 0 };
L
ljc545w 已提交
46
// 接收消息HOOK地址
47
DWORD ReceiveMessageHookAddress = GetWeChatWinBase() + ReceiveMessageHookOffset;
L
ljc545w 已提交
48
// 接收消息HOOK的CALL地址
49
DWORD ReceiveMessageNextCall = GetWeChatWinBase() + ReceiveMessageNextCallOffset;
L
ljc545w 已提交
50 51 52 53 54 55 56 57
// 接收HOOK的跳转地址
DWORD ReceiveMessageJmpBackAddress = ReceiveMessageHookAddress + 0x5;
// 发送消息HOOK地址
DWORD SendMessageHookAddress = GetWeChatWinBase() + SendMessageHookOffset;
// 发送消息HOOK的CALL地址
DWORD SendMessageNextCall = GetWeChatWinBase() + SendMessageNextCallOffset;
// 发送HOOK的跳转地址
DWORD SendMessageJmpBackAddress = SendMessageHookAddress + 0x5;
58

L
ljc545w 已提交
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
// 创建广播消息数组
static SAFEARRAY* CreateMessageArray(messageStruct* ms) {
	HRESULT hr = S_OK;
	SAFEARRAY* psaValue;
	vector<wstring> MessageInfoKey = {
		L"type",
		L"isSendMessage",
		ms->isSendMessage ? L"sendto" : L"from",
		L"wxid",
		L"message",
		L"filepath",
		L"time"
	};
	SAFEARRAYBOUND rgsaBound[2] = { {MessageInfoKey.size(),0},{2,0} };
	psaValue = SafeArrayCreate(VT_VARIANT, 2, rgsaBound);
	long keyIndex[2] = { 0,0 };
	keyIndex[0] = 0; keyIndex[1] = 0;
	for (unsigned int i = 0; i < MessageInfoKey.size(); i++) {
		keyIndex[0] = i; keyIndex[1] = 0;
		_variant_t key = MessageInfoKey[i].c_str();
		hr = SafeArrayPutElement(psaValue, keyIndex, &key);
		keyIndex[0] = i; keyIndex[1] = 1;
		if (i < 2) {
			_variant_t value = ((DWORD*)ms)[i];
			hr = SafeArrayPutElement(psaValue, keyIndex, &value);
		}
		else {
			_variant_t value = ((wchar_t**)ms)[i * 2 - 2];
			hr = SafeArrayPutElement(psaValue, keyIndex, &value);
		}
	}
	return psaValue;
}

L
ljc545w 已提交
93 94 95 96 97
/*
* 消息处理函数,根据消息缓冲区组装结构并存入容器
* messageAddr:保存消息的缓冲区地址
* return:void
*/
98
VOID ReceiveMessage(DWORD messageAddr) {
L
ljc545w 已提交
99 100 101
	// 此处用于区别是发送的还是接收的消息
	BOOL isSendMessage = *(BOOL*)(messageAddr + 0x3C);

102
	messageStruct message = { 0 };
L
ljc545w 已提交
103 104 105
	message.isSendMessage = isSendMessage;
	message.time = GetTimeW();
	message.l_time = wcslen(message.time);
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
	message.messagetype = *(DWORD*)(messageAddr + 0x38);
	
	DWORD length = *(DWORD*)(messageAddr + 0x48 + 0x4);
	message.sender = new wchar_t[length + 1];
	ZeroMemory(message.sender, (length + 1) * 2);
	memcpy(message.sender,(wchar_t*)(*(DWORD*)(messageAddr + 0x48)),length * 2);
	message.l_sender = length;
	
	length = *(DWORD*)(messageAddr + 0x170 + 0x4);
	if (length == 0) {
		message.wxid = new wchar_t[message.l_sender + 1];
		ZeroMemory(message.wxid, (message.l_sender + 1) * 2);
		memcpy(message.wxid, (wchar_t*)(*(DWORD*)(messageAddr + 0x48)), message.l_sender * 2);
		message.l_wxid = message.l_sender;
	}
	else {
		message.wxid = new wchar_t[length + 1];
		ZeroMemory(message.wxid, (length + 1) * 2);
		memcpy(message.wxid, (wchar_t*)(*(DWORD*)(messageAddr + 0x170)), length * 2);
		message.l_wxid = length;
	}
	
	length = *(DWORD*)(messageAddr + 0x70 + 0x4);
	message.message = new wchar_t[length + 1];
	ZeroMemory(message.message, (length + 1) * 2);
	memcpy(message.message, (wchar_t*)(*(DWORD*)(messageAddr + 0x70)), length * 2);
	message.l_message = length;

L
ljc545w 已提交
134 135 136 137 138
	length = *(DWORD*)(messageAddr + 0x1AC + 0x4);
	message.filepath = new wchar_t[length + 1];
	ZeroMemory(message.filepath, (length + 1) * 2);
	memcpy(message.filepath, (wchar_t*)(*(DWORD*)(messageAddr + 0x1AC)), length * 2);
	message.l_filepath = length;
L
ljc545w 已提交
139 140 141 142 143 144 145
#ifdef USE_COM_EVENT
	// 通过连接点,将消息广播给客户端
	SAFEARRAY* psaValue = CreateMessageArray(&message);
	VARIANT vsaValue;
	vsaValue.vt = VT_ARRAY | VT_VARIANT;
	V_ARRAY(&vsaValue) = psaValue;
	PostComMessage(&vsaValue);
L
ljc545w 已提交
146
#endif
147 148 149
	messageVector.push_back(message);
}

L
ljc545w 已提交
150 151 152 153
/*
* 供外部调用的获取消息接口,优先返回较早消息
* return:DWORD,messageVector第一个成员地址
*/
154 155 156 157 158 159
DWORD GetHeadMessage() {
	if (messageVector.size() == 0)
		return 0;
	return (DWORD)&messageVector[0].messagetype;
}

L
ljc545w 已提交
160 161 162 163
/*
* 供外部调用的删除消息接口,用于删除messageVector第一个成员,每读一条需要执行一次
* return:void
*/
164 165 166
VOID PopHeadMessage() {
	if (messageVector.size() == 0)
		return;
L
ljc545w 已提交
167 168 169 170 171 172 173 174
	delete[] messageVector[0].message;
	messageVector[0].message = NULL;
	delete[] messageVector[0].sender;
	messageVector[0].sender = NULL;
	delete[] messageVector[0].wxid;
	messageVector[0].wxid = NULL;
	delete[] messageVector[0].filepath;
	messageVector[0].filepath = NULL;
L
ljc545w 已提交
175 176
	delete[] messageVector[0].time;
	messageVector[0].time = NULL;
177 178 179 180
	vector<messageStruct>::iterator k = messageVector.begin();
	messageVector.erase(k);
}

L
ljc545w 已提交
181 182 183
/*
* HOOK的具体实现,接收到消息后调用处理函数
*/
184 185 186 187
_declspec(naked) void dealReceiveMessage() {
	__asm {
		pushad;
		pushfd;
L
ljc545w 已提交
188 189
		mov eax, [edi];
		push eax;
190 191 192 193 194
		call ReceiveMessage;
		add esp, 0x4;
		popfd;
		popad;
		call ReceiveMessageNextCall;
L
ljc545w 已提交
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
		jmp ReceiveMessageJmpBackAddress;
	}
}

/*
* HOOK的具体实现,发送消息后调用处理函数
*/
_declspec(naked) void dealSendMessage() {
	__asm {
		pushad;
		pushfd;
		push edi;
		call ReceiveMessage;
		add esp, 0x4;
		popfd;
		popad;
		call SendMessageNextCall;
		jmp SendMessageJmpBackAddress;
213 214 215
	}
}

L
ljc545w 已提交
216 217 218 219
/*
* 开始接收消息HOOK
* return:void
*/
220 221 222 223
VOID HookReceiveMessage() {
	if (ReceiveMessageHooked)
		return;
	HookAnyAddress(ReceiveMessageHookAddress,(LPVOID)dealReceiveMessage,OldReceiveMessageAsmCode);
L
ljc545w 已提交
224
	HookAnyAddress(SendMessageHookAddress, (LPVOID)dealSendMessage, OldSendMessageAsmCode);
225 226 227
	ReceiveMessageHooked = TRUE;
}

L
ljc545w 已提交
228 229 230 231
/*
* 停止接收消息HOOK
* return:void
*/
232 233 234 235
VOID UnHookReceiveMessage() {
	if (!ReceiveMessageHooked)
		return;
	UnHookAnyAddress(ReceiveMessageHookAddress,OldReceiveMessageAsmCode);
L
ljc545w 已提交
236
	UnHookAnyAddress(SendMessageHookAddress, OldSendMessageAsmCode);
237 238
	ReceiveMessageHooked = FALSE;
}