ReceiveMessage.cpp 8.6 KB
Newer Older
1 2
#include "pch.h"
#include <vector>
L
ljc545w 已提交
3 4
#include <winsock2.h>
#include <Ws2tcpip.h>
L
ljc545w 已提交
5
#include <map>
L
ljc545w 已提交
6 7 8 9 10 11

#pragma comment(lib, "ws2_32.lib")

using namespace std;

#define CLTIP "127.0.0.1"
12

L
ljc545w 已提交
13
// 接收消息的HOOK地址偏移
L
ljc545w 已提交
14
#define ReceiveMessageHookOffset 0x78BF0F4C - 0x786A0000
L
ljc545w 已提交
15
// 接收消息HOOK的CALL偏移
L
ljc545w 已提交
16
#define ReceiveMessageNextCallOffset 0x79136350 - 0x786A0000
17

L
ljc545w 已提交
18
// 发送消息的HOOK地址偏移
L
ljc545w 已提交
19
#define SendMessageHookOffset 0x78B88E42 - 0x786A0000
L
ljc545w 已提交
20
// 发送消息HOOK的CALL偏移
L
ljc545w 已提交
21
#define SendMessageNextCallOffset 0x78AA8170 - 0x786A0000
L
ljc545w 已提交
22

L
ljc545w 已提交
23 24
#define READ_WSTRING(addr, offset) wstring((wchar_t *)(*(DWORD *)(addr + offset)), *(DWORD *)(addr + offset + 0x4))

L
ljc545w 已提交
25 26
static int SRVPORT = 0;

L
ljc545w 已提交
27 28 29 30 31 32 33 34 35 36 37
struct ScoketMsgStruct
{
    DWORD pid;
    int messagetype;
    BOOL isSendMessage;
    unsigned long long msgid;
    wchar_t sender[80];
    wchar_t wxid[80];
    wchar_t message[0x1000B];
    wchar_t filepath[MAX_PATH];
    wchar_t time[30];
L
ljc545w 已提交
38
};
39

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

L
ljc545w 已提交
59
// 通过socket将消息发送给服务端
L
ljc545w 已提交
60
BOOL SendSocketMessage(ReceiveMsgStruct *ms)
L
ljc545w 已提交
61
{
L
ljc545w 已提交
62 63 64 65 66 67 68 69
    shared_ptr<ReceiveMsgStruct> shared_ms(ms);
    if (SRVPORT == 0)
    {
        return false;
    }
    SOCKET clientsocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (clientsocket < 0)
    {
L
ljc545w 已提交
70
#ifdef _DEBUG
L
ljc545w 已提交
71 72
        cout << "create socket error,"
             << " errno:" << errno << endl;
L
ljc545w 已提交
73
#endif
L
ljc545w 已提交
74 75 76 77 78 79 80 81
        return false;
    }
    BOOL status = false;
    sockaddr_in clientAddr;
    memset(&clientAddr, 0, sizeof(clientAddr));
    clientAddr.sin_family = AF_INET;
    clientAddr.sin_port = htons((u_short)SRVPORT);
    InetPtonA(AF_INET, CLTIP, &clientAddr.sin_addr.s_addr);
L
ljc545w 已提交
82

L
ljc545w 已提交
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
    if (connect(clientsocket, reinterpret_cast<sockaddr *>(&clientAddr), sizeof(sockaddr)) < 0)
    {
#ifdef _DEBUG
        cout << "connect error,"
             << " errno:" << errno << endl;
#endif
        return false;
    }
    char recvbuf[1024] = {0};
    auto sms = std::make_shared<ScoketMsgStruct>();
    ZeroMemory(sms.get(), sizeof(ScoketMsgStruct));
    sms->pid = shared_ms->pid;
    sms->messagetype = shared_ms->messagetype;
    sms->isSendMessage = shared_ms->isSendMessage;
    sms->msgid = shared_ms->msgid;
    memcpy(sms->wxid, shared_ms->wxid.c_str(), shared_ms->wxid.length() * 2);
    memcpy(sms->sender, shared_ms->sender.c_str(), shared_ms->sender.length() * 2);
    memcpy(sms->message, shared_ms->message.c_str(), shared_ms->message.length() * 2);
    memcpy(sms->filepath, shared_ms->filepath.c_str(), shared_ms->filepath.length() * 2);
    memcpy(sms->time, shared_ms->time.c_str(), shared_ms->time.length() * 2);
L
ljc545w 已提交
103
#ifdef _DEBUG
L
ljc545w 已提交
104
    wcout << sms->time << endl;
L
ljc545w 已提交
105
#endif
L
ljc545w 已提交
106 107 108
    int ret = send(clientsocket, (char *)sms.get(), sizeof(ScoketMsgStruct), 0);
    if (ret == -1 || ret == 0)
    {
L
ljc545w 已提交
109
#ifdef _DEBUG
L
ljc545w 已提交
110 111
        cout << "send fail,"
             << " errno:" << errno << endl;
L
ljc545w 已提交
112
#endif
L
ljc545w 已提交
113 114 115 116 117 118 119 120
        closesocket(clientsocket);
        return false;
    }
    memset(recvbuf, 0, sizeof(recvbuf));
    ret = recv(clientsocket, recvbuf, sizeof(recvbuf), 0);
    closesocket(clientsocket);
    if (ret == -1 || ret == 0)
    {
L
ljc545w 已提交
121
#ifdef _DEBUG
L
ljc545w 已提交
122
        cout << "the server close" << endl;
L
ljc545w 已提交
123
#endif
L
ljc545w 已提交
124 125 126
        return false;
    }
    return true;
L
ljc545w 已提交
127 128
}

L
ljc545w 已提交
129
// 创建广播消息数组
130
#ifndef USE_SOCKET
L
ljc545w 已提交
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
static SAFEARRAY *CreateMessageArray(map<wstring, _variant_t> msg)
{
    HRESULT hr = S_OK;
    SAFEARRAY *psaValue;
    vector<wstring> MessageInfoKey = {
        L"pid",
        L"type",
        L"isSendMessage",
        L"msgid",
        msg[L"isSendMessage"].boolVal ? 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;
        hr = SafeArrayPutElement(psaValue, keyIndex, &msg[MessageInfoKey[i]]);
    }
    return psaValue;
L
ljc545w 已提交
161
}
162
#endif
L
ljc545w 已提交
163

L
ljc545w 已提交
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
static void dealMessage(DWORD messageAddr)
{
    BOOL isSendMessage = *(BOOL *)(messageAddr + 0x3C);
    ReceiveMsgStruct *message = new ReceiveMsgStruct;
    ZeroMemory(message, sizeof(ReceiveMsgStruct));
    message->pid = GetCurrentProcessId();
    message->isSendMessage = isSendMessage;
    message->time = GetTimeW(*(DWORD *)(messageAddr + 0x44));
    message->messagetype = *(DWORD *)(messageAddr + 0x38);
    message->msgid = *(unsigned long long *)(messageAddr + 0x30);
    message->sender = READ_WSTRING(messageAddr, 0x48);
    int length = *(DWORD *)(messageAddr + 0x170 + 0x4);
    if (length == 0)
    {
        message->wxid = message->sender;
    }
    else
    {
        message->wxid = READ_WSTRING(messageAddr, 0x170);
    }
    message->message = READ_WSTRING(messageAddr, 0x70);
    message->filepath = READ_WSTRING(messageAddr, 0x1AC);
186
#ifdef USE_COM
L
ljc545w 已提交
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
    // 通过连接点,将消息广播给客户端
    map<wstring, _variant_t> msg_map;
    msg_map[L"pid"] = message->pid;
    msg_map[L"isSendMessage"] = isSendMessage;
    msg_map[L"time"] = message->time.c_str();
    msg_map[L"type"] = message->messagetype;
    msg_map[L"msgid"] = message->msgid;
    msg_map[L"sendto"] = message->sender.c_str();
    msg_map[L"from"] = message->sender.c_str();
    msg_map[L"wxid"] = message->wxid.c_str();
    msg_map[L"message"] = message->message.c_str();
    msg_map[L"filepath"] = message->filepath.c_str();
    SAFEARRAY *psaValue = CreateMessageArray(msg_map);
    VARIANT vsaValue;
    vsaValue.vt = VT_ARRAY | VT_VARIANT;
    V_ARRAY(&vsaValue) = psaValue;
203
    PostComMessage(message->pid, WX_MESSAGE, message->msgid, &vsaValue);
L
ljc545w 已提交
204
#endif
L
ljc545w 已提交
205 206 207 208 209
    HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SendSocketMessage, message, NULL, 0);
    if (hThread)
    {
        CloseHandle(hThread);
    }
210 211
}

L
ljc545w 已提交
212
/*
213 214 215 216
 * 消息处理函数,根据消息缓冲区组装结构并存入容器
 * messageAddr:保存消息的缓冲区地址
 * return:void
 */
L
ljc545w 已提交
217 218 219 220 221 222 223 224
VOID ReceiveMessage(DWORD messagesAddr)
{
    // 此处用于区别是发送的还是接收的消息
    DWORD *messages = (DWORD *)messagesAddr;
    for (DWORD messageAddr = messages[0]; messageAddr < messages[1]; messageAddr += 0x298)
    {
        dealMessage(messageAddr);
    }
L
ljc545w 已提交
225 226
}

L
ljc545w 已提交
227
/*
228 229
 * HOOK的具体实现,接收到消息后调用处理函数
 */
L
ljc545w 已提交
230 231 232
_declspec(naked) void dealReceiveMessage()
{
    __asm {
233 234
		pushad;
		pushfd;
L
ljc545w 已提交
235
		push edi;
236 237 238 239 240
		call ReceiveMessage;
		add esp, 0x4;
		popfd;
		popad;
		call ReceiveMessageNextCall;
L
ljc545w 已提交
241
		jmp ReceiveMessageJmpBackAddress;
L
ljc545w 已提交
242
    }
L
ljc545w 已提交
243 244 245
}

/*
246 247
 * HOOK的具体实现,发送消息后调用处理函数
 */
L
ljc545w 已提交
248 249 250
_declspec(naked) void dealSendMessage()
{
    __asm {
L
ljc545w 已提交
251 252 253
		pushad;
		pushfd;
		push edi;
L
ljc545w 已提交
254
		call dealMessage;
L
ljc545w 已提交
255 256 257 258 259
		add esp, 0x4;
		popfd;
		popad;
		call SendMessageNextCall;
		jmp SendMessageJmpBackAddress;
L
ljc545w 已提交
260
    }
261 262
}

L
ljc545w 已提交
263
/*
264 265 266
 * 开始接收消息HOOK
 * return:void
 */
L
ljc545w 已提交
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
VOID HookReceiveMessage(int port)
{
    SRVPORT = port;
    WeChatWinBase = GetWeChatWinBase();
    if (ReceiveMessageHooked || !WeChatWinBase)
        return;
    ReceiveMessageHookAddress = WeChatWinBase + ReceiveMessageHookOffset;
    ReceiveMessageNextCall = WeChatWinBase + ReceiveMessageNextCallOffset;
    ReceiveMessageJmpBackAddress = ReceiveMessageHookAddress + 0x5;
    SendMessageHookAddress = WeChatWinBase + SendMessageHookOffset;
    SendMessageNextCall = WeChatWinBase + SendMessageNextCallOffset;
    SendMessageJmpBackAddress = SendMessageHookAddress + 0x5;
    HookAnyAddress(ReceiveMessageHookAddress, (LPVOID)dealReceiveMessage, OldReceiveMessageAsmCode);
    HookAnyAddress(SendMessageHookAddress, (LPVOID)dealSendMessage, OldSendMessageAsmCode);
    ReceiveMessageHooked = TRUE;
282 283
}

L
ljc545w 已提交
284
/*
285 286 287
 * 停止接收消息HOOK
 * return:void
 */
L
ljc545w 已提交
288 289 290 291 292 293 294 295 296
VOID UnHookReceiveMessage()
{
    SRVPORT = 0;
    if (!ReceiveMessageHooked)
        return;
    UnHookAnyAddress(ReceiveMessageHookAddress, OldReceiveMessageAsmCode);
    UnHookAnyAddress(SendMessageHookAddress, OldSendMessageAsmCode);
    ReceiveMessageHooked = FALSE;
}