Bump gRPC

This commit is contained in:
Changhua
2022-10-15 20:25:42 +08:00
parent 35498520c2
commit ef20038fcd
50 changed files with 1905 additions and 2387 deletions
+24 -15
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1,5 +1,5 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容
// Windows 头文件
#include <windows.h>
+70 -50
View File
@@ -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
View File
@@ -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);
-278
View File
@@ -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;
}
-19
View File
@@ -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
View File
@@ -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
View File
@@ -1,14 +1,3 @@
EXPORTS
WxInitSDK
WxDestroySDK
WxEnableRecvMsg
WxDisableRecvMsg
WxSendTextMsg
WxGetSelfWxid
WxGetMsgTypes
WxSendImageMsg
WxGetContacts
WxGetDbNames
WxGetDbTables
WxExecDbQuery
WxAcceptNewFriend
+1 -57
View File
@@ -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
View File
@@ -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
View File
@@ -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);