Refactoring
This commit is contained in:
parent
1bec8ce8a2
commit
e012efc682
@ -3,13 +3,12 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <spdlog/sinks/rotating_file_sink.h>
|
|
||||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "util.h"
|
#include <spdlog/sinks/rotating_file_sink.h>
|
||||||
|
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
#define LOG_DEBUG(...) SPDLOG_DEBUG(__VA_ARGS__)
|
#define LOG_DEBUG(...) SPDLOG_DEBUG(__VA_ARGS__)
|
||||||
#define LOG_INFO(...) SPDLOG_INFO(__VA_ARGS__)
|
#define LOG_INFO(...) SPDLOG_INFO(__VA_ARGS__)
|
||||||
@ -48,7 +47,7 @@ inline void InitLogger(const std::string &path)
|
|||||||
logger = spdlog::rotating_logger_mt(DEFAULT_LOGGER_NAME, filename.string(), DEFAULT_LOGGER_MAX_SIZE,
|
logger = spdlog::rotating_logger_mt(DEFAULT_LOGGER_NAME, filename.string(), DEFAULT_LOGGER_MAX_SIZE,
|
||||||
DEFAULT_LOGGER_MAX_FILES);
|
DEFAULT_LOGGER_MAX_FILES);
|
||||||
} catch (const spdlog::spdlog_ex &ex) {
|
} catch (const spdlog::spdlog_ex &ex) {
|
||||||
MessageBox(NULL, util::s2w(ex.what()).c_str(), L"Init LOGGER ERROR", MB_ICONERROR);
|
MessageBoxA(NULL, ex.what(), "Init LOGGER ERROR", MB_ICONERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
|
|
||||||
|
constexpr std::wstring_view WECHATEXE = L"WeChat.exe";
|
||||||
|
constexpr std::string_view WECHATWINDLL = "WeChatWin.dll";
|
||||||
|
|
||||||
std::wstring s2w(const std::string &s)
|
std::wstring s2w(const std::string &s)
|
||||||
{
|
{
|
||||||
if (s.empty()) return std::wstring();
|
if (s.empty()) return std::wstring();
|
||||||
@ -60,7 +63,7 @@ static DWORD get_wechat_pid()
|
|||||||
|
|
||||||
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
|
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
|
||||||
while (Process32Next(hSnapshot, &pe32)) {
|
while (Process32Next(hSnapshot, &pe32)) {
|
||||||
if (w2s(pe32.szExeFile) == WECHATEXE) {
|
if (pe32.szExeFile == WECHATEXE) {
|
||||||
pid = pe32.th32ProcessID;
|
pid = pe32.th32ProcessID;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,6 @@
|
|||||||
|
|
||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
|
|
||||||
inline constexpr char WECHATEXE[] = "WeChat.exe";
|
|
||||||
inline constexpr char WECHATWINDLL[] = "WeChatWin.dll";
|
|
||||||
inline constexpr wchar_t WCFSDKDLL[] = L"sdk.dll";
|
|
||||||
inline constexpr wchar_t WCFSPYDLL[] = L"spy.dll";
|
|
||||||
inline constexpr wchar_t WCFSPYDLL_DEBUG[] = L"spy_debug.dll";
|
|
||||||
|
|
||||||
struct PortPath {
|
struct PortPath {
|
||||||
int port;
|
int port;
|
||||||
char path[MAX_PATH];
|
char path[MAX_PATH];
|
||||||
|
@ -1,112 +1,108 @@
|
|||||||
#include "framework.h"
|
#include "injector.h"
|
||||||
#include "psapi.h"
|
|
||||||
#include <filesystem>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "injector.h"
|
#include <filesystem>
|
||||||
#include "util.h"
|
|
||||||
|
#include "psapi.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
HMODULE GetTargetModuleBase(HANDLE process, string dll)
|
static void handle_injection_error(HANDLE process, LPVOID remote_address, const std::string &error_msg)
|
||||||
{
|
{
|
||||||
DWORD cbNeeded;
|
MessageBoxA(NULL, error_msg.c_str(), "Error", MB_ICONERROR);
|
||||||
HMODULE moduleHandleList[512];
|
if (remote_address) {
|
||||||
BOOL ret = EnumProcessModulesEx(process, moduleHandleList, sizeof(moduleHandleList), &cbNeeded, LIST_MODULES_64BIT);
|
VirtualFreeEx(process, remote_address, 0, MEM_RELEASE);
|
||||||
if (!ret) {
|
}
|
||||||
MessageBox(NULL, L"获取模块失败", L"GetTargetModuleBase", 0);
|
if (process) {
|
||||||
|
CloseHandle(process);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HMODULE get_target_module_base(HANDLE process, const string &dll)
|
||||||
|
{
|
||||||
|
DWORD needed;
|
||||||
|
HMODULE modules[512];
|
||||||
|
if (!EnumProcessModulesEx(process, modules, sizeof(modules), &needed, LIST_MODULES_64BIT)) {
|
||||||
|
MessageBoxA(NULL, "获取模块失败", "get_target_module_base", 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cbNeeded > sizeof(moduleHandleList)) {
|
DWORD count = needed / sizeof(HMODULE);
|
||||||
MessageBox(NULL, L"模块数量过多", L"GetTargetModuleBase", 0);
|
char module_name[MAX_PATH];
|
||||||
return NULL;
|
for (DWORD i = 0; i < count; i++) {
|
||||||
}
|
GetModuleBaseNameA(process, modules[i], module_name, sizeof(module_name));
|
||||||
DWORD processCount = cbNeeded / sizeof(HMODULE);
|
if (!strncmp(dll.c_str(), module_name, dll.size())) {
|
||||||
|
return modules[i];
|
||||||
char moduleName[32];
|
|
||||||
for (DWORD i = 0; i < processCount; i++) {
|
|
||||||
GetModuleBaseNameA(process, moduleHandleList[i], moduleName, 32);
|
|
||||||
if (!strncmp(dll.c_str(), moduleName, dll.size())) {
|
|
||||||
return moduleHandleList[i];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase)
|
HANDLE inject_dll(DWORD pid, const string &dll_path, HMODULE *injected_base)
|
||||||
{
|
{
|
||||||
HANDLE hThread;
|
SIZE_T path_size = dll_path.size() + 1;
|
||||||
SIZE_T cszDLL = (wcslen(dllPath) + 1) * sizeof(WCHAR);
|
|
||||||
|
|
||||||
// 1. 打开目标进程
|
// 1. 打开目标进程
|
||||||
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
||||||
if (hProcess == NULL) {
|
if (!hProcess) {
|
||||||
MessageBox(NULL, L"打开进程失败", L"InjectDll", 0);
|
MessageBoxA(NULL, "打开进程失败", "inject_dll", 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 在目标进程的内存里开辟空间
|
// 2. 在目标进程的内存里开辟空间
|
||||||
LPVOID pRemoteAddress = VirtualAllocEx(hProcess, NULL, cszDLL, MEM_COMMIT, PAGE_READWRITE);
|
LPVOID pRemoteAddress = VirtualAllocEx(hProcess, NULL, path_size, MEM_COMMIT, PAGE_READWRITE);
|
||||||
if (pRemoteAddress == NULL) {
|
if (!pRemoteAddress) {
|
||||||
MessageBox(NULL, L"DLL 路径写入失败", L"InjectDll", 0);
|
handle_injection_error(hProcess, NULL, "DLL 路径写入失败");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 把 dll 的路径写入到目标进程的内存空间中
|
// 3. 把 dll 的路径写入到目标进程的内存空间中
|
||||||
WriteProcessMemory(hProcess, pRemoteAddress, dllPath, cszDLL, NULL);
|
WriteProcessMemory(hProcess, pRemoteAddress, dll_path.c_str(), path_size, NULL);
|
||||||
|
|
||||||
// 3. 创建一个远程线程,让目标进程调用 LoadLibrary
|
// 4. 创建一个远程线程,让目标进程调用 LoadLibrary
|
||||||
HMODULE k32 = GetModuleHandle(L"kernel32.dll");
|
HMODULE k32 = GetModuleHandleA("kernel32.dll");
|
||||||
if (k32 == NULL) {
|
if (!k32) {
|
||||||
MessageBox(NULL, L"获取 kernel32 失败", L"InjectDll", 0);
|
handle_injection_error(hProcess, pRemoteAddress, "获取 kernel32 失败");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
FARPROC libAddr = GetProcAddress(k32, "LoadLibraryW");
|
FARPROC libAddr = GetProcAddress(k32, "LoadLibraryA");
|
||||||
if (!libAddr) {
|
if (!libAddr) {
|
||||||
MessageBox(NULL, L"获取 LoadLibrary 失败", L"InjectDll", 0);
|
handle_injection_error(hProcess, pRemoteAddress, "获取 LoadLibrary 失败");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)libAddr, pRemoteAddress, 0, NULL);
|
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)libAddr, pRemoteAddress, 0, NULL);
|
||||||
if (hThread == NULL) {
|
if (!hThread) {
|
||||||
VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
|
handle_injection_error(hProcess, pRemoteAddress, "CreateRemoteThread 失败");
|
||||||
CloseHandle(hProcess);
|
|
||||||
MessageBox(NULL, L"CreateRemoteThread 失败", L"InjectDll", 0);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitForSingleObject(hThread, -1);
|
WaitForSingleObject(hThread, INFINITE);
|
||||||
CloseHandle(hThread);
|
CloseHandle(hThread);
|
||||||
|
|
||||||
*injectedBase = GetTargetModuleBase(hProcess, filesystem::path(util::w2s(dllPath)).filename().string());
|
*injected_base = get_target_module_base(hProcess, filesystem::path(dll_path).filename().string());
|
||||||
|
|
||||||
VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
|
VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
|
||||||
// CloseHandle(hProcess); // Close when exit
|
|
||||||
|
|
||||||
return hProcess;
|
return hProcess;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EjectDll(HANDLE process, HMODULE dllBase)
|
bool eject_dll(HANDLE process, HMODULE dll_base)
|
||||||
{
|
{
|
||||||
HANDLE hThread = NULL;
|
HMODULE k32 = GetModuleHandleA("kernel32.dll");
|
||||||
|
if (!k32) {
|
||||||
// 使目标进程调用 FreeLibrary,卸载 DLL
|
MessageBoxA(NULL, "获取 kernel32 失败", "eject_dll", 0);
|
||||||
HMODULE k32 = GetModuleHandle(L"kernel32.dll");
|
return false;
|
||||||
if (k32 == NULL) {
|
|
||||||
MessageBox(NULL, L"获取 kernel32 失败", L"InjectDll", 0);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FARPROC libAddr = GetProcAddress(k32, "FreeLibraryAndExitThread");
|
FARPROC libAddr = GetProcAddress(k32, "FreeLibraryAndExitThread");
|
||||||
if (!libAddr) {
|
if (!libAddr) {
|
||||||
MessageBox(NULL, L"获取 FreeLibrary 失败", L"InjectDll", 0);
|
MessageBoxA(NULL, "获取 FreeLibrary 失败", "eject_dll", 0);
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)libAddr, (LPVOID)dllBase, 0, NULL);
|
|
||||||
if (hThread == NULL) {
|
HANDLE hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)libAddr, (LPVOID)dll_base, 0, NULL);
|
||||||
MessageBox(NULL, L"FreeLibrary 调用失败!", L"EjectDll", 0);
|
if (!hThread) {
|
||||||
|
MessageBoxA(NULL, "FreeLibrary 调用失败!", "eject_dll", 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,38 +112,34 @@ bool EjectDll(HANDLE process, HMODULE dllBase)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT64 GetFuncOffset(LPCWSTR dllPath, LPCSTR funcName)
|
static uint64_t get_func_offset(const string &dll_path, const string &func_name)
|
||||||
{
|
{
|
||||||
HMODULE dll = LoadLibrary(dllPath);
|
HMODULE dll = LoadLibraryA(dll_path.c_str());
|
||||||
if (dll == NULL) {
|
if (!dll) {
|
||||||
MessageBox(NULL, L"获取 DLL 失败", L"GetFuncOffset", 0);
|
MessageBoxA(NULL, "获取 DLL 失败", "get_func_offset", 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LPVOID absAddr = GetProcAddress(dll, funcName);
|
LPVOID absAddr = GetProcAddress(dll, func_name.c_str());
|
||||||
UINT64 offset = (UINT64)absAddr - (UINT64)dll;
|
uint64_t offset = reinterpret_cast<uint64_t>(absAddr) - reinterpret_cast<uint64_t>(dll);
|
||||||
FreeLibrary(dll);
|
FreeLibrary(dll);
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPDWORD ret)
|
bool call_dll_func(HANDLE process, const string &dll_path, HMODULE dll_base, const string &func_name, DWORD *ret)
|
||||||
{
|
{
|
||||||
UINT64 offset = GetFuncOffset(dllPath, funcName);
|
uint64_t offset = get_func_offset(dll_path, func_name);
|
||||||
if (offset == 0) {
|
if (offset == 0 || offset > (UINT64_MAX - reinterpret_cast<uint64_t>(dll_base))) {
|
||||||
return false;
|
return false; // 避免溢出
|
||||||
}
|
}
|
||||||
UINT64 pFunc = (UINT64)dllBase + GetFuncOffset(dllPath, funcName);
|
uint64_t pFunc = reinterpret_cast<uint64_t>(dll_base) + offset;
|
||||||
if (pFunc <= (UINT64)dllBase) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, NULL, 0, NULL);
|
HANDLE hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, NULL, 0, NULL);
|
||||||
if (hThread == NULL) {
|
if (!hThread) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
WaitForSingleObject(hThread, INFINITE);
|
WaitForSingleObject(hThread, INFINITE);
|
||||||
if (ret != NULL) {
|
if (ret) {
|
||||||
GetExitCodeThread(hThread, ret);
|
GetExitCodeThread(hThread, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,35 +147,32 @@ bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcNa
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CallDllFuncEx(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPVOID parameter, size_t sz,
|
bool call_dll_func_ex(HANDLE process, const string &dll_path, HMODULE dll_base, const string &func_name,
|
||||||
LPDWORD ret)
|
LPVOID parameter, size_t size, DWORD *ret)
|
||||||
{
|
{
|
||||||
UINT64 offset = GetFuncOffset(dllPath, funcName);
|
uint64_t offset = get_func_offset(dll_path, func_name);
|
||||||
if (offset == 0) {
|
if (offset == 0 || offset > (UINT64_MAX - reinterpret_cast<uint64_t>(dll_base))) {
|
||||||
return false;
|
return false; // 避免溢出
|
||||||
}
|
}
|
||||||
UINT64 pFunc = (UINT64)dllBase + GetFuncOffset(dllPath, funcName);
|
uint64_t pFunc = reinterpret_cast<uint64_t>(dll_base) + offset;
|
||||||
if (pFunc <= (UINT64)dllBase) {
|
LPVOID pRemoteAddress = VirtualAllocEx(process, NULL, size, MEM_COMMIT, PAGE_READWRITE);
|
||||||
|
if (!pRemoteAddress) {
|
||||||
|
MessageBoxA(NULL, "申请内存失败", "call_dll_func_ex", 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
LPVOID pRemoteAddress = VirtualAllocEx(process, NULL, sz, MEM_COMMIT, PAGE_READWRITE);
|
WriteProcessMemory(process, pRemoteAddress, parameter, size, NULL);
|
||||||
if (pRemoteAddress == NULL) {
|
|
||||||
MessageBox(NULL, L"申请内存失败", L"CallDllFuncEx", 0);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteProcessMemory(process, pRemoteAddress, parameter, sz, NULL);
|
|
||||||
|
|
||||||
HANDLE hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, pRemoteAddress, 0, NULL);
|
HANDLE hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, pRemoteAddress, 0, NULL);
|
||||||
if (hThread == NULL) {
|
if (!hThread) {
|
||||||
VirtualFree(pRemoteAddress, 0, MEM_RELEASE);
|
VirtualFreeEx(process, pRemoteAddress, 0, MEM_RELEASE);
|
||||||
MessageBox(NULL, L"远程调用失败", L"CallDllFuncEx", 0);
|
MessageBoxA(NULL, "远程调用失败", "call_dll_func_ex", 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitForSingleObject(hThread, INFINITE);
|
WaitForSingleObject(hThread, INFINITE);
|
||||||
VirtualFree(pRemoteAddress, 0, MEM_RELEASE);
|
VirtualFreeEx(process, pRemoteAddress, 0, MEM_RELEASE);
|
||||||
if (ret != NULL) {
|
if (ret) {
|
||||||
GetExitCodeThread(hThread, ret);
|
GetExitCodeThread(hThread, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "framework.h"
|
#include "framework.h"
|
||||||
|
|
||||||
HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase);
|
HANDLE inject_dll(DWORD pid, const std::string &dll_path, HMODULE *injected_base);
|
||||||
bool EjectDll(HANDLE process, HMODULE dllBase);
|
bool eject_dll(HANDLE process, HMODULE dll_base);
|
||||||
bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, DWORD *ret);
|
bool call_dll_func(HANDLE process, const std::string &dll_path, HMODULE dll_base, const std::string &func, DWORD *ret);
|
||||||
bool CallDllFuncEx(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPVOID parameter, size_t sz,
|
bool call_dll_func_ex(HANDLE process, const std::string &dll_path, HMODULE dll_base, const std::string &func,
|
||||||
DWORD *ret);
|
LPVOID parameter, size_t size, DWORD *ret);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "framework.h"
|
#include "sdk.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -6,55 +7,56 @@
|
|||||||
#include <process.h>
|
#include <process.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
#include "framework.h"
|
||||||
#include <tlhelp32.h>
|
#include <tlhelp32.h>
|
||||||
|
|
||||||
#include "injector.h"
|
#include "injector.h"
|
||||||
#include "sdk.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
static BOOL injected = false;
|
static bool injected = false;
|
||||||
static HANDLE wcProcess = NULL;
|
static HANDLE wcProcess = NULL;
|
||||||
static HMODULE spyBase = NULL;
|
static HMODULE spyBase = NULL;
|
||||||
static std::wstring spyDllPath;
|
static std::string spyDllPath;
|
||||||
|
|
||||||
constexpr char DISCLAIMER_FILE[] = ".license_accepted.flag";
|
constexpr std::string_view WCFSDKDLL = "sdk.dll";
|
||||||
constexpr char DISCLAIMER_TEXT_FILE[] = "DISCLAIMER.md";
|
constexpr std::string_view WCFSPYDLL = "spy.dll";
|
||||||
|
constexpr std::string_view WCFSPYDLL_DEBUG = "spy_debug.dll";
|
||||||
|
constexpr std::string_view DISCLAIMER_FLAG = ".license_accepted.flag";
|
||||||
|
constexpr std::string_view DISCLAIMER_TEXT_FILE = "DISCLAIMER.md";
|
||||||
|
|
||||||
static std::optional<std::wstring> ReadDisclaimerText(const char *filePath)
|
static std::optional<std::string> read_disclaimer_text(const std::string &path)
|
||||||
{
|
{
|
||||||
std::ifstream file(filePath, std::ios::binary);
|
std::ifstream file(path, std::ios::binary);
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
return std::nullopt; // 文件打开失败
|
return std::nullopt; // 文件打开失败
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
return std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||||
return util::s2w(content);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ShowDisclaimer()
|
static bool show_disclaimer()
|
||||||
{
|
{
|
||||||
if (std::filesystem::exists(DISCLAIMER_FILE)) {
|
if (std::filesystem::exists(DISCLAIMER_FLAG)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::wstring> disclaimerTextOpt = ReadDisclaimerText(DISCLAIMER_TEXT_FILE);
|
auto disclaimerTextOpt = read_disclaimer_text(std::string(DISCLAIMER_TEXT_FILE));
|
||||||
if (!disclaimerTextOpt.has_value() || disclaimerTextOpt->empty()) {
|
if (!disclaimerTextOpt || disclaimerTextOpt->empty()) {
|
||||||
MessageBox(NULL, L"免责声明文件为空或读取失败。", L"错误", MB_ICONERROR);
|
MessageBoxA(NULL, "免责声明文件为空或读取失败。", "错误", MB_ICONERROR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring disclaimerText = *disclaimerTextOpt;
|
int result
|
||||||
|
= MessageBoxA(NULL, disclaimerTextOpt->c_str(), "免责声明", MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2);
|
||||||
int result = MessageBox(NULL, disclaimerText.c_str(), L"免责声明", MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2);
|
|
||||||
|
|
||||||
if (result == IDCANCEL) {
|
if (result == IDCANCEL) {
|
||||||
MessageBox(NULL, L"您拒绝了免责声明,程序将退出。", L"提示", MB_ICONINFORMATION);
|
MessageBoxA(NULL, "您拒绝了免责声明,程序将退出。", "提示", MB_ICONINFORMATION);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ofstream flagFile(DISCLAIMER_FILE, std::ios::out | std::ios::trunc);
|
std::ofstream flagFile(std::string(DISCLAIMER_FLAG), std::ios::out | std::ios::trunc);
|
||||||
if (!flagFile) {
|
if (!flagFile) {
|
||||||
MessageBox(NULL, L"无法创建协议标志文件。", L"错误", MB_ICONERROR);
|
MessageBoxA(NULL, "无法创建协议标志文件。", "错误", MB_ICONERROR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
flagFile << "User accepted the license agreement.";
|
flagFile << "User accepted the license agreement.";
|
||||||
@ -62,62 +64,56 @@ static bool ShowDisclaimer()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::wstring GetDllPath(bool debug)
|
static std::string get_dll_path(bool debug)
|
||||||
{
|
{
|
||||||
WCHAR buffer[MAX_PATH] = { 0 };
|
char buffer[MAX_PATH] = { 0 };
|
||||||
GetModuleFileName(GetModuleHandle(WCFSDKDLL), buffer, MAX_PATH);
|
GetModuleFileNameA(GetModuleHandleA(WCFSDKDLL), buffer, MAX_PATH);
|
||||||
|
|
||||||
std::filesystem::path path(buffer);
|
std::filesystem::path path(buffer);
|
||||||
path.remove_filename(); // 移除文件名,保留目录路径
|
path.remove_filename(); // 只保留目录路径
|
||||||
|
|
||||||
path /= debug ? WCFSPYDLL_DEBUG : WCFSPYDLL;
|
path /= debug ? WCFSPYDLL_DEBUG : WCFSPYDLL;
|
||||||
|
|
||||||
if (!std::filesystem::exists(path)) {
|
if (!std::filesystem::exists(path)) {
|
||||||
MessageBox(NULL, path.c_str(), L"文件不存在", MB_ICONERROR);
|
MessageBoxA(NULL, path.string().c_str(), "文件不存在", MB_ICONERROR);
|
||||||
return L"";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return path.wstring();
|
return path.string();
|
||||||
}
|
}
|
||||||
|
|
||||||
int WxInitSDK(bool debug, int port)
|
int WxInitSDK(bool debug, int port)
|
||||||
{
|
{
|
||||||
if (!ShowDisclaimer()) {
|
if (!show_disclaimer()) {
|
||||||
exit(-1); // 用户拒绝协议,退出程序
|
exit(-1); // 用户拒绝协议,退出程序
|
||||||
}
|
}
|
||||||
|
|
||||||
int status = 0;
|
int status = 0;
|
||||||
DWORD wcPid = 0;
|
DWORD wcPid = 0;
|
||||||
|
|
||||||
spyDllPath = GetDllPath(debug);
|
spyDllPath = get_dll_path(debug);
|
||||||
if (spyDllPath.empty()) {
|
if (spyDllPath.empty()) {
|
||||||
return ERROR_FILE_NOT_FOUND; // DLL 文件路径不存在
|
return ERROR_FILE_NOT_FOUND; // DLL 文件路径不存在
|
||||||
}
|
}
|
||||||
|
|
||||||
status = util::open_wechat(&wcPid);
|
status = util::open_wechat(&wcPid);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
MessageBox(NULL, L"打开微信失败", L"WxInitSDK", 0);
|
MessageBoxA(NULL, "打开微信失败", "WxInitSDK", 0);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsProcessX64(wcPid)) {
|
|
||||||
MessageBox(NULL, L"只支持 64 位微信", L"WxInitSDK", 0);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(2)); // 等待微信打开
|
std::this_thread::sleep_for(std::chrono::seconds(2)); // 等待微信打开
|
||||||
wcProcess = InjectDll(wcPid, spyDllPath.c_str(), &spyBase);
|
wcProcess = inject_dll(wcPid, spyDllPath, &spyBase);
|
||||||
if (wcProcess == NULL) {
|
if (wcProcess == NULL) {
|
||||||
MessageBox(NULL, L"注入失败", L"WxInitSDK", 0);
|
MessageBoxA(NULL, "注入失败", "WxInitSDK", 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PortPath_t pp = { 0 };
|
util::PortPath pp = { 0 };
|
||||||
pp.port = port;
|
pp.port = port;
|
||||||
sprintf_s(pp.path, MAX_PATH, "%s", std::filesystem::current_path().string().c_str());
|
snprintf(pp.path, MAX_PATH, "%s", std::filesystem::current_path().string().c_str());
|
||||||
|
|
||||||
if (!CallDllFuncEx(wcProcess, spyDllPath.c_str(), spyBase, "InitSpy", (LPVOID)&pp, sizeof(PortPath_t), NULL)) {
|
if (!call_dll_func_ex(wcProcess, spyDllPath, spyBase, "InitSpy", (LPVOID)&pp, sizeof(PortPath_t), NULL)) {
|
||||||
MessageBox(NULL, L"初始化失败", L"WxInitSDK", 0);
|
MessageBoxA(NULL, "初始化失败", "WxInitSDK", 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,16 +124,16 @@ int WxInitSDK(bool debug, int port)
|
|||||||
int WxDestroySDK()
|
int WxDestroySDK()
|
||||||
{
|
{
|
||||||
if (!injected) {
|
if (!injected) {
|
||||||
|
return 1; // 未注入
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!call_dll_func(wcProcess, spyDllPath, spyBase, "CleanupSpy", NULL)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CallDllFunc(wcProcess, spyDllPath.c_str(), spyBase, "CleanupSpy", NULL)) {
|
if (!eject_dll(wcProcess, spyBase)) {
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EjectDll(wcProcess, spyBase)) {
|
|
||||||
return -3; // TODO: Unify error codes
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user