From 19f6854b738f9fb669738a155529706c6ad6e7bf Mon Sep 17 00:00:00 2001 From: Changhua Date: Sun, 7 Aug 2022 15:03:17 +0800 Subject: [PATCH 1/8] Refine RPC --- Rpc/rpc.idl | 17 +++++++++++--- Rpc/rpc_types.h | 13 +---------- SDK/sdk.cpp | 55 +++++++++------------------------------------ SDK/util.cpp | 39 ++++++++++++++++++++++++-------- SDK/util.h | 11 ++++++--- Spy/receive_msg.cpp | 34 ++++++++++++++-------------- Spy/rpc_server.cpp | 4 ++-- Spy/spy_types.h | 4 ++-- 8 files changed, 85 insertions(+), 92 deletions(-) diff --git a/Rpc/rpc.idl b/Rpc/rpc.idl index 50d0893..0cd4ef8 100644 --- a/Rpc/rpc.idl +++ b/Rpc/rpc.idl @@ -5,13 +5,24 @@ ] 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 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); void EnableReceiveMsg(); - [callback] int ReceiveMsg([ in ] RpcMessage_t *msg); + [callback] int ReceiveMsg([ in ] RpcMessage_t rpcMsg); }; diff --git a/Rpc/rpc_types.h b/Rpc/rpc_types.h index b897a96..d4ad805 100644 --- a/Rpc/rpc_types.h +++ b/Rpc/rpc_types.h @@ -1,18 +1,7 @@ -#pragma once +#pragma once #define MSG_SIZE_MSG_ID 64 #define MSG_SIZE_MSG_XML 4096 #define MSG_SIZE_WXID 64 #define MSG_SIZE_ROOMID 64 #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; diff --git a/SDK/sdk.cpp b/SDK/sdk.cpp index 9d45954..2c7d1cb 100644 --- a/SDK/sdk.cpp +++ b/SDK/sdk.cpp @@ -15,8 +15,6 @@ #include "sdk.h" #include "util.h" -static HANDLE hEvent; -static std::queue MsgQueue; static RPC_WSTR pszStringBinding = NULL; static std::function cbReceiveTextMsg; static const MsgTypesMap_t WxMsgTypes = MsgTypesMap_t { { 0x01, L"文字" }, @@ -121,37 +119,6 @@ int WxInitSDK() 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) { unsigned long ulCode = 0; @@ -175,13 +142,6 @@ int WxSetTextMsgCb(const std::function &onMsg) if (onMsg) { HANDLE msgThread; 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); if (msgThread == NULL) { @@ -197,10 +157,17 @@ int WxSetTextMsgCb(const std::function &onMsg) return -1; } -int server_ReceiveMsg(RpcMessage_t *rpcMsg) -{ - MsgQueue.push(*rpcMsg); // 发送消息 - SetEvent(hEvent); // 发送消息通知 +int server_ReceiveMsg(RpcMessage_t rpcMsg) +{ + WxMessage_t msg; + GetRpcMessage(&msg, rpcMsg); + try { + cbReceiveTextMsg(msg); // 调用接收消息回调 + } + catch (...) { + printf("callback error...\n"); + } + return 0; } diff --git a/SDK/util.cpp b/SDK/util.cpp index 0d8a96e..2445bb0 100644 --- a/SDK/util.cpp +++ b/SDK/util.cpp @@ -58,7 +58,7 @@ int GetWeChatWinDLLPath(wchar_t *path) // 微信从(大约)3.7开始,增加了一层版本目录: [3.7.0.29] PathRemoveFileSpec(path); _wfinddata_t findData; - wstring dir = wstring(path) + L"\\[*.*"; + wstring dir = wstring(path) + L"\\[*.*"; intptr_t handle = _wfindfirst(dir.c_str(), &findData); if (handle == -1) { // 检查是否成功 return -1; @@ -66,7 +66,7 @@ int GetWeChatWinDLLPath(wchar_t *path) wstring dllPath = wstring(path) + L"\\" + findData.name; wcscpy_s(path, MAX_PATH, dllPath.c_str()); PathAppend(path, WECHATWINDLL); - } + } return ret; } @@ -133,17 +133,16 @@ int OpenWeChat(DWORD *pid) { int ret = -1; STARTUPINFO si = { sizeof(si) }; + WCHAR Path[MAX_PATH] = { 0 }; PROCESS_INFORMATION pi = { 0 }; - WCHAR Path[MAX_PATH] = { 0 }; - ret = GetWeChatPath(Path); + ret = GetWeChatPath(Path); if (ERROR_SUCCESS != ret) { return ret; } if (!CreateProcess(NULL, Path, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) { - ret = GetLastError(); - return ret; + return GetLastError(); } CloseHandle(pi.hThread); @@ -151,9 +150,7 @@ int OpenWeChat(DWORD *pid) *pid = pi.dwProcessId; - ret = ERROR_SUCCESS; - - return ret; + return ERROR_SUCCESS; } 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; } +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 value = 0; diff --git a/SDK/util.h b/SDK/util.h index 19084e1..c61a6b1 100644 --- a/SDK/util.h +++ b/SDK/util.h @@ -1,6 +1,9 @@ -#pragma once +#pragma once -#include +#include + +#include "sdk.h" +#include "rpc_h.h" #define WECHAREXE L"WeChat.exe" #define WECHATWINDLL L"WeChatWin.dll" @@ -16,6 +19,8 @@ int GetWeChatPath(wchar_t *path); int GetWeChatWinDLLPath(wchar_t *path); int GetWeChatVersion(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); std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address); diff --git a/Spy/receive_msg.cpp b/Spy/receive_msg.cpp index ce21af1..714b09d 100644 --- a/Spy/receive_msg.cpp +++ b/Spy/receive_msg.cpp @@ -1,4 +1,4 @@ -#include "framework.h" +#include "framework.h" #include "load_calls.h" #include "receive_msg.h" @@ -14,30 +14,31 @@ MsgQueue_t g_MsgQueue; DWORD reg_buffer = 0; DWORD recvMsgCallAddr = 0; DWORD recvMsgJumpBackAddr = 0; -RpcMessage_t *pMsg = NULL; // Find a palce to free +RpcMessage_t lMsg = { 0 }; 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); - pMsg->self = GET_DWORD(*p + g_WxCalls.recvMsg.isSelf); + lMsg.type = GET_DWORD(*p + g_WxCalls.recvMsg.type); + 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"") == NULL) { + if (wcsstr(lMsg.xml, L"") == NULL) { // pMsg.roomId = {0}; - GetWstringByAddress(*p + g_WxCalls.recvMsg.roomId, pMsg->wxId, MSG_SIZE_WXID); - } 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); + lMsg.wxId = GetBstrByAddress(*p + g_WxCalls.recvMsg.roomId); } - GetWstringByAddress(*p + g_WxCalls.recvMsg.content, pMsg->content, MSG_SIZE_CONTENT); - g_MsgQueue.push(*pMsg); // 发送消息 + else { + 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); // 发送消息通知 } @@ -63,7 +64,6 @@ void ListenMessage() return; } - pMsg = new RpcMessage_t; DWORD hookAddress = g_WeChatWinDllAddr + g_WxCalls.recvMsg.hook; recvMsgCallAddr = g_WeChatWinDllAddr + g_WxCalls.recvMsg.call; recvMsgJumpBackAddr = hookAddress + 5; diff --git a/Spy/rpc_server.cpp b/Spy/rpc_server.cpp index 932a155..daeed03 100644 --- a/Spy/rpc_server.cpp +++ b/Spy/rpc_server.cpp @@ -25,7 +25,7 @@ void server_EnableReceiveMsg() // 中断式,兼顾及时性和CPU使用率 WaitForSingleObject(g_hEvent, INFINITE); // 等待消息 while (!g_MsgQueue.empty()) { - client_ReceiveMsg((RpcMessage_t *)&g_MsgQueue.front()); // 调用接收消息回调 + client_ReceiveMsg(g_MsgQueue.front()); // 调用接收消息回调 g_MsgQueue.pop(); } ResetEvent(g_hEvent); @@ -34,7 +34,7 @@ void server_EnableReceiveMsg() RpcExcept(1) { ulCode = RpcExceptionCode(); - printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode); + printf("server_EnableReceiveMsg exception 0x%lx = %ld\n", ulCode, ulCode); } RpcEndExcept } diff --git a/Spy/spy_types.h b/Spy/spy_types.h index 3b2ee29..6c98504 100644 --- a/Spy/spy_types.h +++ b/Spy/spy_types.h @@ -3,7 +3,7 @@ #include "framework.h" #include -#include "rpc_types.h" +#include "rpc_h.h" typedef struct UserInfoCall { DWORD wxid; @@ -19,7 +19,7 @@ typedef struct RecvMsg { DWORD msgId; // 消息ID地址 DWORD msgXml; // 消息xml内容地址 DWORD roomId; // 群聊时,为群ID;私聊时,为微信ID - DWORD wxId; // 私聊时,为空;群群时,为发送者微信ID + DWORD wxId; // 私聊时,为空;群聊时,为发送者微信ID DWORD content; // 消息内容地址 } RecvMsg_t; From 2905d49c59013e8bcc265533895d3b534fac5714 Mon Sep 17 00:00:00 2001 From: Changhua Date: Sun, 7 Aug 2022 15:36:55 +0800 Subject: [PATCH 2/8] Remove rpc_types.h --- Rpc/rpc.idl | 2 +- Rpc/rpc_types.h | 7 ------- SDK/sdk.cpp | 1 - Spy/Spy.vcxproj | 1 - Spy/Spy.vcxproj.filters | 3 --- 5 files changed, 1 insertion(+), 13 deletions(-) delete mode 100644 Rpc/rpc_types.h diff --git a/Rpc/rpc.idl b/Rpc/rpc.idl index 0cd4ef8..34b56aa 100644 --- a/Rpc/rpc.idl +++ b/Rpc/rpc.idl @@ -1,4 +1,4 @@ -[ +[ uuid(ed838ecd-8a1e-4da7-bfda-9f2d12d07893), version(1.0), implicit_handle(handle_t hSpyBinding), diff --git a/Rpc/rpc_types.h b/Rpc/rpc_types.h deleted file mode 100644 index d4ad805..0000000 --- a/Rpc/rpc_types.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#define MSG_SIZE_MSG_ID 64 -#define MSG_SIZE_MSG_XML 4096 -#define MSG_SIZE_WXID 64 -#define MSG_SIZE_ROOMID 64 -#define MSG_SIZE_CONTENT 16385 diff --git a/SDK/sdk.cpp b/SDK/sdk.cpp index 2c7d1cb..46cdfaa 100644 --- a/SDK/sdk.cpp +++ b/SDK/sdk.cpp @@ -11,7 +11,6 @@ #pragma comment(lib, "Rpcrt4.lib") #include "injector.h" -#include "rpc_types.h" #include "sdk.h" #include "util.h" diff --git a/Spy/Spy.vcxproj b/Spy/Spy.vcxproj index 2b4569a..28b3413 100644 --- a/Spy/Spy.vcxproj +++ b/Spy/Spy.vcxproj @@ -163,7 +163,6 @@ - diff --git a/Spy/Spy.vcxproj.filters b/Spy/Spy.vcxproj.filters index d34335b..d756e4f 100644 --- a/Spy/Spy.vcxproj.filters +++ b/Spy/Spy.vcxproj.filters @@ -27,9 +27,6 @@ 头文件 - - Rpc - 头文件 From de0c61cae91a345130f86aff8faef66911d001ee Mon Sep 17 00:00:00 2001 From: Changhua Date: Sun, 7 Aug 2022 16:21:28 +0800 Subject: [PATCH 3/8] Refine RPC --- SDK/SDK.vcxproj | 2 + SDK/SDK.vcxproj.filters | 6 ++ SDK/rpc_client.cpp | 127 ++++++++++++++++++++++++++++++++++++ SDK/rpc_client.h | 11 ++++ SDK/sdk.cpp | 141 ++++------------------------------------ 5 files changed, 158 insertions(+), 129 deletions(-) create mode 100644 SDK/rpc_client.cpp create mode 100644 SDK/rpc_client.h diff --git a/SDK/SDK.vcxproj b/SDK/SDK.vcxproj index f16a252..2f481de 100644 --- a/SDK/SDK.vcxproj +++ b/SDK/SDK.vcxproj @@ -161,6 +161,7 @@ + @@ -169,6 +170,7 @@ + diff --git a/SDK/SDK.vcxproj.filters b/SDK/SDK.vcxproj.filters index 848686a..66ebf04 100644 --- a/SDK/SDK.vcxproj.filters +++ b/SDK/SDK.vcxproj.filters @@ -30,6 +30,9 @@ 头文件 + + 头文件 + @@ -50,6 +53,9 @@ 源文件 + + 源文件 + diff --git a/SDK/rpc_client.cpp b/SDK/rpc_client.cpp new file mode 100644 index 0000000..ce2517b --- /dev/null +++ b/SDK/rpc_client.cpp @@ -0,0 +1,127 @@ +#include "sdk.h" +#include "util.h" +#include "rpc_client.h" + +#pragma comment(lib, "Rpcrt4.lib") + +static RPC_WSTR pszStringBinding = NULL; +extern std::function g_cbReceiveTextMsg; + +RPC_STATUS RpcConnectServer() +{ + RPC_STATUS status = 0; + // Creates a string binding handle. + status = RpcStringBindingCompose(NULL, // UUID to bind to + reinterpret_cast((RPC_WSTR)L"ncalrpc"), // Use TCP/IP protocol + NULL, // TCP/IP network address to use + reinterpret_cast((RPC_WSTR)L"tmp_endpoint"), // TCP/IP port to use + NULL, // Protocol dependent network options to use + &pszStringBinding); // String binding output + + if (status) + return status; + + /* Validates the format of the string binding handle and converts it to a binding handle. + pszStringBinding: The string binding to validate + hSpyBinding: Put the result in the implicit binding(defined in the IDL file) + */ + status = RpcBindingFromStringBinding(pszStringBinding, &hSpyBinding); + + return status; +} + +RPC_STATUS RpcDisconnectServer() +{ + RPC_STATUS status; + // Free the memory allocated by a string + status = RpcStringFree(&pszStringBinding); + if (status) + return status; + + // Releases binding handle resources and disconnects from the server + status = RpcBindingFree(&hSpyBinding); + + return status; +} + +unsigned int __stdcall RpcSetTextMsgCb(void *p) +{ + unsigned long ulCode = 0; + RpcTryExcept + { + // 建立RPC通道,让服务端能够调用客户端的回调函数。(该接口会被服务端阻塞直到异常退出) + client_EnableReceiveMsg(); + } + RpcExcept(1) + { + ulCode = RpcExceptionCode(); + printf("rpcWxSetTextMsgCb exception 0x%lx = %ld\n", ulCode, ulCode); + } + RpcEndExcept; + + return 0; +} + +int RpcIsLogin() +{ + int loginFlag = 0; + unsigned long ulCode = 0; + RpcTryExcept + { + // 查询登录状态 + loginFlag = client_IsLogin(); + } + RpcExcept(1) + { + ulCode = RpcExceptionCode(); + printf("rpcIsLogin exception 0x%lx = %ld\n", ulCode, ulCode); + } + RpcEndExcept; + + return loginFlag; +} + +int RpcSendTextMsg(const wchar_t *wxid, const wchar_t *at_wxid, const wchar_t *msg) +{ + int ret = 0; + unsigned long ulCode = 0; + + RpcTryExcept { ret = client_SendTextMsg(wxid, at_wxid, msg); } + RpcExcept(1) + { + ulCode = RpcExceptionCode(); + printf("rpcWxSendTextMsg exception 0x%lx = %ld\n", ulCode, ulCode); + } + RpcEndExcept; + + return ret; +} + +int RpcSendImageMsg(const wchar_t *wxid, const wchar_t *path) +{ + int ret = 0; + unsigned long ulCode = 0; + + RpcTryExcept { ret = client_SendImageMsg(wxid, path); } + RpcExcept(1) + { + ulCode = RpcExceptionCode(); + printf("rpcWxSendImageMsg exception 0x%lx = %ld\n", ulCode, ulCode); + } + RpcEndExcept; + + return ret; +} + +int server_ReceiveMsg(RpcMessage_t rpcMsg) +{ + WxMessage_t msg; + GetRpcMessage(&msg, rpcMsg); + try { + g_cbReceiveTextMsg(msg); // 调用接收消息回调 + } catch (...) { + printf("callback error...\n"); + } + + return 0; +} diff --git a/SDK/rpc_client.h b/SDK/rpc_client.h new file mode 100644 index 0000000..f958d5f --- /dev/null +++ b/SDK/rpc_client.h @@ -0,0 +1,11 @@ +#pragma once + +#include "rpc_h.h" + +RPC_STATUS RpcConnectServer(); +RPC_STATUS RpcDisconnectServer(); + +unsigned int __stdcall RpcSetTextMsgCb(void *p); +int RpcIsLogin(); +int RpcSendTextMsg(const wchar_t *wxid, const wchar_t *at_wxid, const wchar_t *msg); +int RpcSendImageMsg(const wchar_t *wxid, const wchar_t *path); diff --git a/SDK/sdk.cpp b/SDK/sdk.cpp index 46cdfaa..9428289 100644 --- a/SDK/sdk.cpp +++ b/SDK/sdk.cpp @@ -7,15 +7,12 @@ #include #include -#include "../Rpc/rpc_h.h" -#pragma comment(lib, "Rpcrt4.lib") - #include "injector.h" +#include "rpc_client.h" #include "sdk.h" #include "util.h" -static RPC_WSTR pszStringBinding = NULL; -static std::function cbReceiveTextMsg; +std::function g_cbReceiveTextMsg; static const MsgTypesMap_t WxMsgTypes = MsgTypesMap_t { { 0x01, L"文字" }, { 0x03, L"图片" }, { 0x22, L"语音" }, @@ -35,56 +32,18 @@ static const MsgTypesMap_t WxMsgTypes = MsgTypesMap_t { { 0x01, L"文字" }, { 0x2710, L"红包、系统消息" }, { 0x2712, L"撤回消息" } }; -RPC_STATUS RpcConnectServer() -{ - RPC_STATUS status = 0; - // Creates a string binding handle. - status = RpcStringBindingCompose(NULL, // UUID to bind to - reinterpret_cast((RPC_WSTR)L"ncalrpc"), // Use TCP/IP protocol - NULL, // TCP/IP network address to use - reinterpret_cast((RPC_WSTR)L"tmp_endpoint"), // TCP/IP port to use - NULL, // Protocol dependent network options to use - &pszStringBinding); // String binding output - - if (status) - return status; - - /* Validates the format of the string binding handle and converts it to a binding handle. - pszStringBinding: The string binding to validate - hSpyBinding: Put the result in the implicit binding(defined in the IDL file) - */ - status = RpcBindingFromStringBinding(pszStringBinding, &hSpyBinding); - - return status; -} - -RPC_STATUS RpcDisconnectServer() -{ - RPC_STATUS status; - // Free the memory allocated by a string - status = RpcStringFree(&pszStringBinding); - if (status) - return status; - - // Releases binding handle resources and disconnects from the server - status = RpcBindingFree(&hSpyBinding); - - return status; -} - int WxInitSDK() { - int loginFlag = 0; unsigned long ulCode = 0; DWORD status = 0; DWORD pid = 0; WCHAR DllPath[MAX_PATH] = { 0 }; - GetModuleFileNameW(GetModuleHandleW(WECHATSDKDLL), DllPath, MAX_PATH); - PathRemoveFileSpecW(DllPath); - PathAppendW(DllPath, WECHATINJECTDLL); + GetModuleFileName(GetModuleHandle(WECHATSDKDLL), DllPath, MAX_PATH); + PathRemoveFileSpec(DllPath); + PathAppend(DllPath, WECHATINJECTDLL); - if (!PathFileExistsW(DllPath)) { + if (!PathFileExists(DllPath)) { return ERROR_FILE_NOT_FOUND; } @@ -99,50 +58,20 @@ int WxInitSDK() RpcConnectServer(); - while (!loginFlag) { - RpcTryExcept - { - // 查询登录状态 - loginFlag = client_IsLogin(); - } - RpcExcept(1) - { - ulCode = RpcExceptionCode(); - printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode); - } - RpcEndExcept - - Sleep(1000); + while (!RpcIsLogin()) { + Sleep(1000); } return ERROR_SUCCESS; } -static unsigned int __stdcall innerWxSetTextMsgCb(void *p) -{ - unsigned long ulCode = 0; - RpcTryExcept - { - // 建立RPC通道,让服务端能够调用客户端的回调函数。(该接口会被服务端阻塞直到异常退出) - client_EnableReceiveMsg(); - } - RpcExcept(1) - { - ulCode = RpcExceptionCode(); - printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode); - } - RpcEndExcept - - return 0; -} - int WxSetTextMsgCb(const std::function &onMsg) { if (onMsg) { HANDLE msgThread; - cbReceiveTextMsg = onMsg; + g_cbReceiveTextMsg = onMsg; - msgThread = (HANDLE)_beginthreadex(NULL, 0, innerWxSetTextMsgCb, NULL, 0, NULL); + msgThread = (HANDLE)_beginthreadex(NULL, 0, RpcSetTextMsgCb, NULL, 0, NULL); if (msgThread == NULL) { printf("Failed to create innerWxRecvTextMsg.\n"); return -2; @@ -156,58 +85,12 @@ int WxSetTextMsgCb(const std::function &onMsg) return -1; } -int server_ReceiveMsg(RpcMessage_t rpcMsg) -{ - WxMessage_t msg; - GetRpcMessage(&msg, rpcMsg); - try { - cbReceiveTextMsg(msg); // 调用接收消息回调 - } - catch (...) { - printf("callback error...\n"); - } - - return 0; -} - -static int innerWxSendTextMsg(const wchar_t *wxid, const wchar_t *at_wxid, const wchar_t *msg) -{ - int ret = 0; - unsigned long ulCode = 0; - - RpcTryExcept { ret = client_SendTextMsg(wxid, at_wxid, msg); } - RpcExcept(1) - { - ulCode = RpcExceptionCode(); - printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode); - } - RpcEndExcept - - return ret; -} - int WxSendTextMsg(wstring wxid, wstring at_wxid, wstring msg) { - return innerWxSendTextMsg(wxid.c_str(), at_wxid.c_str(), msg.c_str()); + return RpcSendTextMsg(wxid.c_str(), at_wxid.c_str(), msg.c_str()); } -static int innerWxSendImageMsg(const wchar_t *wxid, const wchar_t *path) -{ - int ret = 0; - unsigned long ulCode = 0; - - RpcTryExcept { ret = client_SendImageMsg(wxid, path); } - RpcExcept(1) - { - ulCode = RpcExceptionCode(); - printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode); - } - RpcEndExcept - - return ret; -} - -int WxSendImageMsg(wstring wxid, wstring path) { return innerWxSendImageMsg(wxid.c_str(), path.c_str()); } +int WxSendImageMsg(wstring wxid, wstring path) { return RpcSendImageMsg(wxid.c_str(), path.c_str()); } static int getAddrHandle(DWORD *addr, HANDLE *handle) { From 48091b85268fe3bb2abc214ff4fe34cd69cc8183 Mon Sep 17 00:00:00 2001 From: Changhua Date: Sun, 7 Aug 2022 20:08:54 +0800 Subject: [PATCH 4/8] Fix WxMsgTypes --- App/App.cpp | 15 ++++++++------- Rpc/rpc.idl | 10 +++++++++- SDK/rpc_client.cpp | 21 +++++++++++++++++++++ SDK/rpc_client.h | 1 + SDK/sdk.cpp | 35 ++++++++++++++++------------------- SDK/util.cpp | 8 ++++---- SDK/util.h | 3 ++- Spy/receive_msg.cpp | 21 ++++++++++++++++++++- Spy/rpc_server.cpp | 34 +++++++++++++++++++++++++++++++--- 9 files changed, 112 insertions(+), 36 deletions(-) diff --git a/App/App.cpp b/App/App.cpp index 0008770..67fda28 100644 --- a/App/App.cpp +++ b/App/App.cpp @@ -39,19 +39,20 @@ int main() _wsetlocale(LC_ALL, L"chs"); // 这是个大坑,不设置中文直接不见了。。。 - // 获取消息类型 - const MsgTypesMap_t WxMsgTypes = WxGetMsgTypes(); - for (auto it = WxMsgTypes.begin(); it != WxMsgTypes.end(); ++it) { - wprintf(L"%d: %s\n", it->first, it->second.c_str()); - } - wprintf(L"WxInitSDK: "); status = WxInitSDK(); wcout << status << endl; wprintf(L"%d\n", status); if (status != 0) { return 0; - } + } + + // 获取消息类型 + wprintf(L"获取消息类型\n"); + const MsgTypesMap_t WxMsgTypes = WxGetMsgTypes(); + for (auto it = WxMsgTypes.begin(); it != WxMsgTypes.end(); ++it) { + wprintf(L"%d: %s\n", it->first, it->second.c_str()); + } wprintf(L"Message: 接收通知中......\n"); WxSetTextMsgCb(onTextMsg); diff --git a/Rpc/rpc.idl b/Rpc/rpc.idl index 34b56aa..2ec1d8d 100644 --- a/Rpc/rpc.idl +++ b/Rpc/rpc.idl @@ -17,11 +17,19 @@ interface ISpy BSTR wxId; // 发送人微信ID BSTR roomId; // 群ID BSTR content; // 消息内容,MAC版最大:16384,即16KB - } RpcMessage_t; + } RpcMessage_t; + + typedef struct RpcIntBstrPair { + int key; + BSTR value; + } RpcIntBstrPair_t; + typedef RpcIntBstrPair_t* PRpcIntBstrPair_t; + typedef RpcIntBstrPair_t** PPRpcIntBstrPair_t; int IsLogin(); 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 GetMsgTypes([ out ] int *pNum, [ out, size_is(, *pNum) ] PPRpcIntBstrPair_t *msgTypes); void EnableReceiveMsg(); [callback] int ReceiveMsg([ in ] RpcMessage_t rpcMsg); diff --git a/SDK/rpc_client.cpp b/SDK/rpc_client.cpp index ce2517b..c6d247d 100644 --- a/SDK/rpc_client.cpp +++ b/SDK/rpc_client.cpp @@ -113,6 +113,27 @@ int RpcSendImageMsg(const wchar_t *wxid, const wchar_t *path) return ret; } +PPRpcIntBstrPair_t RpcGetMsgTypes(int *pNum) +{ + int ret = 0; + unsigned long ulCode = 0; + PPRpcIntBstrPair_t ppRpcMsgTypes = NULL; + + RpcTryExcept{ ret = client_GetMsgTypes(pNum, &ppRpcMsgTypes); } + RpcExcept(1) + { + ulCode = RpcExceptionCode(); + printf("RpcGetMsgTypes exception 0x%lx = %ld\n", ulCode, ulCode); + } + RpcEndExcept; + if (ret != 0) { + printf("GetMsgTypes Failed: %d\n", ret); + return NULL; + } + + return ppRpcMsgTypes; +} + int server_ReceiveMsg(RpcMessage_t rpcMsg) { WxMessage_t msg; diff --git a/SDK/rpc_client.h b/SDK/rpc_client.h index f958d5f..5587f99 100644 --- a/SDK/rpc_client.h +++ b/SDK/rpc_client.h @@ -9,3 +9,4 @@ unsigned int __stdcall RpcSetTextMsgCb(void *p); int RpcIsLogin(); int RpcSendTextMsg(const wchar_t *wxid, const wchar_t *at_wxid, const wchar_t *msg); int RpcSendImageMsg(const wchar_t *wxid, const wchar_t *path); +RpcIntBstrPair_t** RpcGetMsgTypes(int *pNum); diff --git a/SDK/sdk.cpp b/SDK/sdk.cpp index 9428289..0af3228 100644 --- a/SDK/sdk.cpp +++ b/SDK/sdk.cpp @@ -13,24 +13,6 @@ #include "util.h" std::function g_cbReceiveTextMsg; -static const MsgTypesMap_t WxMsgTypes = MsgTypesMap_t { { 0x01, L"文字" }, - { 0x03, L"图片" }, - { 0x22, L"语音" }, - { 0x25, L"好友确认" }, - { 0x28, L"POSSIBLEFRIEND_MSG" }, - { 0x2A, L"名片" }, - { 0x2B, L"视频" }, - { 0x2F, L"石头剪刀布 | 表情图片" }, - { 0x30, L"位置" }, - { 0x31, L"共享实时位置、文件、转账、链接" }, - { 0x32, L"VOIPMSG" }, - { 0x33, L"微信初始化" }, - { 0x34, L"VOIPNOTIFY" }, - { 0x35, L"VOIPINVITE" }, - { 0x3E, L"小视频" }, - { 0x270F, L"SYSNOTICE" }, - { 0x2710, L"红包、系统消息" }, - { 0x2712, L"撤回消息" } }; int WxInitSDK() { @@ -187,4 +169,19 @@ ContactMap_t WxGetContacts() return mContact; } -MsgTypesMap_t WxGetMsgTypes() { return WxMsgTypes; } +MsgTypesMap_t WxGetMsgTypes() +{ + static MsgTypesMap_t WxMsgTypes; + if (WxMsgTypes.empty()) { + int size = 0; + PPRpcIntBstrPair_t pp = RpcGetMsgTypes(&size); + for (int i = 0; i < size; i++) { + WxMsgTypes.insert(make_pair(pp[i]->key, GetWstringFromBstr(pp[i]->value))); + midl_user_free(pp[i]); + } + midl_user_free(pp); + } + + return WxMsgTypes; +} + diff --git a/SDK/util.cpp b/SDK/util.cpp index 2445bb0..e153ea8 100644 --- a/SDK/util.cpp +++ b/SDK/util.cpp @@ -169,14 +169,14 @@ int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size) BSTR GetBstrByAddress(DWORD address) { return SysAllocStringLen(GET_WSTRING(address), GET_DWORD(address + 4)); } -static wstring GetWstringFromBstr(BSTR p) +wstring GetWstringFromBstr(BSTR p) { - wstring ret = L""; + wstring ws = L""; if (p != nullptr) { - ret = wstring(p); + ws = wstring(p); SysFreeString(p); } - return ret; + return ws; } void GetRpcMessage(WxMessage_t *wxMsg, RpcMessage_t rpcMsg) diff --git a/SDK/util.h b/SDK/util.h index c61a6b1..0579361 100644 --- a/SDK/util.h +++ b/SDK/util.h @@ -22,5 +22,6 @@ bool GetFileVersion(const wchar_t *filePath, wchar_t *version); 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 GetWstringFromBstr(BSTR p); std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address); diff --git a/Spy/receive_msg.cpp b/Spy/receive_msg.cpp index 714b09d..ac0f7af 100644 --- a/Spy/receive_msg.cpp +++ b/Spy/receive_msg.cpp @@ -1,4 +1,4 @@ -#include "framework.h" +#include "framework.h" #include "load_calls.h" #include "receive_msg.h" @@ -15,6 +15,25 @@ DWORD reg_buffer = 0; DWORD recvMsgCallAddr = 0; DWORD recvMsgJumpBackAddr = 0; RpcMessage_t lMsg = { 0 }; + +extern const MsgTypesMap_t g_WxMsgTypes = MsgTypesMap_t { { 0x01, L"文字" }, + { 0x03, L"图片" }, + { 0x22, L"语音" }, + { 0x25, L"好友确认" }, + { 0x28, L"POSSIBLEFRIEND_MSG" }, + { 0x2A, L"名片" }, + { 0x2B, L"视频" }, + { 0x2F, L"石头剪刀布 | 表情图片" }, + { 0x30, L"位置" }, + { 0x31, L"共享实时位置、文件、转账、链接" }, + { 0x32, L"VOIPMSG" }, + { 0x33, L"微信初始化" }, + { 0x34, L"VOIPNOTIFY" }, + { 0x35, L"VOIPINVITE" }, + { 0x3E, L"小视频" }, + { 0x270F, L"SYSNOTICE" }, + { 0x2710, L"红包、系统消息" }, + { 0x2712, L"撤回消息" } }; void DispatchMsg(DWORD reg) { diff --git a/Spy/rpc_server.cpp b/Spy/rpc_server.cpp index daeed03..9c340d8 100644 --- a/Spy/rpc_server.cpp +++ b/Spy/rpc_server.cpp @@ -4,13 +4,15 @@ #include "monitor.h" #include "rpc_server.h" #include "send_msg.h" -#include "spy_types.h" +#include "spy_types.h" +#include "sdk.h" -#include "../Rpc/rpc_h.h" -#pragma comment(lib, "Rpcrt4.lib") +#include "rpc_h.h" +#pragma comment(lib, "Rpcrt4.lib") extern HANDLE g_hEvent; extern MsgQueue_t g_MsgQueue; +extern const MsgTypesMap_t g_WxMsgTypes; int server_IsLogin() { return IsLogin(); } @@ -52,6 +54,32 @@ int server_SendImageMsg(const wchar_t *wxid, const wchar_t *path) return 0; } + +int server_GetMsgTypes(int *pNum, PPRpcIntBstrPair_t *msgTypes) +{ + *pNum = g_WxMsgTypes.size(); + PPRpcIntBstrPair_t pp = (PPRpcIntBstrPair_t)midl_user_allocate(*pNum * sizeof(RpcIntBstrPair_t)); + if (pp == NULL) { + printf("server_GetMsgTypes midl_user_allocate Failed for pp\n"); + return -2; + } + int index = 0; + for (auto it = g_WxMsgTypes.begin(); it != g_WxMsgTypes.end(); ++it) { + PRpcIntBstrPair_t p = (PRpcIntBstrPair_t)midl_user_allocate(sizeof(RpcIntBstrPair_t)); + if (p == NULL) { + printf("server_GetMsgTypes midl_user_allocate Failed for p\n"); + return -3; + } + + p->key = it->first; + p->value = SysAllocString(it->second.c_str()); + pp[index++] = p; + } + + *msgTypes = pp; + + return 0; +} RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE /*hInterface*/, void * /*pBindingHandle*/) { From 3042de5183bd4a7e73dbea11f239bcf1f02ae153 Mon Sep 17 00:00:00 2001 From: Changhua Date: Sun, 7 Aug 2022 20:50:49 +0800 Subject: [PATCH 5/8] Impl get contacts --- Rpc/rpc.idl | 19 ++++++++-- SDK/rpc_client.cpp | 35 ++++++++++++++---- SDK/rpc_client.h | 3 +- SDK/sdk.cpp | 82 +++++++++++++++++------------------------ SDK/util.cpp | 12 +++++- Spy/Spy.vcxproj | 2 + Spy/Spy.vcxproj.filters | 6 +++ Spy/get_contacts.cpp | 39 ++++++++++++++++++++ Spy/get_contacts.h | 7 ++++ Spy/rpc_server.cpp | 78 ++++++++++++++++++++++++++++----------- 10 files changed, 201 insertions(+), 82 deletions(-) create mode 100644 Spy/get_contacts.cpp create mode 100644 Spy/get_contacts.h diff --git a/Rpc/rpc.idl b/Rpc/rpc.idl index 2ec1d8d..3b55c2a 100644 --- a/Rpc/rpc.idl +++ b/Rpc/rpc.idl @@ -23,13 +23,26 @@ interface ISpy int key; BSTR value; } RpcIntBstrPair_t; - typedef RpcIntBstrPair_t* PRpcIntBstrPair_t; - typedef RpcIntBstrPair_t** PPRpcIntBstrPair_t; + typedef RpcIntBstrPair_t* PRpcIntBstrPair; + typedef RpcIntBstrPair_t** PPRpcIntBstrPair; + + typedef struct RpcContact { + BSTR wxId; + BSTR wxCode; + BSTR wxName; + BSTR wxCountry; + BSTR wxProvince; + BSTR wxCity; + BSTR wxGender; + } RpcContact_t; + typedef RpcContact_t *PRpcContact; + typedef RpcContact_t **PPRpcContact; int IsLogin(); 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 GetMsgTypes([ out ] int *pNum, [ out, size_is(, *pNum) ] PPRpcIntBstrPair_t *msgTypes); + int GetMsgTypes([ out ] int *pNum, [ out, size_is(, *pNum) ] PPRpcIntBstrPair *msgTypes); + int GetContacts([ out ] int *pNum, [ out, size_is(, *pNum) ] PPRpcContact *contacts); void EnableReceiveMsg(); [callback] int ReceiveMsg([ in ] RpcMessage_t rpcMsg); diff --git a/SDK/rpc_client.cpp b/SDK/rpc_client.cpp index c6d247d..06beb8f 100644 --- a/SDK/rpc_client.cpp +++ b/SDK/rpc_client.cpp @@ -1,6 +1,6 @@ -#include "sdk.h" +#include "rpc_client.h" +#include "sdk.h" #include "util.h" -#include "rpc_client.h" #pragma comment(lib, "Rpcrt4.lib") @@ -113,13 +113,13 @@ int RpcSendImageMsg(const wchar_t *wxid, const wchar_t *path) return ret; } -PPRpcIntBstrPair_t RpcGetMsgTypes(int *pNum) +PPRpcIntBstrPair RpcGetMsgTypes(int *pNum) { - int ret = 0; - unsigned long ulCode = 0; - PPRpcIntBstrPair_t ppRpcMsgTypes = NULL; + int ret = 0; + unsigned long ulCode = 0; + PPRpcIntBstrPair ppRpcMsgTypes = NULL; - RpcTryExcept{ ret = client_GetMsgTypes(pNum, &ppRpcMsgTypes); } + RpcTryExcept { ret = client_GetMsgTypes(pNum, &ppRpcMsgTypes); } RpcExcept(1) { ulCode = RpcExceptionCode(); @@ -134,6 +134,27 @@ PPRpcIntBstrPair_t RpcGetMsgTypes(int *pNum) return ppRpcMsgTypes; } +PPRpcContact RpcGetContacts(int *pNum) +{ + int ret = 0; + unsigned long ulCode = 0; + PPRpcContact ppRpcContacts = NULL; + + RpcTryExcept { ret = client_GetContacts(pNum, &ppRpcContacts); } + RpcExcept(1) + { + ulCode = RpcExceptionCode(); + printf("RpcGetContacts exception 0x%lx = %ld\n", ulCode, ulCode); + } + RpcEndExcept; + if (ret != 0) { + printf("GetContacts Failed: %d\n", ret); + return NULL; + } + + return ppRpcContacts; +} + int server_ReceiveMsg(RpcMessage_t rpcMsg) { WxMessage_t msg; diff --git a/SDK/rpc_client.h b/SDK/rpc_client.h index 5587f99..800d02c 100644 --- a/SDK/rpc_client.h +++ b/SDK/rpc_client.h @@ -9,4 +9,5 @@ unsigned int __stdcall RpcSetTextMsgCb(void *p); int RpcIsLogin(); int RpcSendTextMsg(const wchar_t *wxid, const wchar_t *at_wxid, const wchar_t *msg); int RpcSendImageMsg(const wchar_t *wxid, const wchar_t *path); -RpcIntBstrPair_t** RpcGetMsgTypes(int *pNum); +PPRpcIntBstrPair RpcGetMsgTypes(int *pNum); +PPRpcContact RpcGetContacts(int *pNum); diff --git a/SDK/sdk.cpp b/SDK/sdk.cpp index 0af3228..de7e39f 100644 --- a/SDK/sdk.cpp +++ b/SDK/sdk.cpp @@ -128,60 +128,46 @@ static int getAddrHandle(DWORD *addr, HANDLE *handle) return 0; } +MsgTypesMap_t WxGetMsgTypes() +{ + static MsgTypesMap_t WxMsgTypes; + if (WxMsgTypes.empty()) { + int size = 0; + PPRpcIntBstrPair pp = RpcGetMsgTypes(&size); + for (int i = 0; i < size; i++) { + WxMsgTypes.insert(make_pair(pp[i]->key, GetWstringFromBstr(pp[i]->value))); + midl_user_free(pp[i]); + } + if (pp) { + midl_user_free(pp); + } + } + + return WxMsgTypes; +} + ContactMap_t WxGetContacts() { ContactMap_t mContact; - DWORD moduleBaseAddress; - HANDLE hProcess; + int size = 0; + PPRpcContact pp = RpcGetContacts(&size); + for (int i = 0; i < size; i++) { + WxContact_t contact; + contact.wxId = GetWstringFromBstr(pp[i]->wxId); + contact.wxCode = GetWstringFromBstr(pp[i]->wxCode); + contact.wxName = GetWstringFromBstr(pp[i]->wxName); + contact.wxCountry = GetWstringFromBstr(pp[i]->wxCountry); + contact.wxProvince = GetWstringFromBstr(pp[i]->wxProvince); + contact.wxCity = GetWstringFromBstr(pp[i]->wxCity); + contact.wxGender = GetWstringFromBstr(pp[i]->wxGender); - if (getAddrHandle(&moduleBaseAddress, &hProcess) != 0) { - return mContact; - } - printf("WxGetContacts\n"); - DWORD baseAddr = moduleBaseAddress + 0x23638F4; - DWORD tempAddr = GetMemoryIntByAddress(hProcess, baseAddr); - DWORD head = GetMemoryIntByAddress(hProcess, tempAddr + 0x4C); - DWORD node = GetMemoryIntByAddress(hProcess, head); - - while (node != head) { - WxContact_t contactItem; - contactItem.wxId = GetUnicodeInfoByAddress(hProcess, node + 0x30); - contactItem.wxCode = GetUnicodeInfoByAddress(hProcess, node + 0x44); - contactItem.wxName = GetUnicodeInfoByAddress(hProcess, node + 0x8C); - contactItem.wxCountry = GetUnicodeInfoByAddress(hProcess, node + 0x1D0); - contactItem.wxProvince = GetUnicodeInfoByAddress(hProcess, node + 0x1E4); - contactItem.wxCity = GetUnicodeInfoByAddress(hProcess, node + 0x1F8); - DWORD gender = GetMemoryIntByAddress(hProcess, node + 0x184); - - if (gender == 1) - contactItem.wxGender = L"男"; - else if (gender == 2) - contactItem.wxGender = L"女"; - else - contactItem.wxGender = L"未知"; - - mContact.insert(make_pair(contactItem.wxId, contactItem)); - node = GetMemoryIntByAddress(hProcess, node); + mContact.insert(make_pair(contact.wxId, contact)); + midl_user_free(pp[i]); } - CloseHandle(hProcess); + if (pp) { + midl_user_free(pp); + } return mContact; } - -MsgTypesMap_t WxGetMsgTypes() -{ - static MsgTypesMap_t WxMsgTypes; - if (WxMsgTypes.empty()) { - int size = 0; - PPRpcIntBstrPair_t pp = RpcGetMsgTypes(&size); - for (int i = 0; i < size; i++) { - WxMsgTypes.insert(make_pair(pp[i]->key, GetWstringFromBstr(pp[i]->value))); - midl_user_free(pp[i]); - } - midl_user_free(pp); - } - - return WxMsgTypes; -} - diff --git a/SDK/util.cpp b/SDK/util.cpp index e153ea8..61100be 100644 --- a/SDK/util.cpp +++ b/SDK/util.cpp @@ -167,12 +167,20 @@ int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size) return strLength; } -BSTR GetBstrByAddress(DWORD address) { return SysAllocStringLen(GET_WSTRING(address), GET_DWORD(address + 4)); } +BSTR GetBstrByAddress(DWORD address) +{ + wchar_t *p = GET_WSTRING(address); + if (p == NULL) { + return NULL; + } + + return SysAllocStringLen(GET_WSTRING(address), GET_DWORD(address + 4)); +} wstring GetWstringFromBstr(BSTR p) { wstring ws = L""; - if (p != nullptr) { + if (p != NULL) { ws = wstring(p); SysFreeString(p); } diff --git a/Spy/Spy.vcxproj b/Spy/Spy.vcxproj index 28b3413..4ca44e3 100644 --- a/Spy/Spy.vcxproj +++ b/Spy/Spy.vcxproj @@ -166,6 +166,7 @@ + @@ -178,6 +179,7 @@ + diff --git a/Spy/Spy.vcxproj.filters b/Spy/Spy.vcxproj.filters index d756e4f..be1f776 100644 --- a/Spy/Spy.vcxproj.filters +++ b/Spy/Spy.vcxproj.filters @@ -45,6 +45,9 @@ 头文件 + + 头文件 + @@ -74,6 +77,9 @@ 源文件 + + 源文件 + diff --git a/Spy/get_contacts.cpp b/Spy/get_contacts.cpp new file mode 100644 index 0000000..5f43cc5 --- /dev/null +++ b/Spy/get_contacts.cpp @@ -0,0 +1,39 @@ +#include "get_contacts.h" +#include "load_calls.h" +#include "util.h" + +extern WxCalls_t g_WxCalls; +extern DWORD g_WeChatWinDllAddr; + +std::vector GetContacts() +{ + int gender = 0; + vector vContacts; + DWORD baseAddr = g_WeChatWinDllAddr + 0x23638F4; + DWORD tempAddr = GET_DWORD(baseAddr); + DWORD head = GET_DWORD(tempAddr + 0x4C); + DWORD node = GET_DWORD(head); + + while (node != head) { + RpcContact_t rpcContact = { 0 }; + rpcContact.wxId = GetBstrByAddress(node + 0x30); + rpcContact.wxCode = GetBstrByAddress(node + 0x44); + rpcContact.wxName = GetBstrByAddress(node + 0x8C); + rpcContact.wxCountry = GetBstrByAddress(node + 0x1D0); + rpcContact.wxProvince = GetBstrByAddress(node + 0x1E4); + rpcContact.wxCity = GetBstrByAddress(node + 0x1F8); + + gender = GET_DWORD(node + 0x184); + if (gender == 1) + rpcContact.wxGender = SysAllocString(L"男"); + else if (gender == 2) + rpcContact.wxGender = SysAllocString(L"女"); + else + rpcContact.wxGender = SysAllocString(L"未知"); + + vContacts.push_back(rpcContact); + node = GET_DWORD(node); + } + + return vContacts; +} diff --git a/Spy/get_contacts.h b/Spy/get_contacts.h new file mode 100644 index 0000000..5662225 --- /dev/null +++ b/Spy/get_contacts.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#include "rpc_h.h" + +std::vector GetContacts(); diff --git a/Spy/rpc_server.cpp b/Spy/rpc_server.cpp index 9c340d8..344b34d 100644 --- a/Spy/rpc_server.cpp +++ b/Spy/rpc_server.cpp @@ -1,18 +1,19 @@ -#include +#include #include +#include "get_contacts.h" #include "monitor.h" #include "rpc_server.h" -#include "send_msg.h" -#include "spy_types.h" #include "sdk.h" +#include "send_msg.h" +#include "spy_types.h" #include "rpc_h.h" -#pragma comment(lib, "Rpcrt4.lib") +#pragma comment(lib, "Rpcrt4.lib") extern HANDLE g_hEvent; extern MsgQueue_t g_MsgQueue; -extern const MsgTypesMap_t g_WxMsgTypes; +extern const MsgTypesMap_t g_WxMsgTypes; int server_IsLogin() { return IsLogin(); } @@ -54,32 +55,67 @@ int server_SendImageMsg(const wchar_t *wxid, const wchar_t *path) return 0; } - -int server_GetMsgTypes(int *pNum, PPRpcIntBstrPair_t *msgTypes) + +int server_GetMsgTypes(int *pNum, PPRpcIntBstrPair *msgTypes) { - *pNum = g_WxMsgTypes.size(); - PPRpcIntBstrPair_t pp = (PPRpcIntBstrPair_t)midl_user_allocate(*pNum * sizeof(RpcIntBstrPair_t)); + *pNum = g_WxMsgTypes.size(); + PPRpcIntBstrPair pp = (PPRpcIntBstrPair)midl_user_allocate(*pNum * sizeof(RpcIntBstrPair_t)); if (pp == NULL) { printf("server_GetMsgTypes midl_user_allocate Failed for pp\n"); return -2; - } - int index = 0; - for (auto it = g_WxMsgTypes.begin(); it != g_WxMsgTypes.end(); ++it) { - PRpcIntBstrPair_t p = (PRpcIntBstrPair_t)midl_user_allocate(sizeof(RpcIntBstrPair_t)); + } + int index = 0; + for (auto it = g_WxMsgTypes.begin(); it != g_WxMsgTypes.end(); it++) { + PRpcIntBstrPair p = (PRpcIntBstrPair)midl_user_allocate(sizeof(RpcIntBstrPair_t)); if (p == NULL) { printf("server_GetMsgTypes midl_user_allocate Failed for p\n"); return -3; - } + } - p->key = it->first; - p->value = SysAllocString(it->second.c_str()); + p->key = it->first; + p->value = SysAllocString(it->second.c_str()); pp[index++] = p; - } - - *msgTypes = pp; - + } + + *msgTypes = pp; + return 0; -} +} + +int server_GetContacts(int *pNum, PPRpcContact *contacts) +{ + std::vector vContacts = GetContacts(); + + *pNum = vContacts.size(); + PPRpcContact pp = (PPRpcContact)midl_user_allocate(*pNum * sizeof(RpcContact_t)); + if (pp == NULL) { + printf("server_GetMsgTypes midl_user_allocate Failed for pp\n"); + return -2; + } + + int index = 0; + for (auto it = vContacts.begin(); it != vContacts.end(); it++) { + PRpcContact p = (PRpcContact)midl_user_allocate(sizeof(RpcContact_t)); + if (p == NULL) { + printf("server_GetMsgTypes midl_user_allocate Failed for p\n"); + return -3; + } + + p->wxId = it->wxId; + p->wxCode = it->wxCode; + p->wxName = it->wxName; + p->wxCountry = it->wxCountry; + p->wxProvince = it->wxProvince; + p->wxCity = it->wxCity; + p->wxGender = it->wxGender; + + pp[index++] = p; + } + + *contacts = pp; + + return 0; +} RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE /*hInterface*/, void * /*pBindingHandle*/) { From 1da3e0d69f5270e65f06dafc8a83e6f2b3d3841d Mon Sep 17 00:00:00 2001 From: Changhua Date: Sun, 7 Aug 2022 21:08:27 +0800 Subject: [PATCH 6/8] Fix get contacts --- Spy/get_contacts.cpp | 18 +++++++++--------- Spy/load_calls.cpp | 21 +++++++++++---------- Spy/spy_types.h | 13 +++++++++++++ 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/Spy/get_contacts.cpp b/Spy/get_contacts.cpp index 5f43cc5..8282e2c 100644 --- a/Spy/get_contacts.cpp +++ b/Spy/get_contacts.cpp @@ -9,21 +9,21 @@ std::vector GetContacts() { int gender = 0; vector vContacts; - DWORD baseAddr = g_WeChatWinDllAddr + 0x23638F4; + DWORD baseAddr = g_WeChatWinDllAddr + g_WxCalls.contact.base; DWORD tempAddr = GET_DWORD(baseAddr); - DWORD head = GET_DWORD(tempAddr + 0x4C); + DWORD head = GET_DWORD(tempAddr + g_WxCalls.contact.head); DWORD node = GET_DWORD(head); while (node != head) { RpcContact_t rpcContact = { 0 }; - rpcContact.wxId = GetBstrByAddress(node + 0x30); - rpcContact.wxCode = GetBstrByAddress(node + 0x44); - rpcContact.wxName = GetBstrByAddress(node + 0x8C); - rpcContact.wxCountry = GetBstrByAddress(node + 0x1D0); - rpcContact.wxProvince = GetBstrByAddress(node + 0x1E4); - rpcContact.wxCity = GetBstrByAddress(node + 0x1F8); + rpcContact.wxId = GetBstrByAddress(node + g_WxCalls.contact.wxId); + rpcContact.wxCode = GetBstrByAddress(node + g_WxCalls.contact.wxCode); + rpcContact.wxName = GetBstrByAddress(node + g_WxCalls.contact.wxName); + rpcContact.wxCountry = GetBstrByAddress(node + g_WxCalls.contact.wxCountry); + rpcContact.wxProvince = GetBstrByAddress(node + g_WxCalls.contact.wxProvince); + rpcContact.wxCity = GetBstrByAddress(node + g_WxCalls.contact.wxCity); - gender = GET_DWORD(node + 0x184); + gender = GET_DWORD(node + g_WxCalls.contact.wxGender); if (gender == 1) rpcContact.wxGender = SysAllocString(L"男"); else if (gender == 2) diff --git a/Spy/load_calls.cpp b/Spy/load_calls.cpp index 18ee717..0145286 100644 --- a/Spy/load_calls.cpp +++ b/Spy/load_calls.cpp @@ -4,17 +4,18 @@ #include "load_calls.h" #define SUPPORT_VERSION L"3.7.0.29" -WxCalls_t wxCalls = { - 0x23631D0, // Login Status - { 0x236307C, 0x23630F4, 0x2363128 }, // User Info: wxid, nickname, mobile - 0x521D30, // Send Message - /* Receive Message: - Hook, call, type, self, id, msgXml, roomId, wxId, content */ - { 0x550F4C, 0xA94A50, 0x38, 0x3C, 0x184, 0x1EC, 0x48, 0x170, 0x70 }, - { 0xBD780, 0x770120, 0x521640 } // Send Image Message -}; +WxCalls_t wxCalls = { 0x23631D0, // Login Status + { 0x236307C, 0x23630F4, 0x2363128 }, // User Info: wxid, nickname, mobile + 0x521D30, // Send Message + /* Receive Message: + Hook, call, type, self, id, msgXml, roomId, wxId, content */ + { 0x550F4C, 0xA94A50, 0x38, 0x3C, 0x184, 0x1EC, 0x48, 0x170, 0x70 }, + { 0xBD780, 0x770120, 0x521640 }, // Send Image Message + /* Get Contacts: + Base, head, wxId, Code, Name, Gender, Country, Province, City*/ + { 0x23638F4, 0x4C, 0x30, 0x44, 0x8C, 0x184, 0x1D0, 0x1E4, 0x1F8 } }; -int LoadCalls(const wchar_t* version, WxCalls_t* calls) +int LoadCalls(const wchar_t *version, WxCalls_t *calls) { if (wcscmp(version, SUPPORT_VERSION) != 0) { return -1; diff --git a/Spy/spy_types.h b/Spy/spy_types.h index 6c98504..a565153 100644 --- a/Spy/spy_types.h +++ b/Spy/spy_types.h @@ -29,12 +29,25 @@ typedef struct SendImg { DWORD call3; } SendImg_t; +typedef struct Contact { + DWORD base; + DWORD head; + DWORD wxId; + DWORD wxCode; + DWORD wxName; + DWORD wxGender; + DWORD wxCountry; + DWORD wxProvince; + DWORD wxCity; +} Contact_t; + typedef struct WxCalls { DWORD login; // 登录状态 UserInfoCall_t ui; // 用户信息 DWORD sendTextMsg; // 发送消息 RecvMsg_t recvMsg; // 接收消息 SendImg_t sendImg; // 发送图片 + Contact_t contact; // 获取联系人 } WxCalls_t; typedef struct TextStruct { From b16957ede43eef3aeeaea450608ef262daa0ce56 Mon Sep 17 00:00:00 2001 From: Changhua Date: Sun, 7 Aug 2022 21:17:04 +0800 Subject: [PATCH 7/8] Refine RPC --- SDK/SDK.vcxproj | 1 + SDK/rpc_client.cpp | 4 +--- Spy/Spy.vcxproj | 1 + Spy/rpc_server.cpp | 8 +++----- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/SDK/SDK.vcxproj b/SDK/SDK.vcxproj index 2f481de..cafe36f 100644 --- a/SDK/SDK.vcxproj +++ b/SDK/SDK.vcxproj @@ -119,6 +119,7 @@ true false sdk.def + Rpcrt4.lib;%(AdditionalDependencies) diff --git a/SDK/rpc_client.cpp b/SDK/rpc_client.cpp index 06beb8f..269e656 100644 --- a/SDK/rpc_client.cpp +++ b/SDK/rpc_client.cpp @@ -2,8 +2,6 @@ #include "sdk.h" #include "util.h" -#pragma comment(lib, "Rpcrt4.lib") - static RPC_WSTR pszStringBinding = NULL; extern std::function g_cbReceiveTextMsg; @@ -14,7 +12,7 @@ RPC_STATUS RpcConnectServer() status = RpcStringBindingCompose(NULL, // UUID to bind to reinterpret_cast((RPC_WSTR)L"ncalrpc"), // Use TCP/IP protocol NULL, // TCP/IP network address to use - reinterpret_cast((RPC_WSTR)L"tmp_endpoint"), // TCP/IP port to use + reinterpret_cast((RPC_WSTR)L"wcferry"), // TCP/IP port to use NULL, // Protocol dependent network options to use &pszStringBinding); // String binding output diff --git a/Spy/Spy.vcxproj b/Spy/Spy.vcxproj index 4ca44e3..8eae960 100644 --- a/Spy/Spy.vcxproj +++ b/Spy/Spy.vcxproj @@ -122,6 +122,7 @@ true true false + Rpcrt4.lib;%(AdditionalDependencies) /prefix client "client_" server "server_" diff --git a/Spy/rpc_server.cpp b/Spy/rpc_server.cpp index 344b34d..972d8d3 100644 --- a/Spy/rpc_server.cpp +++ b/Spy/rpc_server.cpp @@ -3,14 +3,12 @@ #include "get_contacts.h" #include "monitor.h" +#include "rpc_h.h" #include "rpc_server.h" #include "sdk.h" #include "send_msg.h" #include "spy_types.h" -#include "rpc_h.h" -#pragma comment(lib, "Rpcrt4.lib") - extern HANDLE g_hEvent; extern MsgQueue_t g_MsgQueue; extern const MsgTypesMap_t g_WxMsgTypes; @@ -129,8 +127,8 @@ int RpcStartServer(HMODULE hModule) // remote procedure calls. status = RpcServerUseProtseqEp(reinterpret_cast((RPC_WSTR)L"ncalrpc"), // Use TCP/IP protocol RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Backlog queue length for TCP/IP. - reinterpret_cast((RPC_WSTR)L"tmp_endpoint"), // TCP/IP port to use - NULL // No security + reinterpret_cast((RPC_WSTR)L"wcferry"), // TCP/IP port to use + NULL // No security ); if (status) From a3500cdd15521ba7bf28dd238d416b599c2bd9db Mon Sep 17 00:00:00 2001 From: Changhua Date: Sun, 7 Aug 2022 21:29:08 +0800 Subject: [PATCH 8/8] Sleep 1s --- App/App.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/App/App.cpp b/App/App.cpp index 67fda28..ce5c043 100644 --- a/App/App.cpp +++ b/App/App.cpp @@ -56,16 +56,17 @@ int main() wprintf(L"Message: 接收通知中......\n"); WxSetTextMsgCb(onTextMsg); + Sleep(1000); // 等待1秒 // 测试发送消息 wprintf(L"测试发送消息\n"); WxSendTextMsg(wxid, at_wxid, content); + Sleep(1000); // 等待1秒 // 测试发送照片 wprintf(L"测试发送照片\n"); WxSendImageMsg(wxid, img_path); - - Sleep(10000); // 等待10秒 + Sleep(1000); // 等待1秒 // 测试获取联系人 auto mContact = WxGetContacts();