Refactoring
This commit is contained in:
parent
ade2c1c22a
commit
c96d85db30
@ -48,7 +48,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, String2Wstring(ex.what()).c_str(), L"Init LOGGER ERROR", MB_ICONERROR);
|
MessageBox(NULL, util::s2w(ex.what()).c_str(), L"Init LOGGER ERROR", MB_ICONERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,177 +1,67 @@
|
|||||||
#include "Shlwapi.h"
|
#include "util.h"
|
||||||
#include "framework.h"
|
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
|
#include <memory>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
#include <tlhelp32.h>
|
#include <tlhelp32.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
|
#include "framework.h"
|
||||||
|
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
#pragma comment(lib, "shlwapi")
|
#pragma comment(lib, "shlwapi")
|
||||||
#pragma comment(lib, "Version.lib")
|
#pragma comment(lib, "Version.lib")
|
||||||
|
|
||||||
using namespace std;
|
namespace util
|
||||||
|
|
||||||
wstring String2Wstring(string s)
|
|
||||||
{
|
{
|
||||||
if (s.empty())
|
|
||||||
return wstring();
|
std::wstring s2w(const std::string &s)
|
||||||
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &s[0], (int)s.size(), NULL, 0);
|
{
|
||||||
wstring ws(size_needed, 0);
|
if (s.empty()) return std::wstring();
|
||||||
MultiByteToWideChar(CP_UTF8, 0, &s[0], (int)s.size(), &ws[0], size_needed);
|
int size_needed = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), static_cast<int>(s.size()), nullptr, 0);
|
||||||
|
std::wstring ws(size_needed, 0);
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, s.c_str(), static_cast<int>(s.size()), &ws[0], size_needed);
|
||||||
return ws;
|
return ws;
|
||||||
}
|
}
|
||||||
|
|
||||||
string Wstring2String(wstring ws)
|
std::string w2s(const std::wstring &ws)
|
||||||
{
|
{
|
||||||
if (ws.empty())
|
if (ws.empty()) return std::string();
|
||||||
return string();
|
int size_needed
|
||||||
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &ws[0], (int)ws.size(), NULL, 0, NULL, NULL);
|
= WideCharToMultiByte(CP_UTF8, 0, ws.c_str(), static_cast<int>(ws.size()), nullptr, 0, nullptr, nullptr);
|
||||||
string s(size_needed, 0);
|
std::string s(size_needed, 0);
|
||||||
WideCharToMultiByte(CP_UTF8, 0, &ws[0], (int)ws.size(), &s[0], size_needed, NULL, NULL);
|
WideCharToMultiByte(CP_UTF8, 0, ws.c_str(), static_cast<int>(ws.size()), &s[0], size_needed, nullptr, nullptr);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
string GB2312ToUtf8(const char *gb2312)
|
std::string gb2312_to_utf8(const char *gb2312)
|
||||||
{
|
{
|
||||||
int size_needed = 0;
|
if (!gb2312) return "";
|
||||||
|
|
||||||
size_needed = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
|
int size_needed = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, nullptr, 0);
|
||||||
wstring ws(size_needed, 0);
|
std::wstring ws(size_needed, 0);
|
||||||
MultiByteToWideChar(CP_ACP, 0, gb2312, -1, &ws[0], size_needed);
|
MultiByteToWideChar(CP_ACP, 0, gb2312, -1, &ws[0], size_needed);
|
||||||
|
|
||||||
size_needed = WideCharToMultiByte(CP_UTF8, 0, &ws[0], -1, NULL, 0, NULL, NULL);
|
size_needed = WideCharToMultiByte(CP_UTF8, 0, ws.c_str(), -1, nullptr, 0, nullptr, nullptr);
|
||||||
string s(size_needed, 0);
|
std::string s(size_needed, 0);
|
||||||
WideCharToMultiByte(CP_UTF8, 0, &ws[0], -1, &s[0], size_needed, NULL, NULL);
|
WideCharToMultiByte(CP_UTF8, 0, ws.c_str(), -1, &s[0], size_needed, nullptr, nullptr);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int GetWeChatPath(wchar_t *path)
|
DWORD get_wechat_pid()
|
||||||
{
|
{
|
||||||
int ret = -1;
|
DWORD pid = 0;
|
||||||
HKEY hKey = NULL;
|
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||||
// HKEY_CURRENT_USER\Software\Tencent\WeChat InstallPath = xx
|
if (hSnapshot == INVALID_HANDLE_VALUE) return 0;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT64 verMS = pVerInfo->dwFileVersionMS;
|
|
||||||
UINT64 verLS = pVerInfo->dwFileVersionLS;
|
|
||||||
UINT64 major = HIWORD(verMS);
|
|
||||||
UINT64 minor = LOWORD(verMS);
|
|
||||||
UINT64 build = HIWORD(verLS);
|
|
||||||
UINT64 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD GetWeChatPid()
|
|
||||||
{
|
|
||||||
DWORD pid = 0;
|
|
||||||
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
||||||
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
|
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
|
||||||
while (Process32Next(hSnapshot, &pe32)) {
|
while (Process32Next(hSnapshot, &pe32)) {
|
||||||
wstring strProcess = pe32.szExeFile;
|
if (std::wstring(pe32.szExeFile) == WECHATEXE) {
|
||||||
if (strProcess == WECHAREXE) {
|
|
||||||
pid = pe32.th32ProcessID;
|
pid = pe32.th32ProcessID;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -180,52 +70,20 @@ DWORD GetWeChatPid()
|
|||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class WindowsArchiture { x32, x64 };
|
int open_wechat(DWORD *pid)
|
||||||
static WindowsArchiture GetWindowsArchitecture()
|
|
||||||
{
|
{
|
||||||
#ifdef _WIN64
|
*pid = get_wechat_pid();
|
||||||
return WindowsArchiture::x64;
|
if (*pid) return ERROR_SUCCESS;
|
||||||
#else
|
|
||||||
return WindowsArchiture::x32;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL IsProcessX64(DWORD pid)
|
WCHAR path[MAX_PATH] = { 0 };
|
||||||
{
|
if (GetModuleFileNameW(nullptr, path, MAX_PATH) == 0) {
|
||||||
BOOL isWow64 = false;
|
return GetLastError();
|
||||||
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pid);
|
|
||||||
if (!hProcess)
|
|
||||||
return false;
|
|
||||||
BOOL result = IsWow64Process(hProcess, &isWow64);
|
|
||||||
CloseHandle(hProcess);
|
|
||||||
if (!result)
|
|
||||||
return false;
|
|
||||||
if (isWow64)
|
|
||||||
return false;
|
|
||||||
else if (GetWindowsArchitecture() == WindowsArchiture::x32)
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int OpenWeChat(DWORD *pid)
|
|
||||||
{
|
|
||||||
*pid = GetWeChatPid();
|
|
||||||
if (*pid) {
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = -1;
|
|
||||||
STARTUPINFO si = { sizeof(si) };
|
STARTUPINFO si = { sizeof(si) };
|
||||||
WCHAR Path[MAX_PATH] = { 0 };
|
|
||||||
PROCESS_INFORMATION pi = { 0 };
|
PROCESS_INFORMATION pi = { 0 };
|
||||||
|
|
||||||
ret = GetWeChatPath(Path);
|
if (!CreateProcessW(nullptr, path, nullptr, nullptr, FALSE, CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi)) {
|
||||||
if (ERROR_SUCCESS != ret) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CreateProcess(NULL, Path, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
|
|
||||||
return GetLastError();
|
return GetLastError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,115 +91,153 @@ int OpenWeChat(DWORD *pid)
|
|||||||
CloseHandle(pi.hProcess);
|
CloseHandle(pi.hProcess);
|
||||||
|
|
||||||
*pid = pi.dwProcessId;
|
*pid = pi.dwProcessId;
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetWstringByAddress(UINT64 addr, wchar_t *buffer, UINT64 buffer_size)
|
static std::optional<std::string> get_wechat_win_dll_path()
|
||||||
{
|
{
|
||||||
size_t strLength = GET_DWORD(addr + 8);
|
char path[MAX_PATH] = { 0 };
|
||||||
if (strLength == 0) {
|
if (GetWeChatPath(path) != ERROR_SUCCESS) {
|
||||||
return 0;
|
return std::nullopt;
|
||||||
} else if (strLength > buffer_size) {
|
|
||||||
strLength = buffer_size - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wmemcpy_s(buffer, strLength + 1, GET_WSTRING(addr), strLength + 1);
|
PathRemoveFileSpecA(path);
|
||||||
|
PathAppendA(path, WECHATWINDLL);
|
||||||
|
|
||||||
return strLength;
|
if (!PathFileExistsA(path)) {
|
||||||
|
// 微信 3.7+ 版本增加了一层目录
|
||||||
|
PathRemoveFileSpecA(path);
|
||||||
|
_finddata_t findData;
|
||||||
|
std::string dir = std::string(path) + "\\[*.*";
|
||||||
|
intptr_t handle = _findfirst(dir.c_str(), &findData);
|
||||||
|
if (handle == -1) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
_findclose(handle);
|
||||||
|
|
||||||
|
std::string dllPath = std::string(path) + "\\" + findData.name + "\\" + WECHATWINDLL;
|
||||||
|
return dllPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::string(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
string GetStringByAddress(UINT64 addr)
|
static std::optional<std::string> get_file_version(const std::string &filePath)
|
||||||
{
|
{
|
||||||
size_t strLength = GET_DWORD(addr + 8);
|
if (filePath.empty() || !PathFileExistsA(filePath.c_str())) {
|
||||||
return Wstring2String(wstring(GET_WSTRING(addr), strLength));
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD handle = 0;
|
||||||
|
DWORD size = GetFileVersionInfoSizeA(filePath.c_str(), &handle);
|
||||||
|
if (size == 0) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<BYTE> data(size);
|
||||||
|
if (!GetFileVersionInfoA(filePath.c_str(), 0, size, data.data())) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
VS_FIXEDFILEINFO *verInfo = nullptr;
|
||||||
|
UINT len = 0;
|
||||||
|
if (!VerQueryValueA(data.data(), "\\", reinterpret_cast<void **>(&verInfo), &len) || len == 0) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
char version[32];
|
||||||
|
StringCbPrintfA(version, sizeof(version), "%d.%d.%d.%d", HIWORD(verInfo->dwFileVersionMS),
|
||||||
|
LOWORD(verInfo->dwFileVersionMS), HIWORD(verInfo->dwFileVersionLS),
|
||||||
|
LOWORD(verInfo->dwFileVersionLS));
|
||||||
|
|
||||||
|
return std::string(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
string GetStringByStrAddr(UINT64 addr)
|
std::string get_wechat_version()
|
||||||
{
|
{
|
||||||
size_t strLength = GET_DWORD(addr + 8);
|
std::string version = "";
|
||||||
return strLength ? string(GET_STRING(addr), strLength) : string();
|
|
||||||
|
auto dllPath = get_wechat_win_dll_path();
|
||||||
|
if (!dllPath) {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
version = get_file_version(*dllPath);
|
||||||
|
return version ? version : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
string GetStringByWstrAddr(UINT64 addr)
|
uint32_t get_memory_int_by_address(HANDLE hProcess, uint64_t addr)
|
||||||
{
|
{
|
||||||
size_t strLength = GET_DWORD(addr + 8);
|
uint32_t value = 0;
|
||||||
return strLength ? Wstring2String(wstring(GET_WSTRING(addr), strLength)) : string();
|
if (!addr || !hProcess) return value;
|
||||||
}
|
|
||||||
|
|
||||||
UINT32 GetMemoryIntByAddress(HANDLE hProcess, UINT64 addr)
|
|
||||||
{
|
|
||||||
UINT32 value = 0;
|
|
||||||
|
|
||||||
unsigned char data[4] = { 0 };
|
unsigned char data[4] = { 0 };
|
||||||
if (ReadProcessMemory(hProcess, (LPVOID)addr, data, 4, 0)) {
|
if (ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(addr), data, sizeof(data), nullptr)) {
|
||||||
value = data[0] & 0xFF;
|
value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
||||||
value |= ((data[1] << 8) & 0xFF00);
|
|
||||||
value |= ((data[2] << 16) & 0xFF0000);
|
|
||||||
value |= ((data[3] << 24) & 0xFF000000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring GetUnicodeInfoByAddress(HANDLE hProcess, UINT64 address)
|
std::wstring get_unicode_info_by_address(HANDLE hProcess, uint64_t address)
|
||||||
{
|
{
|
||||||
wstring value = L"";
|
if (!hProcess || !address) return L"";
|
||||||
|
|
||||||
UINT64 strAddress = GetMemoryIntByAddress(hProcess, address);
|
uint64_t str_address = get_memory_int_by_address(hProcess, address);
|
||||||
UINT64 strLen = GetMemoryIntByAddress(hProcess, address + 0x4);
|
uint64_t str_len = get_memory_int_by_address(hProcess, address + 0x4);
|
||||||
if (strLen > 500)
|
if (str_len > 500) return L"";
|
||||||
return value;
|
|
||||||
|
|
||||||
wchar_t cValue[500] = { 0 };
|
wchar_t cValue[500] = { 0 };
|
||||||
memset(cValue, 0, sizeof(cValue) / sizeof(wchar_t));
|
if (ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(str_address), cValue, (str_len + 1) * sizeof(wchar_t),
|
||||||
if (ReadProcessMemory(hProcess, (LPVOID)strAddress, cValue, (strLen + 1) * 2, 0)) {
|
nullptr)) {
|
||||||
value = wstring(cValue);
|
return std::wstring(cValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return L"";
|
||||||
}
|
}
|
||||||
|
|
||||||
void DbgMsg(const char *zcFormat, ...)
|
void dbg_msg(const char *format, ...)
|
||||||
{
|
{
|
||||||
// initialize use of the variable argument array
|
if (!format) return;
|
||||||
va_list vaArgs;
|
|
||||||
va_start(vaArgs, zcFormat);
|
|
||||||
|
|
||||||
// reliably acquire the size
|
va_list args;
|
||||||
// from a copy of the variable argument array
|
va_start(args, format);
|
||||||
// and a functionally reliable call to mock the formatting
|
|
||||||
va_list vaArgsCopy;
|
|
||||||
va_copy(vaArgsCopy, vaArgs);
|
|
||||||
const int iLen = std::vsnprintf(NULL, 0, zcFormat, vaArgsCopy);
|
|
||||||
va_end(vaArgsCopy);
|
|
||||||
|
|
||||||
// return a formatted string without risking memory mismanagement
|
va_list args_copy;
|
||||||
// and without assuming any compiler or platform specific behavior
|
va_copy(args_copy, args);
|
||||||
std::vector<char> zc(iLen + 1);
|
int len = vsnprintf(nullptr, 0, format, args_copy);
|
||||||
std::vsnprintf(zc.data(), zc.size(), zcFormat, vaArgs);
|
va_end(args_copy);
|
||||||
va_end(vaArgs);
|
|
||||||
std::string strText(zc.data(), iLen);
|
|
||||||
|
|
||||||
OutputDebugStringA(strText.c_str());
|
std::vector<char> buffer(len + 1);
|
||||||
|
vsnprintf(buffer.data(), buffer.size(), format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
OutputDebugStringA(buffer.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
WxString *NewWxStringFromStr(const string &str) { return NewWxStringFromWstr(String2Wstring(str)); }
|
std::unique_ptr<WxString> new_wx_string(const char *str)
|
||||||
|
|
||||||
WxString *NewWxStringFromWstr(const wstring &ws)
|
|
||||||
{
|
{
|
||||||
WxString *p = (WxString *)HeapAlloc(GetProcessHeap(), 0, sizeof(WxString));
|
return new_wx_string(str ? std::string(str) : std::string());
|
||||||
wchar_t *pWstring = (wchar_t *)HeapAlloc(GetProcessHeap(), 0, (ws.size() + 1) * 2);
|
}
|
||||||
if (p == NULL || pWstring == NULL) {
|
|
||||||
LOG_ERROR("Out of Memory...");
|
std::unique_ptr<WxString> new_wx_string(const std::string &str) { return std::make_unique<WxString>(s2w(str)); }
|
||||||
return NULL;
|
|
||||||
|
std::unique_ptr<WxString> new_wx_string(const wchar_t *wstr)
|
||||||
|
{
|
||||||
|
return new_wx_string(wstr ? std::wstring(wstr) : std::wstring());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<WxString> new_wx_string(const std::wstring &wstr) { return std::make_unique<WxString>(wstr); }
|
||||||
|
|
||||||
|
std::vector<WxString> parse_wxids(const std::string &wxids)
|
||||||
|
{
|
||||||
|
std::vector<WxString> wx_members;
|
||||||
|
std::wstringstream wss(s2w(wxids));
|
||||||
|
std::wstring wstr;
|
||||||
|
while (getline(wss, wstr, L',')) {
|
||||||
|
wx_members.emplace_back(wstr);
|
||||||
}
|
}
|
||||||
|
return wx_members;
|
||||||
wmemcpy(pWstring, ws.c_str(), ws.size() + 1);
|
|
||||||
p->wptr = pWstring;
|
|
||||||
p->size = (DWORD)ws.size();
|
|
||||||
p->capacity = (DWORD)ws.size();
|
|
||||||
p->ptr = 0;
|
|
||||||
p->clen = 0;
|
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace util
|
||||||
|
@ -1,41 +1,81 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "spy_types.h"
|
#include "spy_types.h"
|
||||||
|
|
||||||
#define WECHAREXE L"WeChat.exe"
|
namespace util
|
||||||
#define WECHATWINDLL L"WeChatWin.dll"
|
{
|
||||||
#define WCFSDKDLL L"sdk.dll"
|
|
||||||
#define WCFSPYDLL L"spy.dll"
|
|
||||||
#define WCFSPYDLL_DEBUG L"spy_debug.dll"
|
|
||||||
|
|
||||||
#define GET_UINT64(addr) ((UINT64) * (UINT64 *)(addr))
|
inline constexpr wchar_t WECHATEXE[] = L"WeChat.exe";
|
||||||
#define GET_DWORD(addr) ((DWORD) * (UINT64 *)(addr))
|
inline constexpr wchar_t WECHATWINDLL[] = L"WeChatWin.dll";
|
||||||
#define GET_QWORD(addr) ((UINT64) * (UINT64 *)(addr))
|
inline constexpr wchar_t WCFSDKDLL[] = L"sdk.dll";
|
||||||
#define GET_STRING(addr) ((CHAR *)(*(UINT64 *)(addr)))
|
inline constexpr wchar_t WCFSPYDLL[] = L"spy.dll";
|
||||||
#define GET_WSTRING(addr) ((WCHAR *)(*(UINT64 *)(addr)))
|
inline constexpr wchar_t WCFSPYDLL_DEBUG[] = L"spy_debug.dll";
|
||||||
#define GET_STRING_FROM_P(addr) ((CHAR *)(addr))
|
|
||||||
#define GET_WSTRING_FROM_P(addr) ((WCHAR *)(addr))
|
|
||||||
|
|
||||||
typedef struct PortPath {
|
struct PortPath {
|
||||||
int port;
|
int port;
|
||||||
char path[MAX_PATH];
|
char path[MAX_PATH];
|
||||||
} PortPath_t;
|
};
|
||||||
|
|
||||||
DWORD GetWeChatPid();
|
inline DWORD get_dword(uint64_t addr) { return addr ? *reinterpret_cast<DWORD *>(addr) : 0; }
|
||||||
BOOL IsProcessX64(DWORD pid);
|
inline QWORD get_qword(uint64_t addr) { return addr ? *reinterpret_cast<QWORD *>(addr) : 0; }
|
||||||
int OpenWeChat(DWORD *pid);
|
inline uint64_t get_uint64(uint64_t addr) { return addr ? *reinterpret_cast<uint64_t *>(addr) : 0; }
|
||||||
int GetWeChatVersion(wchar_t *version);
|
inline std::string get_p_string(uint64_t addr) { return addr ? std::string(reinterpret_cast<const char *>(addr)) : ""; }
|
||||||
size_t GetWstringByAddress(UINT64 address, wchar_t *buffer, UINT64 buffer_size);
|
inline std::string get_p_string(uint64_t addr, size_t len)
|
||||||
UINT32 GetMemoryIntByAddress(HANDLE hProcess, UINT64 address);
|
{
|
||||||
std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, UINT64 address);
|
return addr ? std::string(reinterpret_cast<const char *>(addr), len) : "";
|
||||||
std::wstring String2Wstring(std::string s);
|
}
|
||||||
std::string Wstring2String(std::wstring ws);
|
inline std::wstring get_p_wstring(uint64_t addr)
|
||||||
std::string GB2312ToUtf8(const char *gb2312);
|
{
|
||||||
std::string GetStringByAddress(UINT64 address);
|
return addr ? std::wstring(reinterpret_cast<const wchar_t *>(addr)) : L"";
|
||||||
std::string GetStringByStrAddr(UINT64 addr);
|
}
|
||||||
std::string GetStringByWstrAddr(UINT64 addr);
|
inline std::wstring get_p_wstring(uint64_t addr, size_t len)
|
||||||
void DbgMsg(const char *zcFormat, ...);
|
{
|
||||||
WxString *NewWxStringFromStr(const std::string &str);
|
return addr ? std::wstring(reinterpret_cast<const wchar_t *>(addr), len) : L"";
|
||||||
WxString *NewWxStringFromWstr(const std::wstring &ws);
|
}
|
||||||
|
inline std::string get_pp_string(uint64_t addr)
|
||||||
|
{
|
||||||
|
if (!addr) return "";
|
||||||
|
|
||||||
|
const char *ptr = *reinterpret_cast<const char **>(addr);
|
||||||
|
return (ptr && *ptr) ? std::string(ptr) : "";
|
||||||
|
}
|
||||||
|
inline std::wstring get_pp_wstring(uint64_t addr)
|
||||||
|
{
|
||||||
|
if (!addr) return L"";
|
||||||
|
|
||||||
|
const wchar_t *ptr = *reinterpret_cast<const wchar_t **>(addr);
|
||||||
|
return (ptr && *ptr) ? std::wstring(ptr) : "";
|
||||||
|
}
|
||||||
|
inline std::string get_pp_len_string(uint64_t addr)
|
||||||
|
{
|
||||||
|
size_t len = get_dword(addr + 8);
|
||||||
|
return (addr && len) ? std::string(*reinterpret_cast<const char **>(addr), len) : L"";
|
||||||
|
}
|
||||||
|
inline std::wstring get_pp_len_wstring(uint64_t addr)
|
||||||
|
{
|
||||||
|
size_t len = get_dword(addr + 8);
|
||||||
|
return (addr && len) ? std::wstring(*reinterpret_cast<const wchar_t **>(addr), len) : L"";
|
||||||
|
}
|
||||||
|
inline std::string get_str_by_wstr_addr(uint64_t addr) { return w2s(get_pp_len_wstring(addr)); }
|
||||||
|
|
||||||
|
DWORD get_wechat_pid();
|
||||||
|
int open_wechat(DWORD *pid);
|
||||||
|
std::string get_wechat_version();
|
||||||
|
uint32_t get_memory_int_by_address(HANDLE hProcess, uint64_t addr);
|
||||||
|
std::wstring get_unicode_info_by_address(HANDLE hProcess, uint64_t addr);
|
||||||
|
std::wstring s2w(const std::string &s);
|
||||||
|
std::string w2s(const std::wstring &ws);
|
||||||
|
std::string gb2312_to_utf8(const char *gb2312);
|
||||||
|
void dbg_msg(const char *format, ...);
|
||||||
|
|
||||||
|
std::unique_ptr<WxString> new_wx_string(const char *str);
|
||||||
|
std::unique_ptr<WxString> new_wx_string(const wchar_t *wstr);
|
||||||
|
std::unique_ptr<WxString> new_wx_string(const std::string &str);
|
||||||
|
std::unique_ptr<WxString> new_wx_string(const std::wstring &wstr);
|
||||||
|
|
||||||
|
std::vector<WxString> parse_wxids(const std::string &wxids);
|
||||||
|
|
||||||
|
} // namespace util
|
||||||
|
@ -80,7 +80,7 @@ HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase)
|
|||||||
WaitForSingleObject(hThread, -1);
|
WaitForSingleObject(hThread, -1);
|
||||||
CloseHandle(hThread);
|
CloseHandle(hThread);
|
||||||
|
|
||||||
*injectedBase = GetTargetModuleBase(hProcess, filesystem::path(Wstring2String(dllPath)).filename().string());
|
*injectedBase = GetTargetModuleBase(hProcess, filesystem::path(util::w2s(dllPath)).filename().string());
|
||||||
|
|
||||||
VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
|
VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE);
|
||||||
// CloseHandle(hProcess); // Close when exit
|
// CloseHandle(hProcess); // Close when exit
|
||||||
|
@ -28,7 +28,7 @@ static std::optional<std::wstring> ReadDisclaimerText(const char *filePath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||||
return String2Wstring(content);
|
return util::s2w(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ShowDisclaimer()
|
static bool ShowDisclaimer()
|
||||||
@ -94,7 +94,7 @@ int WxInitSDK(bool debug, int port)
|
|||||||
return ERROR_FILE_NOT_FOUND; // DLL 文件路径不存在
|
return ERROR_FILE_NOT_FOUND; // DLL 文件路径不存在
|
||||||
}
|
}
|
||||||
|
|
||||||
status = OpenWeChat(&wcPid);
|
status = util::open_wechat(&wcPid);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
MessageBox(NULL, L"打开微信失败", L"WxInitSDK", 0);
|
MessageBox(NULL, L"打开微信失败", L"WxInitSDK", 0);
|
||||||
return status;
|
return status;
|
||||||
|
@ -24,7 +24,7 @@ using invite_member_to_chatroom_t = QWORD (*)(QWORD, QWORD, QWORD, QWORD);
|
|||||||
static vector<WxString> parse_wxids(const string &wxids)
|
static vector<WxString> parse_wxids(const string &wxids)
|
||||||
{
|
{
|
||||||
vector<WxString> wx_members;
|
vector<WxString> wx_members;
|
||||||
wstringstream wss(String2Wstring(wxids));
|
wstringstream wss(util::s2w(wxids));
|
||||||
wstring wstr;
|
wstring wstr;
|
||||||
while (getline(wss, wstr, L',')) {
|
while (getline(wss, wstr, L',')) {
|
||||||
wx_members.emplace_back(wstr);
|
wx_members.emplace_back(wstr);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma execution_character_set("utf-8")
|
#pragma execution_character_set("utf-8")
|
||||||
|
|
||||||
#include "contact_mgmt.h"
|
#include "contact_mgmt.h"
|
||||||
|
|
||||||
#include "fill_response.h"
|
#include "fill_response.h"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "pb_util.h"
|
#include "pb_util.h"
|
||||||
@ -55,7 +56,7 @@ static string get_cnt_string(QWORD start, QWORD end, const uint8_t *feat, size_t
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return Wstring2String(wstring(GET_WSTRING_FROM_P(pfeat + FEAT_LEN + 4), lfeat));
|
return util::w2s(util::get_p_wstring(pfeat + FEAT_LEN + 4, lfeat));
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<RpcContact_t> get_contacts()
|
vector<RpcContact_t> get_contacts()
|
||||||
@ -80,10 +81,10 @@ vector<RpcContact_t> get_contacts()
|
|||||||
QWORD pbin = GET_QWORD(pstart + OS_CONTACT_BIN);
|
QWORD pbin = GET_QWORD(pstart + OS_CONTACT_BIN);
|
||||||
QWORD lenbin = GET_DWORD(pstart + OS_CONTACT_BIN_LEN);
|
QWORD lenbin = GET_DWORD(pstart + OS_CONTACT_BIN_LEN);
|
||||||
|
|
||||||
cnt.wxid = GetStringByWstrAddr(pstart + OS_CONTACT_WXID);
|
cnt.wxid = util::get_str_by_wstr_addr(pstart + OS_CONTACT_WXID);
|
||||||
cnt.code = GetStringByWstrAddr(pstart + OS_CONTACT_CODE);
|
cnt.code = util::get_str_by_wstr_addr(pstart + OS_CONTACT_CODE);
|
||||||
cnt.remark = GetStringByWstrAddr(pstart + OS_CONTACT_REMARK);
|
cnt.remark = util::get_str_by_wstr_addr(pstart + OS_CONTACT_REMARK);
|
||||||
cnt.name = GetStringByWstrAddr(pstart + OS_CONTACT_NAME);
|
cnt.name = util::get_str_by_wstr_addr(pstart + OS_CONTACT_NAME);
|
||||||
|
|
||||||
cnt.country = get_cnt_string(pbin, pbin + lenbin, FEAT_COUNTRY, FEAT_LEN);
|
cnt.country = get_cnt_string(pbin, pbin + lenbin, FEAT_COUNTRY, FEAT_LEN);
|
||||||
cnt.province = get_cnt_string(pbin, pbin + lenbin, FEAT_PROVINCE, FEAT_LEN);
|
cnt.province = get_cnt_string(pbin, pbin + lenbin, FEAT_PROVINCE, FEAT_LEN);
|
||||||
@ -112,8 +113,8 @@ int accept_new_friend(const std::string &v3, const std::string &v4, int scene)
|
|||||||
|
|
||||||
LOG_DEBUG("\nv3: {}\nv4: {}\nscene: {}", v3, v4, scene);
|
LOG_DEBUG("\nv3: {}\nv4: {}\nscene: {}", v3, v4, scene);
|
||||||
|
|
||||||
wstring ws_v3 = String2Wstring(v3);
|
wstring ws_v3 = util::s2w(v3);
|
||||||
wstring ws_v4 = String2Wstring(v4);
|
wstring ws_v4 = util::s2w(v4);
|
||||||
WxString wx_v3(ws_v3);
|
WxString wx_v3(ws_v3);
|
||||||
WxString wx_v4(ws_v4);
|
WxString wx_v4(ws_v4);
|
||||||
|
|
||||||
@ -154,7 +155,7 @@ RpcContact_t get_contact_by_wxid(const string &wxid)
|
|||||||
RpcContact_t contact;
|
RpcContact_t contact;
|
||||||
#if 0
|
#if 0
|
||||||
char buff[0x440] = { 0 };
|
char buff[0x440] = { 0 };
|
||||||
wstring ws_wxid = String2Wstring(wxid);
|
wstring ws_wxid = util::s2w(wxid);
|
||||||
WxString pri(ws_wxid);
|
WxString pri(ws_wxid);
|
||||||
|
|
||||||
DWORD contact_mgr_addr = g_WeChatWinDllAddr + 0x75A4A0;
|
DWORD contact_mgr_addr = g_WeChatWinDllAddr + 0x75A4A0;
|
||||||
@ -176,9 +177,9 @@ RpcContact_t get_contact_by_wxid(const string &wxid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
contact.wxid = wxid;
|
contact.wxid = wxid;
|
||||||
contact.code = GetStringByWstrAddr(reinterpret_cast<DWORD>(buff) + g_WxCalls.contact.wxCode);
|
contact.code = util::get_str_by_wstr_addr(reinterpret_cast<DWORD>(buff) + g_WxCalls.contact.wxCode);
|
||||||
contact.remark = GetStringByWstrAddr(reinterpret_cast<DWORD>(buff) + g_WxCalls.contact.wxRemark);
|
contact.remark = util::get_str_by_wstr_addr(reinterpret_cast<DWORD>(buff) + g_WxCalls.contact.wxRemark);
|
||||||
contact.name = GetStringByWstrAddr(reinterpret_cast<DWORD>(buff) + g_WxCalls.contact.wxName);
|
contact.name = util::get_str_by_wstr_addr(reinterpret_cast<DWORD>(buff) + g_WxCalls.contact.wxName);
|
||||||
contact.gender = GET_DWORD(reinterpret_cast<DWORD>(buff) + 0x148);
|
contact.gender = GET_DWORD(reinterpret_cast<DWORD>(buff) + 0x148);
|
||||||
|
|
||||||
__asm {
|
__asm {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include <algorithm>
|
#include "exec_sql.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
#include "exec_sql.h"
|
|
||||||
#include "fill_response.h"
|
#include "fill_response.h"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "pb_util.h"
|
#include "pb_util.h"
|
||||||
@ -29,7 +30,7 @@ static db_map_t db_map;
|
|||||||
static void get_db_handle(QWORD base, QWORD offset)
|
static void get_db_handle(QWORD base, QWORD offset)
|
||||||
{
|
{
|
||||||
auto *wsp = reinterpret_cast<wchar_t *>(*(QWORD *)(base + offset + OFFSET_DB_NAME));
|
auto *wsp = reinterpret_cast<wchar_t *>(*(QWORD *)(base + offset + OFFSET_DB_NAME));
|
||||||
std::string dbname = Wstring2String(std::wstring(wsp));
|
std::string dbname = util::w2s(std::wstring(wsp));
|
||||||
db_map[dbname] = GET_QWORD(base + offset);
|
db_map[dbname] = GET_QWORD(base + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,12 +42,12 @@ static void get_msg_db_handle(QWORD msg_mgr_addr)
|
|||||||
QWORD db_addr = GET_QWORD(p_start + i * 0x08);
|
QWORD db_addr = GET_QWORD(p_start + i * 0x08);
|
||||||
if (db_addr) {
|
if (db_addr) {
|
||||||
// MSGi.db
|
// MSGi.db
|
||||||
std::string dbname = Wstring2String(GET_WSTRING(db_addr));
|
std::string dbname = util::w2s(get_pp_wstring(db_addr));
|
||||||
db_map[dbname] = GET_QWORD(db_addr + 0x78);
|
db_map[dbname] = GET_QWORD(db_addr + 0x78);
|
||||||
|
|
||||||
// MediaMsgi.db
|
// MediaMsgi.db
|
||||||
QWORD mmdb_addr = GET_QWORD(db_addr + 0x20);
|
QWORD mmdb_addr = GET_QWORD(db_addr + 0x20);
|
||||||
std::string mmdbname = Wstring2String(GET_WSTRING(mmdb_addr + 0x78));
|
std::string mmdbname = util::w2s(get_pp_wstring(mmdb_addr + 0x78));
|
||||||
db_map[mmdbname] = GET_QWORD(mmdb_addr + 0x50);
|
db_map[mmdbname] = GET_QWORD(mmdb_addr + 0x50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,7 +200,7 @@ int get_local_id_and_dbidx(uint64_t id, uint64_t *local_id, uint32_t *db_idx)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dbname = Wstring2String(GET_WSTRING(db_addr));
|
std::string dbname = util::w2s(get_pp_wstring(db_addr));
|
||||||
db_map[dbname] = GET_QWORD(db_addr + 0x78);
|
db_map[dbname] = GET_QWORD(db_addr + 0x78);
|
||||||
|
|
||||||
std::string sql = "SELECT localId FROM MSG WHERE MsgSvrID=" + std::to_string(id) + ";";
|
std::string sql = "SELECT localId FROM MSG WHERE MsgSvrID=" + std::to_string(id) + ";";
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
#pragma warning(disable : 4244)
|
#pragma warning(disable : 4244)
|
||||||
|
#include "funcs.h"
|
||||||
|
|
||||||
#include "framework.h"
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "framework.h"
|
||||||
|
|
||||||
#include "codec.h"
|
#include "codec.h"
|
||||||
#include "exec_sql.h"
|
#include "exec_sql.h"
|
||||||
#include "funcs.h"
|
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "receive_msg.h"
|
#include "receive_msg.h"
|
||||||
#include "spy_types.h"
|
#include "spy_types.h"
|
||||||
@ -342,7 +343,7 @@ OcrResult_t GetOcrResult(string path)
|
|||||||
QWORD *pUnk1 = &unk1;
|
QWORD *pUnk1 = &unk1;
|
||||||
QWORD *pUnk2 = &unk2;
|
QWORD *pUnk2 = &unk2;
|
||||||
// 路径分隔符有要求,必须为 `\`
|
// 路径分隔符有要求,必须为 `\`
|
||||||
wstring wsPath = String2Wstring(fs::path(path).make_preferred().string());
|
wstring wsPath = util::s2w(fs::path(path).make_preferred().string());
|
||||||
WxString wxPath(wsPath);
|
WxString wxPath(wsPath);
|
||||||
vector<QWORD> *pv = (vector<QWORD> *)HeapAlloc(GetProcessHeap(), 0, 0x20);
|
vector<QWORD> *pv = (vector<QWORD> *)HeapAlloc(GetProcessHeap(), 0, 0x20);
|
||||||
RawVector_t *pRv = (RawVector_t *)pv;
|
RawVector_t *pRv = (RawVector_t *)pv;
|
||||||
@ -358,7 +359,7 @@ OcrResult_t GetOcrResult(string path)
|
|||||||
QWORD header = GET_QWORD(buff);
|
QWORD header = GET_QWORD(buff);
|
||||||
for (QWORD i = 0; i < count; i++) {
|
for (QWORD i = 0; i < count; i++) {
|
||||||
QWORD content = GET_QWORD(header);
|
QWORD content = GET_QWORD(header);
|
||||||
ret.result += Wstring2String(GET_WSTRING(content + 0x28));
|
ret.result += util::w2s(get_pp_wstring(content + 0x28));
|
||||||
ret.result += "\n";
|
ret.result += "\n";
|
||||||
header = content;
|
header = content;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
|
#include "receive_msg.h"
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
@ -6,7 +7,6 @@
|
|||||||
#include "framework.h"
|
#include "framework.h"
|
||||||
|
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "receive_msg.h"
|
|
||||||
#include "user_info.h"
|
#include "user_info.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@ -42,20 +42,21 @@ QWORD MessageHandler::DispatchMsg(QWORD arg1, QWORD arg2)
|
|||||||
wxMsg.type = GET_DWORD(arg2 + OS_RECV_MSG_TYPE);
|
wxMsg.type = GET_DWORD(arg2 + OS_RECV_MSG_TYPE);
|
||||||
wxMsg.is_self = GET_DWORD(arg2 + OS_RECV_MSG_SELF);
|
wxMsg.is_self = GET_DWORD(arg2 + OS_RECV_MSG_SELF);
|
||||||
wxMsg.ts = GET_DWORD(arg2 + OS_RECV_MSG_TS);
|
wxMsg.ts = GET_DWORD(arg2 + OS_RECV_MSG_TS);
|
||||||
wxMsg.content = GetStringByWstrAddr(arg2 + OS_RECV_MSG_CONTENT);
|
wxMsg.content = util::get_str_by_wstr_addr(arg2 + OS_RECV_MSG_CONTENT);
|
||||||
wxMsg.sign = GetStringByWstrAddr(arg2 + OS_RECV_MSG_SIGN);
|
wxMsg.sign = util::get_str_by_wstr_addr(arg2 + OS_RECV_MSG_SIGN);
|
||||||
wxMsg.xml = GetStringByWstrAddr(arg2 + OS_RECV_MSG_XML);
|
wxMsg.xml = util::get_str_by_wstr_addr(arg2 + OS_RECV_MSG_XML);
|
||||||
wxMsg.roomid = GetStringByWstrAddr(arg2 + OS_RECV_MSG_ROOMID);
|
wxMsg.roomid = util::get_str_by_wstr_addr(arg2 + OS_RECV_MSG_ROOMID);
|
||||||
|
|
||||||
if (wxMsg.roomid.find("@chatroom") != std::string::npos) {
|
if (wxMsg.roomid.find("@chatroom") != std::string::npos) {
|
||||||
wxMsg.is_group = true;
|
wxMsg.is_group = true;
|
||||||
wxMsg.sender = wxMsg.is_self ? user_info::get_self_wxid() : GetStringByWstrAddr(arg2 + OS_RECV_MSG_WXID);
|
wxMsg.sender
|
||||||
|
= wxMsg.is_self ? user_info::get_self_wxid() : util::get_str_by_wstr_addr(arg2 + OS_RECV_MSG_WXID);
|
||||||
} else {
|
} else {
|
||||||
wxMsg.is_group = false;
|
wxMsg.is_group = false;
|
||||||
wxMsg.sender = wxMsg.is_self ? user_info::get_self_wxid() : wxMsg.roomid;
|
wxMsg.sender = wxMsg.is_self ? user_info::get_self_wxid() : wxMsg.roomid;
|
||||||
}
|
}
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
LOG_ERROR(GB2312ToUtf8(e.what()));
|
LOG_ERROR(util::gb2312_to_utf8(e.what()));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -77,7 +78,7 @@ QWORD MessageHandler::PrintWxLog(QWORD a1, QWORD a2, QWORD a3, QWORD a4, QWORD a
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("【WX】\n{}", GB2312ToUtf8((char *)p));
|
LOG_INFO("【WX】\n{}", util::gb2312_to_utf8((char *)p));
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,9 +100,9 @@ void MessageHandler::DispatchPyq(QWORD arg1, QWORD arg2, QWORD arg3)
|
|||||||
wxMsg.is_group = false;
|
wxMsg.is_group = false;
|
||||||
wxMsg.id = GET_QWORD(startAddr);
|
wxMsg.id = GET_QWORD(startAddr);
|
||||||
wxMsg.ts = GET_DWORD(startAddr + OS_PYQ_MSG_TS);
|
wxMsg.ts = GET_DWORD(startAddr + OS_PYQ_MSG_TS);
|
||||||
wxMsg.xml = GetStringByWstrAddr(startAddr + OS_PYQ_MSG_XML);
|
wxMsg.xml = util::get_str_by_wstr_addr(startAddr + OS_PYQ_MSG_XML);
|
||||||
wxMsg.sender = GetStringByWstrAddr(startAddr + OS_PYQ_MSG_SENDER);
|
wxMsg.sender = util::get_str_by_wstr_addr(startAddr + OS_PYQ_MSG_SENDER);
|
||||||
wxMsg.content = GetStringByWstrAddr(startAddr + OS_PYQ_MSG_CONTENT);
|
wxMsg.content = util::get_str_by_wstr_addr(startAddr + OS_PYQ_MSG_CONTENT);
|
||||||
|
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(handler.mutex_);
|
std::unique_lock<std::mutex> lock(handler.mutex_);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma warning(disable : 4251)
|
#pragma warning(disable : 4251)
|
||||||
|
|
||||||
|
#include "rpc_server.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
@ -26,7 +28,6 @@
|
|||||||
#include "pb_types.h"
|
#include "pb_types.h"
|
||||||
#include "pb_util.h"
|
#include "pb_util.h"
|
||||||
#include "receive_msg.h"
|
#include "receive_msg.h"
|
||||||
#include "rpc_server.h"
|
|
||||||
#include "send_msg.h"
|
#include "send_msg.h"
|
||||||
#include "spy.h"
|
#include "spy.h"
|
||||||
#include "spy_types.h"
|
#include "spy_types.h"
|
||||||
@ -158,7 +159,7 @@ static bool func_send_img(char *path, char *receiver, uint8_t *out, size_t *len)
|
|||||||
if ((path == NULL) || (receiver == NULL)) {
|
if ((path == NULL) || (receiver == NULL)) {
|
||||||
LOG_ERROR("Empty path or receiver.");
|
LOG_ERROR("Empty path or receiver.");
|
||||||
rsp.msg.status = -1;
|
rsp.msg.status = -1;
|
||||||
} else if (!fs::exists(String2Wstring(path))) {
|
} else if (!fs::exists(util::s2w(path))) {
|
||||||
LOG_ERROR("Path does not exist: {}", path);
|
LOG_ERROR("Path does not exist: {}", path);
|
||||||
rsp.msg.status = -2;
|
rsp.msg.status = -2;
|
||||||
} else {
|
} else {
|
||||||
@ -174,7 +175,7 @@ static bool func_send_file(char *path, char *receiver, uint8_t *out, size_t *len
|
|||||||
if ((path == nullptr) || (receiver == nullptr)) {
|
if ((path == nullptr) || (receiver == nullptr)) {
|
||||||
LOG_ERROR("Empty path or receiver.");
|
LOG_ERROR("Empty path or receiver.");
|
||||||
rsp.msg.status = -1;
|
rsp.msg.status = -1;
|
||||||
} else if (!fs::exists(String2Wstring(path))) {
|
} else if (!fs::exists(util::s2w(path))) {
|
||||||
LOG_ERROR("Path does not exist: {}", path);
|
LOG_ERROR("Path does not exist: {}", path);
|
||||||
rsp.msg.status = -2;
|
rsp.msg.status = -2;
|
||||||
} else {
|
} else {
|
||||||
@ -685,7 +686,7 @@ static int RunRpcServer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
LOG_ERROR(GB2312ToUtf8(e.what()));
|
LOG_ERROR(util::gb2312_to_utf8(e.what()));
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
LOG_ERROR("Unknow exception.");
|
LOG_ERROR("Unknow exception.");
|
||||||
}
|
}
|
||||||
|
@ -56,13 +56,13 @@ std::unique_ptr<WxString> SendMsgManager::new_wx_string(const char *str)
|
|||||||
}
|
}
|
||||||
std::unique_ptr<WxString> SendMsgManager::new_wx_string(const std::string &str)
|
std::unique_ptr<WxString> SendMsgManager::new_wx_string(const std::string &str)
|
||||||
{
|
{
|
||||||
return std::make_unique<WxString>(String2Wstring(str));
|
return std::make_unique<WxString>(util::s2w(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<WxString> SendMsgManager::parse_wxids(const string &wxids)
|
std::vector<WxString> SendMsgManager::parse_wxids(const string &wxids)
|
||||||
{
|
{
|
||||||
vector<WxString> wx_members;
|
vector<WxString> wx_members;
|
||||||
wstringstream wss(String2Wstring(wxids));
|
wstringstream wss(util::s2w(wxids));
|
||||||
wstring wstr;
|
wstring wstr;
|
||||||
while (getline(wss, wstr, L',')) {
|
while (getline(wss, wstr, L',')) {
|
||||||
wx_members.emplace_back(wstr);
|
wx_members.emplace_back(wstr);
|
||||||
|
@ -1,44 +1,37 @@
|
|||||||
#include <filesystem>
|
#include "spy.h"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "rpc_server.h"
|
#include "rpc_server.h"
|
||||||
#include "spy.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
constexpr std::string_view SUPPORT_VERSION = "3.9.11.25";
|
||||||
|
|
||||||
UINT64 g_WeChatWinDllAddr = 0;
|
UINT64 g_WeChatWinDllAddr = 0;
|
||||||
|
|
||||||
static bool IsWxVersionMatched(const wchar_t *version)
|
|
||||||
{
|
|
||||||
if (wcscmp(version, SUPPORT_VERSION) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitSpy(LPVOID args)
|
void InitSpy(LPVOID args)
|
||||||
{
|
{
|
||||||
|
auto *pp = static_cast<PortPath_t *>(args);
|
||||||
wchar_t version[16] = { 0 };
|
|
||||||
PortPath_t *pp = (PortPath_t *)args;
|
|
||||||
|
|
||||||
Log::InitLogger(pp->path);
|
Log::InitLogger(pp->path);
|
||||||
g_WeChatWinDllAddr = (UINT64)GetModuleHandle(L"WeChatWin.dll"); // 获取wechatWin模块地址
|
if (auto dll_addr = GetModuleHandle(L"WeChatWin.dll")) {
|
||||||
if (g_WeChatWinDllAddr == 0) {
|
g_WeChatWinDllAddr = reinterpret_cast<UINT64>(dll_addr);
|
||||||
LOG_ERROR("获取 wechatWin.dll 模块地址失败");
|
} else {
|
||||||
|
LOG_ERROR("获取 WeChatWin.dll 模块地址失败");
|
||||||
return; // TODO: 退出进程,避免后面操作失败
|
return; // TODO: 退出进程,避免后面操作失败
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetWeChatVersion(version)) { // 获取微信版本
|
std::string version = util::get_wechat_version();
|
||||||
LOG_ERROR("获取微信版本失败");
|
std::string msg = "WCF 支持版本: " + SUPPORT_VERSION + ",当前版本: " + version;
|
||||||
return;
|
if (version != SUPPORT_VERSION) {
|
||||||
}
|
LOG_ERROR(msg);
|
||||||
LOG_INFO("WeChat version: {}", Wstring2String(version).c_str());
|
MessageBoxA(NULL, msg.c_str(), "错误", MB_ICONERROR);
|
||||||
if (!IsWxVersionMatched(version)) {
|
|
||||||
LOG_ERROR("不支持当前版本");
|
|
||||||
MessageBox(NULL, L"不支持当前版本", L"错误", 0);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_INFO(msg);
|
||||||
RpcStartServer(pp->port);
|
RpcStartServer(pp->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,5 @@
|
|||||||
|
|
||||||
#include "framework.h"
|
#include "framework.h"
|
||||||
|
|
||||||
#define SUPPORT_VERSION L"3.9.11.25"
|
|
||||||
|
|
||||||
void InitSpy(int port);
|
void InitSpy(int port);
|
||||||
void CleanupSpy();
|
void CleanupSpy();
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#include <filesystem>
|
#include "user_info.h"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "fill_response.h"
|
#include "fill_response.h"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "user_info.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
extern UINT64 g_WeChatWinDllAddr;
|
extern UINT64 g_WeChatWinDllAddr;
|
||||||
@ -15,14 +16,13 @@ namespace user_info
|
|||||||
#define OS_USER_NAME 0x595C3D8
|
#define OS_USER_NAME 0x595C3D8
|
||||||
#define OS_USER_MOBILE 0x595C318
|
#define OS_USER_MOBILE 0x595C318
|
||||||
|
|
||||||
std::string
|
std::string get_home_path()
|
||||||
get_home_path()
|
|
||||||
{
|
{
|
||||||
static std::once_flag flag;
|
static std::once_flag flag;
|
||||||
static std::string home_path;
|
static std::string home_path;
|
||||||
|
|
||||||
std::call_once(flag, [] {
|
std::call_once(flag, [] {
|
||||||
std::string path = Wstring2String(GET_WSTRING(g_WeChatWinDllAddr + OS_USER_HOME)) + "\\WeChat Files\\";
|
std::string path = util::w2s(get_pp_wstring(g_WeChatWinDllAddr + OS_USER_HOME)) + "\\WeChat Files\\";
|
||||||
home_path = std::filesystem::absolute(path).string();
|
home_path = std::filesystem::absolute(path).string();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -39,9 +39,9 @@ std::string get_self_wxid()
|
|||||||
try {
|
try {
|
||||||
wxid_type = GET_UINT64(g_WeChatWinDllAddr + OS_USER_WXID + 0x18);
|
wxid_type = GET_UINT64(g_WeChatWinDllAddr + OS_USER_WXID + 0x18);
|
||||||
if (wxid_type == 0xF) {
|
if (wxid_type == 0xF) {
|
||||||
wxid = GET_STRING_FROM_P(g_WeChatWinDllAddr + OS_USER_WXID);
|
wxid = util::get_p_string(g_WeChatWinDllAddr + OS_USER_WXID);
|
||||||
} else {
|
} else {
|
||||||
wxid = GET_STRING(g_WeChatWinDllAddr + OS_USER_WXID);
|
wxid = util::get_pp_string(g_WeChatWinDllAddr + OS_USER_WXID);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
@ -59,10 +59,10 @@ UserInfo_t get_user_info()
|
|||||||
ui.wxid = get_self_wxid();
|
ui.wxid = get_self_wxid();
|
||||||
|
|
||||||
UINT64 name_type = GET_UINT64(g_WeChatWinDllAddr + OS_USER_NAME + 0x18);
|
UINT64 name_type = GET_UINT64(g_WeChatWinDllAddr + OS_USER_NAME + 0x18);
|
||||||
ui.name = (name_type == 0xF) ? GET_STRING_FROM_P(g_WeChatWinDllAddr + OS_USER_NAME)
|
ui.name = (name_type == 0xF) ? util::get_p_string(g_WeChatWinDllAddr + OS_USER_NAME)
|
||||||
: GET_STRING(g_WeChatWinDllAddr + OS_USER_NAME);
|
: util::get_pp_string(g_WeChatWinDllAddr + OS_USER_NAME);
|
||||||
|
|
||||||
ui.mobile = GET_STRING_FROM_P(g_WeChatWinDllAddr + OS_USER_MOBILE);
|
ui.mobile = util::get_p_string(g_WeChatWinDllAddr + OS_USER_MOBILE);
|
||||||
ui.home = get_home_path();
|
ui.home = get_home_path();
|
||||||
|
|
||||||
return ui;
|
return ui;
|
||||||
|
Loading…
Reference in New Issue
Block a user