Merge branch 'feat_rpc'
This commit is contained in:
commit
da5eae278c
18
App/App.cpp
18
App/App.cpp
@ -39,12 +39,6 @@ int main()
|
|||||||
|
|
||||||
_wsetlocale(LC_ALL, L"chs"); // 这是个大坑,不设置中文直接不见了。。。
|
_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: ");
|
wprintf(L"WxInitSDK: ");
|
||||||
status = WxInitSDK();
|
status = WxInitSDK();
|
||||||
wcout << status << endl;
|
wcout << status << endl;
|
||||||
@ -53,18 +47,26 @@ int main()
|
|||||||
return 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");
|
wprintf(L"Message: 接收通知中......\n");
|
||||||
WxSetTextMsgCb(onTextMsg);
|
WxSetTextMsgCb(onTextMsg);
|
||||||
|
Sleep(1000); // 等待1秒
|
||||||
|
|
||||||
// 测试发送消息
|
// 测试发送消息
|
||||||
wprintf(L"测试发送消息\n");
|
wprintf(L"测试发送消息\n");
|
||||||
WxSendTextMsg(wxid, at_wxid, content);
|
WxSendTextMsg(wxid, at_wxid, content);
|
||||||
|
Sleep(1000); // 等待1秒
|
||||||
|
|
||||||
// 测试发送照片
|
// 测试发送照片
|
||||||
wprintf(L"测试发送照片\n");
|
wprintf(L"测试发送照片\n");
|
||||||
WxSendImageMsg(wxid, img_path);
|
WxSendImageMsg(wxid, img_path);
|
||||||
|
Sleep(1000); // 等待1秒
|
||||||
Sleep(10000); // 等待10秒
|
|
||||||
|
|
||||||
// 测试获取联系人
|
// 测试获取联系人
|
||||||
auto mContact = WxGetContacts();
|
auto mContact = WxGetContacts();
|
||||||
|
38
Rpc/rpc.idl
38
Rpc/rpc.idl
@ -1,4 +1,4 @@
|
|||||||
[
|
[
|
||||||
uuid(ed838ecd-8a1e-4da7-bfda-9f2d12d07893),
|
uuid(ed838ecd-8a1e-4da7-bfda-9f2d12d07893),
|
||||||
version(1.0),
|
version(1.0),
|
||||||
implicit_handle(handle_t hSpyBinding),
|
implicit_handle(handle_t hSpyBinding),
|
||||||
@ -6,12 +6,44 @@
|
|||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
typedef struct RpcIntBstrPair {
|
||||||
|
int key;
|
||||||
|
BSTR value;
|
||||||
|
} RpcIntBstrPair_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 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);
|
||||||
|
int GetMsgTypes([ out ] int *pNum, [ out, size_is(, *pNum) ] PPRpcIntBstrPair *msgTypes);
|
||||||
|
int GetContacts([ out ] int *pNum, [ out, size_is(, *pNum) ] PPRpcContact *contacts);
|
||||||
|
|
||||||
void EnableReceiveMsg();
|
void EnableReceiveMsg();
|
||||||
[callback] int ReceiveMsg([ in ] RpcMessage_t *msg);
|
[callback] int ReceiveMsg([ in ] RpcMessage_t rpcMsg);
|
||||||
};
|
};
|
||||||
|
@ -1,18 +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
|
|
||||||
|
|
||||||
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;
|
|
@ -119,6 +119,7 @@
|
|||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableUAC>false</EnableUAC>
|
<EnableUAC>false</EnableUAC>
|
||||||
<ModuleDefinitionFile>sdk.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>sdk.def</ModuleDefinitionFile>
|
||||||
|
<AdditionalDependencies>Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -161,6 +162,7 @@
|
|||||||
<ClInclude Include="..\Rpc\rpc_h.h" />
|
<ClInclude Include="..\Rpc\rpc_h.h" />
|
||||||
<ClInclude Include="framework.h" />
|
<ClInclude Include="framework.h" />
|
||||||
<ClInclude Include="injector.h" />
|
<ClInclude Include="injector.h" />
|
||||||
|
<ClInclude Include="rpc_client.h" />
|
||||||
<ClInclude Include="sdk.h" />
|
<ClInclude Include="sdk.h" />
|
||||||
<ClInclude Include="util.h" />
|
<ClInclude Include="util.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@ -169,6 +171,7 @@
|
|||||||
<ClCompile Include="..\Rpc\rpc_memory.cpp" />
|
<ClCompile Include="..\Rpc\rpc_memory.cpp" />
|
||||||
<ClCompile Include="dllmain.cpp" />
|
<ClCompile Include="dllmain.cpp" />
|
||||||
<ClCompile Include="injector.cpp" />
|
<ClCompile Include="injector.cpp" />
|
||||||
|
<ClCompile Include="rpc_client.cpp" />
|
||||||
<ClCompile Include="sdk.cpp" />
|
<ClCompile Include="sdk.cpp" />
|
||||||
<ClCompile Include="util.cpp" />
|
<ClCompile Include="util.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -30,6 +30,9 @@
|
|||||||
<ClInclude Include="injector.h">
|
<ClInclude Include="injector.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="rpc_client.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="dllmain.cpp">
|
<ClCompile Include="dllmain.cpp">
|
||||||
@ -50,6 +53,9 @@
|
|||||||
<ClCompile Include="injector.cpp">
|
<ClCompile Include="injector.cpp">
|
||||||
<Filter>源文件</Filter>
|
<Filter>源文件</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="rpc_client.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="sdk.def">
|
<None Include="sdk.def">
|
||||||
|
167
SDK/rpc_client.cpp
Normal file
167
SDK/rpc_client.cpp
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
#include "rpc_client.h"
|
||||||
|
#include "sdk.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
static RPC_WSTR pszStringBinding = NULL;
|
||||||
|
extern std::function<int(WxMessage_t)> 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>((RPC_WSTR)L"ncalrpc"), // Use TCP/IP protocol
|
||||||
|
NULL, // TCP/IP network address to use
|
||||||
|
reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"wcferry"), // 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
PPRpcIntBstrPair RpcGetMsgTypes(int *pNum)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
unsigned long ulCode = 0;
|
||||||
|
PPRpcIntBstrPair 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
GetRpcMessage(&msg, rpcMsg);
|
||||||
|
try {
|
||||||
|
g_cbReceiveTextMsg(msg); // 调用接收消息回调
|
||||||
|
} catch (...) {
|
||||||
|
printf("callback error...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
13
SDK/rpc_client.h
Normal file
13
SDK/rpc_client.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#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);
|
||||||
|
PPRpcIntBstrPair RpcGetMsgTypes(int *pNum);
|
||||||
|
PPRpcContact RpcGetContacts(int *pNum);
|
258
SDK/sdk.cpp
258
SDK/sdk.cpp
@ -7,87 +7,25 @@
|
|||||||
#include <tlhelp32.h>
|
#include <tlhelp32.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../Rpc/rpc_h.h"
|
|
||||||
#pragma comment(lib, "Rpcrt4.lib")
|
|
||||||
|
|
||||||
#include "injector.h"
|
#include "injector.h"
|
||||||
#include "rpc_types.h"
|
#include "rpc_client.h"
|
||||||
#include "sdk.h"
|
#include "sdk.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
static HANDLE hEvent;
|
std::function<int(WxMessage_t)> g_cbReceiveTextMsg;
|
||||||
static std::queue<RpcMessage_t> MsgQueue;
|
|
||||||
static RPC_WSTR pszStringBinding = NULL;
|
|
||||||
static std::function<int(WxMessage_t)> 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"撤回消息" } };
|
|
||||||
|
|
||||||
RPC_STATUS RpcConnectServer()
|
|
||||||
{
|
|
||||||
RPC_STATUS status = 0;
|
|
||||||
// Creates a string binding handle.
|
|
||||||
status = RpcStringBindingCompose(NULL, // UUID to bind to
|
|
||||||
reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"ncalrpc"), // Use TCP/IP protocol
|
|
||||||
NULL, // TCP/IP network address to use
|
|
||||||
reinterpret_cast<RPC_WSTR>((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 WxInitSDK()
|
||||||
{
|
{
|
||||||
int loginFlag = 0;
|
|
||||||
unsigned long ulCode = 0;
|
unsigned long ulCode = 0;
|
||||||
DWORD status = 0;
|
DWORD status = 0;
|
||||||
DWORD pid = 0;
|
DWORD pid = 0;
|
||||||
WCHAR DllPath[MAX_PATH] = { 0 };
|
WCHAR DllPath[MAX_PATH] = { 0 };
|
||||||
|
|
||||||
GetModuleFileNameW(GetModuleHandleW(WECHATSDKDLL), DllPath, MAX_PATH);
|
GetModuleFileName(GetModuleHandle(WECHATSDKDLL), DllPath, MAX_PATH);
|
||||||
PathRemoveFileSpecW(DllPath);
|
PathRemoveFileSpec(DllPath);
|
||||||
PathAppendW(DllPath, WECHATINJECTDLL);
|
PathAppend(DllPath, WECHATINJECTDLL);
|
||||||
|
|
||||||
if (!PathFileExistsW(DllPath)) {
|
if (!PathFileExists(DllPath)) {
|
||||||
return ERROR_FILE_NOT_FOUND;
|
return ERROR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,88 +40,20 @@ int WxInitSDK()
|
|||||||
|
|
||||||
RpcConnectServer();
|
RpcConnectServer();
|
||||||
|
|
||||||
while (!loginFlag) {
|
while (!RpcIsLogin()) {
|
||||||
RpcTryExcept
|
|
||||||
{
|
|
||||||
// 查询登录状态
|
|
||||||
loginFlag = client_IsLogin();
|
|
||||||
}
|
|
||||||
RpcExcept(1)
|
|
||||||
{
|
|
||||||
ulCode = RpcExceptionCode();
|
|
||||||
printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
|
|
||||||
}
|
|
||||||
RpcEndExcept
|
|
||||||
|
|
||||||
Sleep(1000);
|
Sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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<int(WxMessage_t)> &onMsg)
|
int WxSetTextMsgCb(const std::function<int(WxMessage_t)> &onMsg)
|
||||||
{
|
{
|
||||||
if (onMsg) {
|
if (onMsg) {
|
||||||
HANDLE msgThread;
|
HANDLE msgThread;
|
||||||
cbReceiveTextMsg = onMsg;
|
g_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, RpcSetTextMsgCb, NULL, 0, NULL);
|
||||||
if (msgThread == NULL) {
|
if (msgThread == NULL) {
|
||||||
printf("Failed to create innerWxRecvTextMsg.\n");
|
printf("Failed to create innerWxRecvTextMsg.\n");
|
||||||
return -2;
|
return -2;
|
||||||
@ -197,51 +67,12 @@ int WxSetTextMsgCb(const std::function<int(WxMessage_t)> &onMsg)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int server_ReceiveMsg(RpcMessage_t *rpcMsg)
|
|
||||||
{
|
|
||||||
MsgQueue.push(*rpcMsg); // 发送消息
|
|
||||||
SetEvent(hEvent); // 发送消息通知
|
|
||||||
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)
|
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 WxSendImageMsg(wstring wxid, wstring path) { return RpcSendImageMsg(wxid.c_str(), path.c_str()); }
|
||||||
{
|
|
||||||
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()); }
|
|
||||||
|
|
||||||
static int getAddrHandle(DWORD *addr, HANDLE *handle)
|
static int getAddrHandle(DWORD *addr, HANDLE *handle)
|
||||||
{
|
{
|
||||||
@ -297,45 +128,46 @@ static int getAddrHandle(DWORD *addr, HANDLE *handle)
|
|||||||
return 0;
|
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 WxGetContacts()
|
||||||
{
|
{
|
||||||
ContactMap_t mContact;
|
ContactMap_t mContact;
|
||||||
DWORD moduleBaseAddress;
|
int size = 0;
|
||||||
HANDLE hProcess;
|
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) {
|
mContact.insert(make_pair(contact.wxId, contact));
|
||||||
return mContact;
|
midl_user_free(pp[i]);
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(hProcess);
|
if (pp) {
|
||||||
|
midl_user_free(pp);
|
||||||
|
}
|
||||||
|
|
||||||
return mContact;
|
return mContact;
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgTypesMap_t WxGetMsgTypes() { return WxMsgTypes; }
|
|
||||||
|
41
SDK/util.cpp
41
SDK/util.cpp
@ -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,38 @@ int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size)
|
|||||||
return strLength;
|
return strLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 != NULL) {
|
||||||
|
ws = wstring(p);
|
||||||
|
SysFreeString(p);
|
||||||
|
}
|
||||||
|
return ws;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
#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"
|
||||||
#define WECHATSDKDLL L"SDK.dll"
|
#define WECHATSDKDLL L"SDK.dll"
|
||||||
@ -17,5 +20,8 @@ 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 GetWstringFromBstr(BSTR p);
|
||||||
std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address);
|
std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address);
|
||||||
|
@ -122,6 +122,7 @@
|
|||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableUAC>false</EnableUAC>
|
<EnableUAC>false</EnableUAC>
|
||||||
|
<AdditionalDependencies>Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<Midl>
|
<Midl>
|
||||||
<AdditionalOptions>/prefix client "client_" server "server_" </AdditionalOptions>
|
<AdditionalOptions>/prefix client "client_" server "server_" </AdditionalOptions>
|
||||||
@ -163,10 +164,10 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\Rpc\rpc_types.h" />
|
|
||||||
<ClInclude Include="..\Rpc\rpc_h.h" />
|
<ClInclude Include="..\Rpc\rpc_h.h" />
|
||||||
<ClInclude Include="..\SDK\util.h" />
|
<ClInclude Include="..\SDK\util.h" />
|
||||||
<ClInclude Include="framework.h" />
|
<ClInclude Include="framework.h" />
|
||||||
|
<ClInclude Include="get_contacts.h" />
|
||||||
<ClInclude Include="load_calls.h" />
|
<ClInclude Include="load_calls.h" />
|
||||||
<ClInclude Include="monitor.h" />
|
<ClInclude Include="monitor.h" />
|
||||||
<ClInclude Include="receive_msg.h" />
|
<ClInclude Include="receive_msg.h" />
|
||||||
@ -179,6 +180,7 @@
|
|||||||
<ClCompile Include="..\Rpc\rpc_s.c" />
|
<ClCompile Include="..\Rpc\rpc_s.c" />
|
||||||
<ClCompile Include="..\SDK\util.cpp" />
|
<ClCompile Include="..\SDK\util.cpp" />
|
||||||
<ClCompile Include="dllmain.cpp" />
|
<ClCompile Include="dllmain.cpp" />
|
||||||
|
<ClCompile Include="get_contacts.cpp" />
|
||||||
<ClCompile Include="load_calls.cpp" />
|
<ClCompile Include="load_calls.cpp" />
|
||||||
<ClCompile Include="monitor.cpp" />
|
<ClCompile Include="monitor.cpp" />
|
||||||
<ClCompile Include="receive_msg.cpp" />
|
<ClCompile Include="receive_msg.cpp" />
|
||||||
|
@ -27,9 +27,6 @@
|
|||||||
<ClInclude Include="monitor.h">
|
<ClInclude Include="monitor.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\Rpc\rpc_types.h">
|
|
||||||
<Filter>Rpc</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="rpc_server.h">
|
<ClInclude Include="rpc_server.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -48,6 +45,9 @@
|
|||||||
<ClInclude Include="spy_types.h">
|
<ClInclude Include="spy_types.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="get_contacts.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="dllmain.cpp">
|
<ClCompile Include="dllmain.cpp">
|
||||||
@ -77,6 +77,9 @@
|
|||||||
<ClCompile Include="send_msg.cpp">
|
<ClCompile Include="send_msg.cpp">
|
||||||
<Filter>源文件</Filter>
|
<Filter>源文件</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="get_contacts.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Midl Include="..\Rpc\rpc.idl">
|
<Midl Include="..\Rpc\rpc.idl">
|
||||||
|
39
Spy/get_contacts.cpp
Normal file
39
Spy/get_contacts.cpp
Normal file
@ -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<RpcContact_t> GetContacts()
|
||||||
|
{
|
||||||
|
int gender = 0;
|
||||||
|
vector<RpcContact_t> vContacts;
|
||||||
|
DWORD baseAddr = g_WeChatWinDllAddr + g_WxCalls.contact.base;
|
||||||
|
DWORD tempAddr = GET_DWORD(baseAddr);
|
||||||
|
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 + 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 + g_WxCalls.contact.wxGender);
|
||||||
|
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;
|
||||||
|
}
|
7
Spy/get_contacts.h
Normal file
7
Spy/get_contacts.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "rpc_h.h"
|
||||||
|
|
||||||
|
std::vector<RpcContact_t> GetContacts();
|
@ -4,15 +4,16 @@
|
|||||||
#include "load_calls.h"
|
#include "load_calls.h"
|
||||||
|
|
||||||
#define SUPPORT_VERSION L"3.7.0.29"
|
#define SUPPORT_VERSION L"3.7.0.29"
|
||||||
WxCalls_t wxCalls = {
|
WxCalls_t wxCalls = { 0x23631D0, // Login Status
|
||||||
0x23631D0, // Login Status
|
|
||||||
{ 0x236307C, 0x23630F4, 0x2363128 }, // User Info: wxid, nickname, mobile
|
{ 0x236307C, 0x23630F4, 0x2363128 }, // User Info: wxid, nickname, mobile
|
||||||
0x521D30, // Send Message
|
0x521D30, // Send Message
|
||||||
/* Receive Message:
|
/* Receive Message:
|
||||||
Hook, call, type, self, id, msgXml, roomId, wxId, content */
|
Hook, call, type, self, id, msgXml, roomId, wxId, content */
|
||||||
{ 0x550F4C, 0xA94A50, 0x38, 0x3C, 0x184, 0x1EC, 0x48, 0x170, 0x70 },
|
{ 0x550F4C, 0xA94A50, 0x38, 0x3C, 0x184, 0x1EC, 0x48, 0x170, 0x70 },
|
||||||
{ 0xBD780, 0x770120, 0x521640 } // Send Image Message
|
{ 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)
|
||||||
{
|
{
|
||||||
|
@ -14,30 +14,50 @@ 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 };
|
||||||
|
|
||||||
|
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)
|
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 +83,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;
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "get_contacts.h"
|
||||||
#include "monitor.h"
|
#include "monitor.h"
|
||||||
|
#include "rpc_h.h"
|
||||||
#include "rpc_server.h"
|
#include "rpc_server.h"
|
||||||
|
#include "sdk.h"
|
||||||
#include "send_msg.h"
|
#include "send_msg.h"
|
||||||
#include "spy_types.h"
|
#include "spy_types.h"
|
||||||
|
|
||||||
#include "../Rpc/rpc_h.h"
|
|
||||||
#pragma comment(lib, "Rpcrt4.lib")
|
|
||||||
|
|
||||||
extern HANDLE g_hEvent;
|
extern HANDLE g_hEvent;
|
||||||
extern MsgQueue_t g_MsgQueue;
|
extern MsgQueue_t g_MsgQueue;
|
||||||
|
extern const MsgTypesMap_t g_WxMsgTypes;
|
||||||
|
|
||||||
int server_IsLogin() { return IsLogin(); }
|
int server_IsLogin() { return IsLogin(); }
|
||||||
|
|
||||||
@ -25,7 +26,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 +35,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
|
||||||
}
|
}
|
||||||
@ -53,6 +54,67 @@ int server_SendImageMsg(const wchar_t *wxid, const wchar_t *path)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int server_GetMsgTypes(int *pNum, PPRpcIntBstrPair *msgTypes)
|
||||||
|
{
|
||||||
|
*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 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());
|
||||||
|
pp[index++] = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
*msgTypes = pp;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int server_GetContacts(int *pNum, PPRpcContact *contacts)
|
||||||
|
{
|
||||||
|
std::vector<RpcContact_t> 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*/)
|
RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE /*hInterface*/, void * /*pBindingHandle*/)
|
||||||
{
|
{
|
||||||
return RPC_S_OK; // Always allow anyone.
|
return RPC_S_OK; // Always allow anyone.
|
||||||
@ -65,7 +127,7 @@ int RpcStartServer(HMODULE hModule)
|
|||||||
// remote procedure calls.
|
// remote procedure calls.
|
||||||
status = RpcServerUseProtseqEp(reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"ncalrpc"), // Use TCP/IP protocol
|
status = RpcServerUseProtseqEp(reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"ncalrpc"), // Use TCP/IP protocol
|
||||||
RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Backlog queue length for TCP/IP.
|
RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Backlog queue length for TCP/IP.
|
||||||
reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"tmp_endpoint"), // TCP/IP port to use
|
reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"wcferry"), // TCP/IP port to use
|
||||||
NULL // No security
|
NULL // No security
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
@ -29,12 +29,25 @@ typedef struct SendImg {
|
|||||||
DWORD call3;
|
DWORD call3;
|
||||||
} SendImg_t;
|
} 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 {
|
typedef struct WxCalls {
|
||||||
DWORD login; // 登录状态
|
DWORD login; // 登录状态
|
||||||
UserInfoCall_t ui; // 用户信息
|
UserInfoCall_t ui; // 用户信息
|
||||||
DWORD sendTextMsg; // 发送消息
|
DWORD sendTextMsg; // 发送消息
|
||||||
RecvMsg_t recvMsg; // 接收消息
|
RecvMsg_t recvMsg; // 接收消息
|
||||||
SendImg_t sendImg; // 发送图片
|
SendImg_t sendImg; // 发送图片
|
||||||
|
Contact_t contact; // 获取联系人
|
||||||
} WxCalls_t;
|
} WxCalls_t;
|
||||||
|
|
||||||
typedef struct TextStruct {
|
typedef struct TextStruct {
|
||||||
|
Loading…
Reference in New Issue
Block a user