Bump gRPC
This commit is contained in:
+24
-15
@@ -21,8 +21,8 @@
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{707f2dcd-1001-42a7-b20e-b85b1bbab228}</ProjectGuid>
|
||||
<RootNamespace>SDK</RootNamespace>
|
||||
<ProjectGuid>{abfcb647-137f-478b-a73e-f0b1e3adc215}</ProjectGuid>
|
||||
<RootNamespace>sdk</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
@@ -82,16 +82,18 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<VcpkgUseStatic>true</VcpkgUseStatic>
|
||||
<VcpkgTriplet>x86-windows-static</VcpkgTriplet>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;SDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalOptions> /utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Rpc</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -109,8 +111,11 @@
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;SDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Rpc</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeaderFile>
|
||||
</PrecompiledHeaderFile>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)spy;C:\Tools\vcpkg\installed\x86-windows-static\include</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -119,8 +124,15 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<ModuleDefinitionFile>sdk.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>xcopy /y $(OutDir)sdk.dll $(SolutionDir)python
|
||||
xcopy /y $(SolutionDir)TEQuant.jpeg $(SolutionDir)python
|
||||
xcopy /y $(SolutionDir)TEQuant.jpeg $(SolutionDir)Release</Command>
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Message>Copy files</Message>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
@@ -159,21 +171,18 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Rpc\rpc_h.h" />
|
||||
<ClInclude Include="..\spy\log.h" />
|
||||
<ClInclude Include="..\spy\util.h" />
|
||||
<ClInclude Include="framework.h" />
|
||||
<ClInclude Include="injector.h" />
|
||||
<ClInclude Include="rpc_client.h" />
|
||||
<ClInclude Include="sdk.h" />
|
||||
<ClInclude Include="util.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\Rpc\rpc_c.c" />
|
||||
<ClCompile Include="..\Rpc\rpc_memory.cpp" />
|
||||
<ClCompile Include="..\spy\log.cpp" />
|
||||
<ClCompile Include="..\spy\util.cpp" />
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="injector.cpp" />
|
||||
<ClCompile Include="rpc_client.cpp" />
|
||||
<ClCompile Include="sdk.cpp" />
|
||||
<ClCompile Include="util.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="sdk.def" />
|
||||
|
||||
+8
-17
@@ -21,41 +21,32 @@
|
||||
<ClInclude Include="sdk.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Rpc\rpc_h.h">
|
||||
<ClInclude Include="..\spy\util.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util.h">
|
||||
<ClInclude Include="..\spy\log.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="injector.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpc_client.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\spy\log.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\spy\util.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sdk.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Rpc\rpc_c.c">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Rpc\rpc_memory.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="util.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="injector.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpc_client.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="sdk.def">
|
||||
|
||||
+13
-13
@@ -1,19 +1,19 @@
|
||||
// dllmain.cpp : 定义 DLL 应用程序的入口点。
|
||||
#include "framework.h"
|
||||
#include "framework.h"
|
||||
|
||||
#include "sdk.h"
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
case DLL_PROCESS_DETACH: {
|
||||
WxDestroySDK(); // 默认退出时清理 SDK
|
||||
break;
|
||||
}
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容
|
||||
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容
|
||||
// Windows 头文件
|
||||
#include <windows.h>
|
||||
|
||||
+70
-50
@@ -1,70 +1,90 @@
|
||||
#include "injector.h"
|
||||
|
||||
int InjectDll(DWORD pid, const WCHAR *dllPath)
|
||||
HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase)
|
||||
{
|
||||
HANDLE hThread;
|
||||
DWORD dwWriteSize = 0;
|
||||
// 1. 获取目标进程,并在目标进程的内存里开辟空间
|
||||
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
||||
LPVOID pRemoteAddress = VirtualAllocEx(hProcess, NULL, 1, MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
// 2. 把 dll 的路径写入到目标进程的内存空间中
|
||||
if (pRemoteAddress) {
|
||||
WriteProcessMemory(hProcess, pRemoteAddress, dllPath, wcslen(dllPath) * 2 + 2, &dwWriteSize);
|
||||
} else {
|
||||
MessageBox(NULL, L"DLL 路径写入失败", L"InjectDll", 0);
|
||||
return -1;
|
||||
SIZE_T cszDLL = (wcslen(dllPath) + 1) * sizeof(WCHAR);
|
||||
// 1. 打开目标进程
|
||||
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
||||
if (hProcess == NULL) {
|
||||
MessageBox(NULL, L"打开进程失败", L"InjectDll", 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 2. 在目标进程的内存里开辟空间
|
||||
LPVOID pRemoteAddress = VirtualAllocEx(hProcess, NULL, cszDLL, MEM_COMMIT, PAGE_READWRITE);
|
||||
if (pRemoteAddress == NULL) {
|
||||
MessageBox(NULL, L"DLL 路径写入失败", L"InjectDll", 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 3. 把 dll 的路径写入到目标进程的内存空间中
|
||||
WriteProcessMemory(hProcess, pRemoteAddress, dllPath, cszDLL, NULL);
|
||||
|
||||
// 3. 创建一个远程线程,让目标进程调用 LoadLibrary
|
||||
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibrary, pRemoteAddress, NULL, NULL);
|
||||
if (hThread) {
|
||||
WaitForSingleObject(hThread, -1);
|
||||
} else {
|
||||
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibrary, pRemoteAddress, 0, NULL);
|
||||
if (hThread == NULL) {
|
||||
MessageBox(NULL, L"LoadLibrary 调用失败", L"InjectDll", 0);
|
||||
return -2;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WaitForSingleObject(hThread, -1);
|
||||
GetExitCodeThread(hThread, (LPDWORD)injectedBase);
|
||||
CloseHandle(hThread);
|
||||
VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
|
||||
CloseHandle(hProcess);
|
||||
return 0;
|
||||
// CloseHandle(hProcess); // Close when exit
|
||||
|
||||
return hProcess;
|
||||
}
|
||||
|
||||
int EjectDll(DWORD pid, const WCHAR *dllPath)
|
||||
bool EjectDll(HANDLE process, HMODULE dllBase)
|
||||
{
|
||||
DWORD dwHandle, dwID;
|
||||
HANDLE hThread = NULL;
|
||||
DWORD dwWriteSize = 0;
|
||||
|
||||
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
||||
LPVOID pRemoteAddress = VirtualAllocEx(hProcess, NULL, 1, MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
if (pRemoteAddress)
|
||||
WriteProcessMemory(hProcess, pRemoteAddress, dllPath, wcslen(dllPath) * 2 + 2, &dwWriteSize);
|
||||
else {
|
||||
MessageBox(NULL, L"DLL 路径写入失败", L"EjectDll", 0);
|
||||
return -1;
|
||||
}
|
||||
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetModuleHandleW, pRemoteAddress, 0, &dwID);
|
||||
if (hThread) {
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
GetExitCodeThread(hThread, &dwHandle);
|
||||
} else {
|
||||
MessageBox(NULL, L"GetModuleHandleW 调用失败!", L"EjectDll", 0);
|
||||
return -2;
|
||||
}
|
||||
CloseHandle(hThread);
|
||||
HANDLE hThread = NULL;
|
||||
|
||||
// 使目标进程调用 FreeLibrary,卸载 DLL
|
||||
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)FreeLibrary, (LPVOID)dwHandle, 0, &dwID);
|
||||
if (hThread) {
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
} else {
|
||||
hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)FreeLibrary, (LPVOID)dllBase, 0, NULL);
|
||||
if (hThread == NULL) {
|
||||
MessageBox(NULL, L"FreeLibrary 调用失败!", L"EjectDll", 0);
|
||||
return -3;
|
||||
return false;
|
||||
}
|
||||
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
CloseHandle(hThread);
|
||||
VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
|
||||
CloseHandle(hProcess);
|
||||
return 0;
|
||||
CloseHandle(process);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void *GetFuncAddr(LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName)
|
||||
{
|
||||
HMODULE hLoaded = LoadLibrary(dllPath);
|
||||
if (hLoaded == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *absAddr = GetProcAddress(hLoaded, funcName);
|
||||
DWORD offset = (DWORD)absAddr - (DWORD)hLoaded;
|
||||
|
||||
FreeLibrary(hLoaded);
|
||||
|
||||
return (void *)((DWORD)dllBase + offset);
|
||||
}
|
||||
|
||||
bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, DWORD *ret)
|
||||
{
|
||||
void *pFunc = GetFuncAddr(dllPath, dllBase, funcName);
|
||||
if (pFunc == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HANDLE hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, NULL, 0, NULL);
|
||||
if (hThread == NULL) {
|
||||
return false;
|
||||
}
|
||||
WaitForSingleObject(hThread, INFINITE);
|
||||
if (ret != NULL) {
|
||||
GetExitCodeThread(hThread, ret);
|
||||
}
|
||||
|
||||
CloseHandle(hThread);
|
||||
return true;
|
||||
}
|
||||
|
||||
+4
-3
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "framework.h"
|
||||
|
||||
int InjectDll(DWORD pid, const WCHAR* dllPath);
|
||||
int EjectDll(DWORD pid, const WCHAR* dllPath);
|
||||
|
||||
HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase);
|
||||
bool EjectDll(HANDLE process, HMODULE dllBase);
|
||||
bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, DWORD *ret);
|
||||
|
||||
@@ -1,278 +0,0 @@
|
||||
#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);
|
||||
|
||||
// Releases binding handle resources and disconnects from the server
|
||||
status = RpcBindingFree(&hSpyBinding);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int RpcEnableReceiveMsg()
|
||||
{
|
||||
unsigned long ulCode = 0;
|
||||
RpcTryExcept
|
||||
{
|
||||
// 建立RPC通道,让服务端能够调用客户端的回调函数。(该接口会被服务端阻塞直到异常退出)
|
||||
client_EnableReceiveMsg();
|
||||
}
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("RpcEnableReceiveMsg exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RpcDisableReceiveMsg()
|
||||
{
|
||||
unsigned long ulCode = 0;
|
||||
RpcTryExcept
|
||||
{
|
||||
// UnHook Message receiving
|
||||
client_DisableReceiveMsg();
|
||||
}
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("RpcDisableReceiveMsg 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);
|
||||
return -1;
|
||||
}
|
||||
RpcEndExcept;
|
||||
|
||||
return loginFlag;
|
||||
}
|
||||
|
||||
int RpcGetSelfWxId(wchar_t wxid[20])
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned long ulCode = 0;
|
||||
RpcTryExcept { ret = client_GetSelfWxId(wxid); }
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("RpcIsLogin exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RpcSendTextMsg(const wchar_t *wxid, const wchar_t *msg, const wchar_t *atWxids)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long ulCode = 0;
|
||||
|
||||
RpcTryExcept { ret = client_SendTextMsg(wxid, msg, atWxids); }
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("RpcSendTextMsg 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("RpcSendImageMsg 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;
|
||||
}
|
||||
|
||||
BSTR *RpcGetDbNames(int *pNum)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long ulCode = 0;
|
||||
BSTR *pBstr = NULL;
|
||||
|
||||
RpcTryExcept { ret = client_GetDbNames(pNum, &pBstr); }
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("RpcGetDbNames exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept;
|
||||
if (ret != 0) {
|
||||
printf("RpcGetDbNames Failed: %d\n", ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pBstr;
|
||||
}
|
||||
|
||||
PPRpcTables RpcGetDbTables(const wchar_t *db, int *pNum)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long ulCode = 0;
|
||||
PPRpcTables ppRpcTables = NULL;
|
||||
|
||||
RpcTryExcept { ret = client_GetDbTables(db, pNum, &ppRpcTables); }
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("RpcGetDbTables exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept;
|
||||
if (ret != 0) {
|
||||
printf("RpcGetDbTables Failed: %d\n", ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ppRpcTables;
|
||||
}
|
||||
|
||||
PPPRpcSqlResult RpcExecDbQuery(const wchar_t *db, const wchar_t *sql, int *pRow, int *pCol)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long ulCode = 0;
|
||||
PPPRpcSqlResult pppRpcSqlResult = NULL;
|
||||
|
||||
RpcTryExcept { ret = client_ExecDbQuery(db, sql, pRow, pCol, &pppRpcSqlResult); }
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("RpcExecDbQuery exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||
}
|
||||
RpcEndExcept;
|
||||
if (ret != 0) {
|
||||
printf("RpcExecDbQuery Failed: %d\n", ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pppRpcSqlResult;
|
||||
}
|
||||
|
||||
BOOL AcceptNewFriend(const wchar_t *v3, const wchar_t *v4)
|
||||
{
|
||||
BOOL ret = 0;
|
||||
unsigned long ulCode = 0;
|
||||
|
||||
RpcTryExcept { ret = client_AcceptNewFriend(v3, v4); }
|
||||
RpcExcept(1)
|
||||
{
|
||||
ulCode = RpcExceptionCode();
|
||||
printf("AcceptNewFriend 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;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "rpc_h.h"
|
||||
|
||||
RPC_STATUS RpcConnectServer();
|
||||
RPC_STATUS RpcDisconnectServer();
|
||||
|
||||
int RpcEnableReceiveMsg();
|
||||
int RpcDisableReceiveMsg();
|
||||
int RpcIsLogin();
|
||||
int RpcGetSelfWxId(wchar_t wxid[20]);
|
||||
int RpcSendTextMsg(const wchar_t *wxid, const wchar_t *msg, const wchar_t *atWxids);
|
||||
int RpcSendImageMsg(const wchar_t *wxid, const wchar_t *path);
|
||||
PPRpcIntBstrPair RpcGetMsgTypes(int *pNum);
|
||||
PPRpcContact RpcGetContacts(int *pNum);
|
||||
BSTR *RpcGetDbNames(int *pNum);
|
||||
PPRpcTables RpcGetDbTables(const wchar_t *db, int *pNum);
|
||||
PPPRpcSqlResult RpcExecDbQuery(const wchar_t *db, const wchar_t *sql, int *row, int *col);
|
||||
BOOL AcceptNewFriend(const wchar_t *v3, const wchar_t *v4);
|
||||
+38
-238
@@ -1,273 +1,73 @@
|
||||
#include "Shlwapi.h"
|
||||
#include "Shlwapi.h"
|
||||
#include "framework.h"
|
||||
#include <process.h>
|
||||
#include <queue>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <vector>
|
||||
|
||||
#include "injector.h"
|
||||
#include "rpc_client.h"
|
||||
#include "log.h"
|
||||
#include "sdk.h"
|
||||
#include "util.h"
|
||||
|
||||
std::function<int(WxMessage_t)> g_cbReceiveTextMsg;
|
||||
|
||||
static DWORD WeChatPID = 0;
|
||||
static WCHAR SpyDllPath[MAX_PATH] = { 0 };
|
||||
static DWORD wcPid = 0;
|
||||
static HANDLE wcProcess = NULL;
|
||||
static HMODULE spyBase = NULL;
|
||||
static WCHAR spyDllPath[MAX_PATH] = { 0 };
|
||||
|
||||
int WxInitSDK()
|
||||
{
|
||||
int status = 0;
|
||||
unsigned long ulCode = 0;
|
||||
int status = 0;
|
||||
InitLogger();
|
||||
LOG_INFO("WxInitSDK.");
|
||||
GetModuleFileName(GetModuleHandle(WECHATSDKDLL), spyDllPath, MAX_PATH);
|
||||
PathRemoveFileSpec(spyDllPath);
|
||||
PathAppend(spyDllPath, WECHATINJECTDLL);
|
||||
|
||||
GetModuleFileName(GetModuleHandle(WECHATSDKDLL), SpyDllPath, MAX_PATH);
|
||||
PathRemoveFileSpec(SpyDllPath);
|
||||
PathAppend(SpyDllPath, WECHATINJECTDLL);
|
||||
|
||||
if (!PathFileExists(SpyDllPath)) {
|
||||
if (!PathFileExists(spyDllPath)) {
|
||||
LOG_ERROR("DLL does not exists.");
|
||||
return ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
status = OpenWeChat(&WeChatPID);
|
||||
status = OpenWeChat(&wcPid);
|
||||
if (status != 0) {
|
||||
LOG_ERROR("OpenWeChat failed: {}.", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
Sleep(2000); // 等待微信打开
|
||||
if (InjectDll(WeChatPID, SpyDllPath)) {
|
||||
wcProcess = InjectDll(wcPid, spyDllPath, &spyBase);
|
||||
if (wcProcess == NULL) {
|
||||
LOG_ERROR("Failed to Inject DLL into WeChat.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Sleep(1000); // 等待SPY就绪
|
||||
status = RpcConnectServer();
|
||||
if (status != 0) {
|
||||
printf("RpcConnectServer: %d\n", status);
|
||||
if (!CallDllFunc(wcProcess, spyDllPath, spyBase, "InitSpy", NULL)) {
|
||||
LOG_ERROR("Failed to InitSpy.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
status = RpcIsLogin();
|
||||
if (status == -1) {
|
||||
return status;
|
||||
} else if (status == 1) {
|
||||
break;
|
||||
if (!CallDllFunc(wcProcess, spyDllPath, spyBase, "IsLogin", (DWORD *)&status)) {
|
||||
LOG_ERROR("Failed to check login status.");
|
||||
return -1;
|
||||
}
|
||||
Sleep(1000);
|
||||
} while (1);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int WxDestroySDK()
|
||||
{
|
||||
WxDisableRecvMsg();
|
||||
RpcDisconnectServer();
|
||||
// 关闭 RPC,但不卸载 DLL,方便下次使用。
|
||||
// EjectDll(WeChatPID, SpyDllPath);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int WxEnableRecvMsg(const std::function<int(WxMessage_t)> &onMsg)
|
||||
{
|
||||
if (onMsg) {
|
||||
HANDLE msgThread;
|
||||
g_cbReceiveTextMsg = onMsg;
|
||||
|
||||
msgThread = (HANDLE)CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RpcEnableReceiveMsg, NULL, 0, NULL);
|
||||
if (msgThread == NULL) {
|
||||
printf("Failed to create innerWxRecvTextMsg.\n");
|
||||
return -2;
|
||||
}
|
||||
CloseHandle(msgThread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Empty Callback.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int WxDisableRecvMsg()
|
||||
{
|
||||
RpcDisableReceiveMsg();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int WxSendTextMsg(wstring wxid, wstring msg, wstring atWxids)
|
||||
{
|
||||
return RpcSendTextMsg(wxid.c_str(), msg.c_str(), atWxids.c_str());
|
||||
}
|
||||
|
||||
int WxSendImageMsg(wstring wxid, wstring path) { return RpcSendImageMsg(wxid.c_str(), path.c_str()); }
|
||||
|
||||
static int getAddrHandle(DWORD *addr, HANDLE *handle)
|
||||
{
|
||||
DWORD processID = 0;
|
||||
wstring processName = L"WeChat.exe";
|
||||
wstring moduleName = L"WeChatWin.dll";
|
||||
|
||||
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
|
||||
while (Process32Next(hSnapshot, &pe32)) {
|
||||
wstring strProcess = pe32.szExeFile;
|
||||
if (strProcess == processName) {
|
||||
processID = pe32.th32ProcessID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CloseHandle(hSnapshot);
|
||||
if (processID == 0) {
|
||||
printf("Failed to get Process ID\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
HANDLE hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processID);
|
||||
if (hProcessSnapshot == INVALID_HANDLE_VALUE) {
|
||||
printf("Failed to get Process Snapshot\r\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
MODULEENTRY32 me32;
|
||||
SecureZeroMemory(&me32, sizeof(MODULEENTRY32));
|
||||
me32.dwSize = sizeof(MODULEENTRY32);
|
||||
while (Module32Next(hProcessSnapshot, &me32)) {
|
||||
me32.dwSize = sizeof(MODULEENTRY32);
|
||||
|
||||
if (!wcscmp(me32.szModule, moduleName.c_str())) {
|
||||
*addr = (DWORD)me32.modBaseAddr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(hProcessSnapshot);
|
||||
if (*addr == 0) {
|
||||
printf("Failed to get Module Address\r\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
*handle = OpenProcess(PROCESS_VM_READ, FALSE, processID);
|
||||
if (*handle == 0) {
|
||||
printf("Failed to open Process\r\n");
|
||||
return -4;
|
||||
}
|
||||
} while (status == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
wstring WxGetSelfWxid()
|
||||
int WxDestroySDK()
|
||||
{
|
||||
wchar_t wxid[20] = { 0 };
|
||||
RpcGetSelfWxId(wxid);
|
||||
return wstring(wxid);
|
||||
LOG_INFO("WxDestroySDK");
|
||||
if (!CallDllFunc(wcProcess, spyDllPath, spyBase, "CleanupSpy", NULL)) {
|
||||
LOG_ERROR("Failed to CleanupSpy.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!EjectDll(wcProcess, spyBase)) {
|
||||
LOG_ERROR("Failed to Eject DLL.");
|
||||
return -1; // TODO: Unify error codes
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
|
||||
mContact.insert(make_pair(contact.wxId, contact));
|
||||
midl_user_free(pp[i]);
|
||||
}
|
||||
|
||||
if (pp) {
|
||||
midl_user_free(pp);
|
||||
}
|
||||
|
||||
return mContact;
|
||||
}
|
||||
|
||||
std::vector<std::wstring> WxGetDbNames()
|
||||
{
|
||||
std::vector<std::wstring> vDbs;
|
||||
int size = 0;
|
||||
BSTR *pBstr = RpcGetDbNames(&size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
vDbs.push_back(GetWstringFromBstr(pBstr[i]));
|
||||
}
|
||||
|
||||
if (pBstr) {
|
||||
midl_user_free(pBstr);
|
||||
}
|
||||
|
||||
return vDbs;
|
||||
}
|
||||
|
||||
DbTableVector_t WxGetDbTables(wstring db)
|
||||
{
|
||||
DbTableVector_t vTables;
|
||||
int size = 0;
|
||||
PPRpcTables pp = RpcGetDbTables(db.c_str(), &size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
WxDbTable_t tbl;
|
||||
tbl.table = GetWstringFromBstr(pp[i]->table);
|
||||
tbl.sql = GetWstringFromBstr(pp[i]->sql);
|
||||
|
||||
vTables.push_back(tbl);
|
||||
midl_user_free(pp[i]);
|
||||
}
|
||||
|
||||
if (pp) {
|
||||
midl_user_free(pp);
|
||||
}
|
||||
|
||||
return vTables;
|
||||
}
|
||||
|
||||
SqlRetVector_t WxExecDbQuery(wstring db, wstring sql)
|
||||
{
|
||||
int row, col = 0;
|
||||
PPPRpcSqlResult ppp = RpcExecDbQuery(db.c_str(), sql.c_str(), &row, &col);
|
||||
vector<vector<WxSqlResult_t>> vvResults;
|
||||
for (int r = 0; r < row; r++) {
|
||||
vector<WxSqlResult_t> vResult;
|
||||
for (int c = 0; c < col; c++) {
|
||||
WxSqlResult_t result = { 0 };
|
||||
result.type = ppp[r][c]->type;
|
||||
result.column = GetWstringFromBstr(ppp[r][c]->column);
|
||||
result.content = GetBytesFromBstr(ppp[r][c]->content);
|
||||
vResult.push_back(result);
|
||||
midl_user_free(ppp[r][c]);
|
||||
}
|
||||
vvResults.push_back(vResult);
|
||||
midl_user_free(ppp[r]);
|
||||
}
|
||||
if (ppp) {
|
||||
midl_user_free(ppp);
|
||||
}
|
||||
|
||||
return vvResults;
|
||||
}
|
||||
|
||||
BOOL WxAcceptNewFriend(wstring v3, wstring v4) { return AcceptNewFriend(v3.c_str(), v4.c_str()); }
|
||||
|
||||
-11
@@ -1,14 +1,3 @@
|
||||
EXPORTS
|
||||
WxInitSDK
|
||||
WxDestroySDK
|
||||
WxEnableRecvMsg
|
||||
WxDisableRecvMsg
|
||||
WxSendTextMsg
|
||||
WxGetSelfWxid
|
||||
WxGetMsgTypes
|
||||
WxSendImageMsg
|
||||
WxGetContacts
|
||||
WxGetDbNames
|
||||
WxGetDbTables
|
||||
WxExecDbQuery
|
||||
WxAcceptNewFriend
|
||||
|
||||
@@ -1,60 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "framework.h"
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef struct WxMessage {
|
||||
int self; // 是否自己发的消息:0=否,1=是
|
||||
int type; // 消息类型
|
||||
int source; // 消息来源:0=好友消息,1=群消息
|
||||
wstring id; // 消息ID
|
||||
wstring xml; // 群其他消息
|
||||
wstring wxId; // 发送人微信ID
|
||||
wstring roomId; // 群ID
|
||||
wstring content; // 消息内容,MAC版最大:16384,即16KB
|
||||
} WxMessage_t;
|
||||
|
||||
typedef struct WxContact {
|
||||
wstring wxId; // 微信ID
|
||||
wstring wxCode; // 微信号
|
||||
wstring wxName; // 微信昵称
|
||||
wstring wxCountry; // 国家
|
||||
wstring wxProvince; // 省/州
|
||||
wstring wxCity; // 城市
|
||||
wstring wxGender; // 性别
|
||||
} WxContact_t;
|
||||
|
||||
typedef struct WxDbTable {
|
||||
wstring table; // 表名
|
||||
wstring sql; // 建表 SQL
|
||||
} WxDbTable_t;
|
||||
|
||||
typedef struct WxSqlResult {
|
||||
int type;
|
||||
wstring column;
|
||||
string content;
|
||||
} WxSqlResult_t;
|
||||
|
||||
typedef map<int, wstring> MsgTypesMap_t;
|
||||
typedef map<wstring, WxContact_t> ContactMap_t;
|
||||
typedef vector<WxDbTable_t> DbTableVector_t;
|
||||
typedef vector<vector<WxSqlResult_t>> SqlRetVector_t;
|
||||
#pragma once
|
||||
|
||||
int WxInitSDK();
|
||||
int WxDestroySDK();
|
||||
int WxEnableRecvMsg(const std::function<int(WxMessage_t)> &onMsg);
|
||||
int WxDisableRecvMsg();
|
||||
int WxSendTextMsg(wstring wxid, wstring msg, wstring vAtWxids);
|
||||
int WxSendImageMsg(wstring wxid, wstring path);
|
||||
wstring WxGetSelfWxid();
|
||||
ContactMap_t WxGetContacts();
|
||||
MsgTypesMap_t WxGetMsgTypes();
|
||||
vector<wstring> WxGetDbNames();
|
||||
DbTableVector_t WxGetDbTables(wstring db);
|
||||
SqlRetVector_t WxExecDbQuery(wstring db, wstring sql);
|
||||
BOOL WxAcceptNewFriend(wstring v3, wstring v4);
|
||||
|
||||
-312
@@ -1,312 +0,0 @@
|
||||
#include "Shlwapi.h"
|
||||
#include "framework.h"
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
#include <string.h>
|
||||
#include <strsafe.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#pragma comment(lib, "shlwapi")
|
||||
#pragma comment(lib, "Version.lib")
|
||||
|
||||
using namespace std;
|
||||
|
||||
static wstring_convert<codecvt_utf8<wchar_t>, wchar_t> S_WS_Converter;
|
||||
|
||||
wstring String2Wstring(string s) { return S_WS_Converter.from_bytes(s); }
|
||||
string Wstring2String(wstring ws) { return S_WS_Converter.to_bytes(ws); }
|
||||
|
||||
static int GetWeChatPath(wchar_t *path)
|
||||
{
|
||||
int ret = -1;
|
||||
HKEY hKey = NULL;
|
||||
// HKEY_CURRENT_USER\Software\Tencent\WeChat InstallPath = xx
|
||||
if (ERROR_SUCCESS != RegOpenKey(HKEY_CURRENT_USER, L"Software\\Tencent\\WeChat", &hKey)) {
|
||||
ret = GetLastError();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DWORD Type = REG_SZ;
|
||||
DWORD cbData = MAX_PATH * sizeof(WCHAR);
|
||||
if (ERROR_SUCCESS != RegQueryValueEx(hKey, L"InstallPath", 0, &Type, (LPBYTE)path, &cbData)) {
|
||||
ret = GetLastError();
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
if (path != NULL) {
|
||||
PathAppend(path, WECHAREXE);
|
||||
}
|
||||
|
||||
__exit:
|
||||
if (hKey) {
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static int GetWeChatWinDLLPath(wchar_t *path)
|
||||
{
|
||||
int ret = GetWeChatPath(path);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
PathRemoveFileSpecW(path);
|
||||
PathAppendW(path, WECHATWINDLL);
|
||||
if (!PathFileExists(path)) {
|
||||
// 微信从(大约)3.7开始,增加了一层版本目录: [3.7.0.29]
|
||||
PathRemoveFileSpec(path);
|
||||
_wfinddata_t findData;
|
||||
wstring dir = wstring(path) + L"\\[*.*";
|
||||
intptr_t handle = _wfindfirst(dir.c_str(), &findData);
|
||||
if (handle == -1) { // 检查是否成功
|
||||
return -1;
|
||||
}
|
||||
wstring dllPath = wstring(path) + L"\\" + findData.name;
|
||||
wcscpy_s(path, MAX_PATH, dllPath.c_str());
|
||||
PathAppend(path, WECHATWINDLL);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool GetFileVersion(const wchar_t *filePath, wchar_t *version)
|
||||
{
|
||||
if (wcslen(filePath) > 0 && PathFileExists(filePath)) {
|
||||
VS_FIXEDFILEINFO *pVerInfo = NULL;
|
||||
DWORD dwTemp, dwSize;
|
||||
BYTE *pData = NULL;
|
||||
UINT uLen;
|
||||
|
||||
dwSize = GetFileVersionInfoSize(filePath, &dwTemp);
|
||||
if (dwSize == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pData = new BYTE[dwSize + 1];
|
||||
if (pData == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GetFileVersionInfo(filePath, 0, dwSize, pData)) {
|
||||
delete[] pData;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!VerQueryValue(pData, TEXT("\\"), (void **)&pVerInfo, &uLen)) {
|
||||
delete[] pData;
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD verMS = pVerInfo->dwFileVersionMS;
|
||||
DWORD verLS = pVerInfo->dwFileVersionLS;
|
||||
DWORD major = HIWORD(verMS);
|
||||
DWORD minor = LOWORD(verMS);
|
||||
DWORD build = HIWORD(verLS);
|
||||
DWORD revision = LOWORD(verLS);
|
||||
delete[] pData;
|
||||
|
||||
StringCbPrintf(version, 0x20, TEXT("%d.%d.%d.%d"), major, minor, build, revision);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int GetWeChatVersion(wchar_t *version)
|
||||
{
|
||||
WCHAR Path[MAX_PATH] = { 0 };
|
||||
|
||||
int ret = GetWeChatWinDLLPath(Path);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = GetFileVersion(Path, version);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DWORD GetWeChatPid()
|
||||
{
|
||||
DWORD pid = 0;
|
||||
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
|
||||
while (Process32Next(hSnapshot, &pe32)) {
|
||||
wstring strProcess = pe32.szExeFile;
|
||||
if (strProcess == WECHAREXE) {
|
||||
pid = pe32.th32ProcessID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CloseHandle(hSnapshot);
|
||||
return pid;
|
||||
}
|
||||
|
||||
int OpenWeChat(DWORD *pid)
|
||||
{
|
||||
*pid = GetWeChatPid();
|
||||
if (*pid) {
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int ret = -1;
|
||||
STARTUPINFO si = { sizeof(si) };
|
||||
WCHAR Path[MAX_PATH] = { 0 };
|
||||
PROCESS_INFORMATION pi = { 0 };
|
||||
|
||||
ret = GetWeChatPath(Path);
|
||||
if (ERROR_SUCCESS != ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!CreateProcess(NULL, Path, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
CloseHandle(pi.hThread);
|
||||
CloseHandle(pi.hProcess);
|
||||
|
||||
*pid = pi.dwProcessId;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size)
|
||||
{
|
||||
DWORD strLength = GET_DWORD(address + 4);
|
||||
if (strLength == 0) {
|
||||
return 0;
|
||||
} else if (strLength > buffer_size) {
|
||||
strLength = buffer_size - 1;
|
||||
}
|
||||
|
||||
wmemcpy_s(buffer, strLength + 1, GET_WSTRING(address), strLength + 1);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
BSTR GetBstrFromString(const char *str)
|
||||
{
|
||||
int wslen = MultiByteToWideChar(CP_ACP, 0, str, strlen(str), 0, 0);
|
||||
BSTR bstr = SysAllocStringLen(0, wslen);
|
||||
MultiByteToWideChar(CP_ACP, 0, str, strlen(str), bstr, wslen);
|
||||
|
||||
return bstr;
|
||||
}
|
||||
|
||||
BSTR GetBstrFromWstring(wstring ws)
|
||||
{
|
||||
if (!ws.empty()) {
|
||||
return SysAllocStringLen(ws.data(), ws.size());
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BSTR GetBstrFromStringBuffer(const char *str, int length)
|
||||
{
|
||||
int wslen = MultiByteToWideChar(CP_ACP, 0, str, length, 0, 0);
|
||||
BSTR bstr = SysAllocStringLen(0, wslen);
|
||||
MultiByteToWideChar(CP_ACP, 0, str, length, bstr, wslen);
|
||||
|
||||
return bstr;
|
||||
}
|
||||
|
||||
BSTR GetBstrFromByteArray(const byte *b, int len)
|
||||
{
|
||||
BSTR bstr = SysAllocStringLen(0, len);
|
||||
if (bstr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memcpy((byte *)bstr, b, len);
|
||||
|
||||
return bstr;
|
||||
}
|
||||
|
||||
string GetBytesFromBstr(BSTR bstr)
|
||||
{
|
||||
string s = "";
|
||||
if (bstr) {
|
||||
int len = SysStringByteLen(bstr) / 2;
|
||||
char *tmp = new char[len];
|
||||
char *p = (char *)bstr;
|
||||
for (int i = 0; i < len; i++) {
|
||||
tmp[i] = p[i];
|
||||
}
|
||||
SysFreeString(bstr);
|
||||
s = string(tmp, len);
|
||||
delete[] tmp;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
unsigned char data[4] = { 0 };
|
||||
if (ReadProcessMemory(hProcess, (LPVOID)address, data, 4, 0)) {
|
||||
value = data[0] & 0xFF;
|
||||
value |= ((data[1] << 8) & 0xFF00);
|
||||
value |= ((data[2] << 16) & 0xFF0000);
|
||||
value |= ((data[3] << 24) & 0xFF000000);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address)
|
||||
{
|
||||
wstring value = L"";
|
||||
|
||||
DWORD strAddress = GetMemoryIntByAddress(hProcess, address);
|
||||
DWORD strLen = GetMemoryIntByAddress(hProcess, address + 0x4);
|
||||
if (strLen > 500)
|
||||
return value;
|
||||
|
||||
wchar_t cValue[500] = { 0 };
|
||||
memset(cValue, 0, sizeof(cValue) / sizeof(wchar_t));
|
||||
if (ReadProcessMemory(hProcess, (LPVOID)strAddress, cValue, (strLen + 1) * 2, 0)) {
|
||||
value = wstring(cValue);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "rpc_h.h"
|
||||
#include "sdk.h"
|
||||
|
||||
#define WECHAREXE L"WeChat.exe"
|
||||
#define WECHATWINDLL L"WeChatWin.dll"
|
||||
#define WECHATSDKDLL L"SDK.dll"
|
||||
#define WECHATINJECTDLL L"Spy.dll"
|
||||
|
||||
#define GET_DWORD(addr) ((DWORD) * (DWORD *)(addr))
|
||||
#define GET_STRING(addr) ((CHAR *)(*(DWORD *)(addr)))
|
||||
#define GET_WSTRING(addr) ((WCHAR *)(*(DWORD *)(addr)))
|
||||
|
||||
int OpenWeChat(DWORD *pid);
|
||||
int GetWeChatVersion(wchar_t *version);
|
||||
int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size);
|
||||
void GetRpcMessage(WxMessage_t *wxMsg, RpcMessage_t rpcMsg);
|
||||
DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address);
|
||||
BSTR GetBstrByAddress(DWORD address);
|
||||
BSTR GetBstrFromString(const char *str);
|
||||
BSTR GetBstrFromWstring(std::wstring ws);
|
||||
BSTR GetBstrFromByteArray(const byte *b, int len);
|
||||
BSTR GetBstrFromStringBuffer(const char *str, int length);
|
||||
std::string GetBytesFromBstr(BSTR bstr);
|
||||
std::wstring GetWstringFromBstr(BSTR bstr);
|
||||
std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address);
|
||||
std::wstring String2Wstring(std::string s);
|
||||
std::string Wstring2String(std::wstring ws);
|
||||
Reference in New Issue
Block a user