Refine RPC

This commit is contained in:
Changhua 2022-08-07 15:03:17 +08:00
parent 4959b58b23
commit 19f6854b73
8 changed files with 85 additions and 92 deletions

View File

@ -5,13 +5,24 @@
] ]
interface ISpy interface ISpy
{ {
import "rpc_types.h"; import "oaidl.idl";
typedef struct RpcMessage {
int self; // 是否自己发的消息0=否1=是
int type; // 消息类型
int source; // 消息来源0=好友消息1=群消息
BSTR id; // 消息ID
BSTR xml; // 群其他消息
BSTR wxId; // 发送人微信ID
BSTR roomId; // 群ID
BSTR content; // 消息内容MAC版最大16384即16KB
} RpcMessage_t;
int IsLogin(); int IsLogin();
int SendTextMsg([ in, string ] const wchar_t *wxid, [ in, string ] const wchar_t *at_wxid, [ in, string ] const wchar_t *msg); int SendTextMsg([ in, string ] const wchar_t *wxid, [ in, string ] const wchar_t *at_wxid, [ in, string ] const wchar_t *msg);
int SendImageMsg([ in, string ] const wchar_t *wxid, [ in, string ] const wchar_t *path); int SendImageMsg([ in, string ] const wchar_t *wxid, [ in, string ] const wchar_t *path);
void EnableReceiveMsg(); void EnableReceiveMsg();
[callback] int ReceiveMsg([ in ] RpcMessage_t *msg); [callback] int ReceiveMsg([ in ] RpcMessage_t rpcMsg);
}; };

View File

@ -1,18 +1,7 @@
#pragma once #pragma once
#define MSG_SIZE_MSG_ID 64 #define MSG_SIZE_MSG_ID 64
#define MSG_SIZE_MSG_XML 4096 #define MSG_SIZE_MSG_XML 4096
#define MSG_SIZE_WXID 64 #define MSG_SIZE_WXID 64
#define MSG_SIZE_ROOMID 64 #define MSG_SIZE_ROOMID 64
#define MSG_SIZE_CONTENT 16385 #define MSG_SIZE_CONTENT 16385
typedef struct RpcMessage {
int self; // 是否自己发的消息0=否1=是
int type; // 消息类型
int source; // 消息来源0=好友消息1=群消息
wchar_t id[MSG_SIZE_MSG_ID]; // 消息ID
wchar_t xml[MSG_SIZE_MSG_XML]; // 群其他消息
wchar_t wxId[MSG_SIZE_WXID]; // 发送人微信ID
wchar_t roomId[MSG_SIZE_ROOMID]; // 群ID
wchar_t content[MSG_SIZE_CONTENT]; // 消息内容MAC版最大16384即16KB
} RpcMessage_t;

View File

@ -15,8 +15,6 @@
#include "sdk.h" #include "sdk.h"
#include "util.h" #include "util.h"
static HANDLE hEvent;
static std::queue<RpcMessage_t> MsgQueue;
static RPC_WSTR pszStringBinding = NULL; static RPC_WSTR pszStringBinding = NULL;
static std::function<int(WxMessage_t)> cbReceiveTextMsg; static std::function<int(WxMessage_t)> cbReceiveTextMsg;
static const MsgTypesMap_t WxMsgTypes = MsgTypesMap_t { { 0x01, L"文字" }, static const MsgTypesMap_t WxMsgTypes = MsgTypesMap_t { { 0x01, L"文字" },
@ -121,37 +119,6 @@ int WxInitSDK()
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static unsigned int __stdcall waitForMsg(void *p)
{
RpcMessage_t *rpcMsg;
while (true) {
// 中断式兼顾及时性和CPU使用率
WaitForSingleObject(hEvent, INFINITE); // 等待消息
while (!MsgQueue.empty()) {
rpcMsg = (RpcMessage_t *)&MsgQueue.front();
WxMessage_t msg;
msg.id = wstring(rpcMsg->id);
msg.self = rpcMsg->self;
msg.type = rpcMsg->type;
msg.source = rpcMsg->source;
msg.xml = wstring(rpcMsg->xml);
msg.wxId = wstring(rpcMsg->wxId);
msg.roomId = wstring(rpcMsg->roomId);
msg.content = wstring(rpcMsg->content);
try {
cbReceiveTextMsg(msg); // 调用接收消息回调
} catch (...) {
printf("callback error...\n");
}
MsgQueue.pop();
}
ResetEvent(hEvent);
}
return 0;
}
static unsigned int __stdcall innerWxSetTextMsgCb(void *p) static unsigned int __stdcall innerWxSetTextMsgCb(void *p)
{ {
unsigned long ulCode = 0; unsigned long ulCode = 0;
@ -175,13 +142,6 @@ int WxSetTextMsgCb(const std::function<int(WxMessage_t)> &onMsg)
if (onMsg) { if (onMsg) {
HANDLE msgThread; HANDLE msgThread;
cbReceiveTextMsg = onMsg; cbReceiveTextMsg = onMsg;
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
msgThread = (HANDLE)_beginthreadex(NULL, 0, waitForMsg, NULL, 0, NULL);
if (msgThread == NULL) {
printf("Failed to create message listening thread.\n");
return -2;
}
CloseHandle(msgThread);
msgThread = (HANDLE)_beginthreadex(NULL, 0, innerWxSetTextMsgCb, NULL, 0, NULL); msgThread = (HANDLE)_beginthreadex(NULL, 0, innerWxSetTextMsgCb, NULL, 0, NULL);
if (msgThread == NULL) { if (msgThread == NULL) {
@ -197,10 +157,17 @@ int WxSetTextMsgCb(const std::function<int(WxMessage_t)> &onMsg)
return -1; return -1;
} }
int server_ReceiveMsg(RpcMessage_t *rpcMsg) int server_ReceiveMsg(RpcMessage_t rpcMsg)
{ {
MsgQueue.push(*rpcMsg); // 发送消息 WxMessage_t msg;
SetEvent(hEvent); // 发送消息通知 GetRpcMessage(&msg, rpcMsg);
try {
cbReceiveTextMsg(msg); // 调用接收消息回调
}
catch (...) {
printf("callback error...\n");
}
return 0; return 0;
} }

View File

@ -58,7 +58,7 @@ int GetWeChatWinDLLPath(wchar_t *path)
// 微信从大约3.7开始,增加了一层版本目录: [3.7.0.29] // 微信从大约3.7开始,增加了一层版本目录: [3.7.0.29]
PathRemoveFileSpec(path); PathRemoveFileSpec(path);
_wfinddata_t findData; _wfinddata_t findData;
wstring dir = wstring(path) + L"\\[*.*"; wstring dir = wstring(path) + L"\\[*.*";
intptr_t handle = _wfindfirst(dir.c_str(), &findData); intptr_t handle = _wfindfirst(dir.c_str(), &findData);
if (handle == -1) { // 检查是否成功 if (handle == -1) { // 检查是否成功
return -1; return -1;
@ -66,7 +66,7 @@ int GetWeChatWinDLLPath(wchar_t *path)
wstring dllPath = wstring(path) + L"\\" + findData.name; wstring dllPath = wstring(path) + L"\\" + findData.name;
wcscpy_s(path, MAX_PATH, dllPath.c_str()); wcscpy_s(path, MAX_PATH, dllPath.c_str());
PathAppend(path, WECHATWINDLL); PathAppend(path, WECHATWINDLL);
} }
return ret; return ret;
} }
@ -133,17 +133,16 @@ int OpenWeChat(DWORD *pid)
{ {
int ret = -1; int ret = -1;
STARTUPINFO si = { sizeof(si) }; STARTUPINFO si = { sizeof(si) };
WCHAR Path[MAX_PATH] = { 0 };
PROCESS_INFORMATION pi = { 0 }; PROCESS_INFORMATION pi = { 0 };
WCHAR Path[MAX_PATH] = { 0 }; ret = GetWeChatPath(Path);
ret = GetWeChatPath(Path);
if (ERROR_SUCCESS != ret) { if (ERROR_SUCCESS != ret) {
return ret; return ret;
} }
if (!CreateProcess(NULL, Path, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) { if (!CreateProcess(NULL, Path, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
ret = GetLastError(); return GetLastError();
return ret;
} }
CloseHandle(pi.hThread); CloseHandle(pi.hThread);
@ -151,9 +150,7 @@ int OpenWeChat(DWORD *pid)
*pid = pi.dwProcessId; *pid = pi.dwProcessId;
ret = ERROR_SUCCESS; return ERROR_SUCCESS;
return ret;
} }
int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size) int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size)
@ -170,6 +167,30 @@ int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size)
return strLength; return strLength;
} }
BSTR GetBstrByAddress(DWORD address) { return SysAllocStringLen(GET_WSTRING(address), GET_DWORD(address + 4)); }
static wstring GetWstringFromBstr(BSTR p)
{
wstring ret = L"";
if (p != nullptr) {
ret = wstring(p);
SysFreeString(p);
}
return ret;
}
void GetRpcMessage(WxMessage_t *wxMsg, RpcMessage_t rpcMsg)
{
wxMsg->self = rpcMsg.self;
wxMsg->type = rpcMsg.type;
wxMsg->source = rpcMsg.source;
wxMsg->id = GetWstringFromBstr(rpcMsg.id);
wxMsg->xml = GetWstringFromBstr(rpcMsg.xml);
wxMsg->wxId = GetWstringFromBstr(rpcMsg.wxId);
wxMsg->roomId = GetWstringFromBstr(rpcMsg.roomId);
wxMsg->content = GetWstringFromBstr(rpcMsg.content);
}
DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address) DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address)
{ {
DWORD value = 0; DWORD value = 0;

View File

@ -1,6 +1,9 @@
#pragma once #pragma once
#include <string> #include <string>
#include "sdk.h"
#include "rpc_h.h"
#define WECHAREXE L"WeChat.exe" #define WECHAREXE L"WeChat.exe"
#define WECHATWINDLL L"WeChatWin.dll" #define WECHATWINDLL L"WeChatWin.dll"
@ -16,6 +19,8 @@ int GetWeChatPath(wchar_t *path);
int GetWeChatWinDLLPath(wchar_t *path); int GetWeChatWinDLLPath(wchar_t *path);
int GetWeChatVersion(wchar_t *version); int GetWeChatVersion(wchar_t *version);
bool GetFileVersion(const wchar_t *filePath, wchar_t *version); bool GetFileVersion(const wchar_t *filePath, wchar_t *version);
int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size); int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size);
BSTR GetBstrByAddress(DWORD address);
void GetRpcMessage(WxMessage_t *wxMsg, RpcMessage_t rpcMsg);
DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address); DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address);
std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address); std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address);

View File

@ -1,4 +1,4 @@
#include "framework.h" #include "framework.h"
#include "load_calls.h" #include "load_calls.h"
#include "receive_msg.h" #include "receive_msg.h"
@ -14,30 +14,31 @@ MsgQueue_t g_MsgQueue;
DWORD reg_buffer = 0; DWORD reg_buffer = 0;
DWORD recvMsgCallAddr = 0; DWORD recvMsgCallAddr = 0;
DWORD recvMsgJumpBackAddr = 0; DWORD recvMsgJumpBackAddr = 0;
RpcMessage_t *pMsg = NULL; // Find a palce to free RpcMessage_t lMsg = { 0 };
void DispatchMsg(DWORD reg) void DispatchMsg(DWORD reg)
{ {
DWORD *p = (DWORD *)reg; //消息结构基址 DWORD* p = (DWORD*)reg; //消息结构基址
memset(pMsg, 0, sizeof(RpcMessage_t)); memset(&lMsg, 0, sizeof(RpcMessage_t));
pMsg->type = GET_DWORD(*p + g_WxCalls.recvMsg.type); lMsg.type = GET_DWORD(*p + g_WxCalls.recvMsg.type);
pMsg->self = GET_DWORD(*p + g_WxCalls.recvMsg.isSelf); lMsg.self = GET_DWORD(*p + g_WxCalls.recvMsg.isSelf);
lMsg.id = GetBstrByAddress(*p + g_WxCalls.recvMsg.msgId);
lMsg.xml = GetBstrByAddress(*p + g_WxCalls.recvMsg.msgXml);
GetWstringByAddress(*p + g_WxCalls.recvMsg.msgId, pMsg->id, MSG_SIZE_MSG_ID);
GetWstringByAddress(*p + g_WxCalls.recvMsg.msgXml, pMsg->xml, MSG_SIZE_MSG_XML);
if (wcsstr(pMsg->xml, L"<membercount>") == NULL) { if (wcsstr(lMsg.xml, L"<membercount>") == NULL) {
// pMsg.roomId = {0}; // pMsg.roomId = {0};
GetWstringByAddress(*p + g_WxCalls.recvMsg.roomId, pMsg->wxId, MSG_SIZE_WXID); lMsg.wxId = GetBstrByAddress(*p + g_WxCalls.recvMsg.roomId);
} else {
pMsg->source = 1;
GetWstringByAddress(*p + g_WxCalls.recvMsg.roomId, pMsg->roomId, MSG_SIZE_ROOMID);
GetWstringByAddress(*p + g_WxCalls.recvMsg.wxId, pMsg->wxId, MSG_SIZE_WXID);
} }
GetWstringByAddress(*p + g_WxCalls.recvMsg.content, pMsg->content, MSG_SIZE_CONTENT); else {
g_MsgQueue.push(*pMsg); // 发送消息 lMsg.source = 1;
lMsg.wxId = GetBstrByAddress(*p + g_WxCalls.recvMsg.wxId);
lMsg.roomId = GetBstrByAddress(*p + g_WxCalls.recvMsg.roomId);
}
lMsg.content = GetBstrByAddress(*p + g_WxCalls.recvMsg.content);
g_MsgQueue.push(lMsg); // 发送消息
SetEvent(g_hEvent); // 发送消息通知 SetEvent(g_hEvent); // 发送消息通知
} }
@ -63,7 +64,6 @@ void ListenMessage()
return; return;
} }
pMsg = new RpcMessage_t;
DWORD hookAddress = g_WeChatWinDllAddr + g_WxCalls.recvMsg.hook; DWORD hookAddress = g_WeChatWinDllAddr + g_WxCalls.recvMsg.hook;
recvMsgCallAddr = g_WeChatWinDllAddr + g_WxCalls.recvMsg.call; recvMsgCallAddr = g_WeChatWinDllAddr + g_WxCalls.recvMsg.call;
recvMsgJumpBackAddr = hookAddress + 5; recvMsgJumpBackAddr = hookAddress + 5;

View File

@ -25,7 +25,7 @@ void server_EnableReceiveMsg()
// 中断式兼顾及时性和CPU使用率 // 中断式兼顾及时性和CPU使用率
WaitForSingleObject(g_hEvent, INFINITE); // 等待消息 WaitForSingleObject(g_hEvent, INFINITE); // 等待消息
while (!g_MsgQueue.empty()) { while (!g_MsgQueue.empty()) {
client_ReceiveMsg((RpcMessage_t *)&g_MsgQueue.front()); // 调用接收消息回调 client_ReceiveMsg(g_MsgQueue.front()); // 调用接收消息回调
g_MsgQueue.pop(); g_MsgQueue.pop();
} }
ResetEvent(g_hEvent); ResetEvent(g_hEvent);
@ -34,7 +34,7 @@ void server_EnableReceiveMsg()
RpcExcept(1) RpcExcept(1)
{ {
ulCode = RpcExceptionCode(); ulCode = RpcExceptionCode();
printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode); printf("server_EnableReceiveMsg exception 0x%lx = %ld\n", ulCode, ulCode);
} }
RpcEndExcept RpcEndExcept
} }

View File

@ -3,7 +3,7 @@
#include "framework.h" #include "framework.h"
#include <queue> #include <queue>
#include "rpc_types.h" #include "rpc_h.h"
typedef struct UserInfoCall { typedef struct UserInfoCall {
DWORD wxid; DWORD wxid;
@ -19,7 +19,7 @@ typedef struct RecvMsg {
DWORD msgId; // 消息ID地址 DWORD msgId; // 消息ID地址
DWORD msgXml; // 消息xml内容地址 DWORD msgXml; // 消息xml内容地址
DWORD roomId; // 群聊时为群ID私聊时为微信ID DWORD roomId; // 群聊时为群ID私聊时为微信ID
DWORD wxId; // 私聊时,为空;群为发送者微信ID DWORD wxId; // 私聊时,为空;群为发送者微信ID
DWORD content; // 消息内容地址 DWORD content; // 消息内容地址
} RecvMsg_t; } RecvMsg_t;