diff --git a/WeChatFerry/com/log.hpp b/WeChatFerry/com/log.hpp index 4f30b27..4be5e76 100644 --- a/WeChatFerry/com/log.hpp +++ b/WeChatFerry/com/log.hpp @@ -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, DEFAULT_LOGGER_MAX_FILES); } 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; } diff --git a/WeChatFerry/com/util.cpp b/WeChatFerry/com/util.cpp index 0134592..21b0039 100644 --- a/WeChatFerry/com/util.cpp +++ b/WeChatFerry/com/util.cpp @@ -1,177 +1,67 @@ -#include "Shlwapi.h" -#include "framework.h" +#include "util.h" + #include #include +#include #include #include #include #include #include +#include "framework.h" + #include "log.hpp" -#include "util.h" #pragma comment(lib, "shlwapi") #pragma comment(lib, "Version.lib") -using namespace std; - -wstring String2Wstring(string s) +namespace util { - if (s.empty()) - return wstring(); - int size_needed = MultiByteToWideChar(CP_UTF8, 0, &s[0], (int)s.size(), NULL, 0); - wstring ws(size_needed, 0); - MultiByteToWideChar(CP_UTF8, 0, &s[0], (int)s.size(), &ws[0], size_needed); + +std::wstring s2w(const std::string &s) +{ + if (s.empty()) return std::wstring(); + int size_needed = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), static_cast(s.size()), nullptr, 0); + std::wstring ws(size_needed, 0); + MultiByteToWideChar(CP_UTF8, 0, s.c_str(), static_cast(s.size()), &ws[0], size_needed); return ws; } -string Wstring2String(wstring ws) +std::string w2s(const std::wstring &ws) { - if (ws.empty()) - return string(); - int size_needed = WideCharToMultiByte(CP_UTF8, 0, &ws[0], (int)ws.size(), NULL, 0, NULL, NULL); - string s(size_needed, 0); - WideCharToMultiByte(CP_UTF8, 0, &ws[0], (int)ws.size(), &s[0], size_needed, NULL, NULL); + if (ws.empty()) return std::string(); + int size_needed + = WideCharToMultiByte(CP_UTF8, 0, ws.c_str(), static_cast(ws.size()), nullptr, 0, nullptr, nullptr); + std::string s(size_needed, 0); + WideCharToMultiByte(CP_UTF8, 0, ws.c_str(), static_cast(ws.size()), &s[0], size_needed, nullptr, nullptr); 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); - wstring ws(size_needed, 0); + int size_needed = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, nullptr, 0); + std::wstring ws(size_needed, 0); MultiByteToWideChar(CP_ACP, 0, gb2312, -1, &ws[0], size_needed); - size_needed = WideCharToMultiByte(CP_UTF8, 0, &ws[0], -1, NULL, 0, NULL, NULL); - string s(size_needed, 0); - WideCharToMultiByte(CP_UTF8, 0, &ws[0], -1, &s[0], size_needed, NULL, NULL); + size_needed = WideCharToMultiByte(CP_UTF8, 0, ws.c_str(), -1, nullptr, 0, nullptr, nullptr); + std::string s(size_needed, 0); + WideCharToMultiByte(CP_UTF8, 0, ws.c_str(), -1, &s[0], size_needed, nullptr, nullptr); return s; } -static int GetWeChatPath(wchar_t *path) +DWORD get_wechat_pid() { - 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 pid = 0; + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapshot == INVALID_HANDLE_VALUE) return 0; - 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) }; while (Process32Next(hSnapshot, &pe32)) { - wstring strProcess = pe32.szExeFile; - if (strProcess == WECHAREXE) { + if (std::wstring(pe32.szExeFile) == WECHATEXE) { pid = pe32.th32ProcessID; break; } @@ -180,52 +70,20 @@ DWORD GetWeChatPid() return pid; } -enum class WindowsArchiture { x32, x64 }; -static WindowsArchiture GetWindowsArchitecture() +int open_wechat(DWORD *pid) { -#ifdef _WIN64 - return WindowsArchiture::x64; -#else - return WindowsArchiture::x32; -#endif -} + *pid = get_wechat_pid(); + if (*pid) return ERROR_SUCCESS; -BOOL IsProcessX64(DWORD pid) -{ - BOOL isWow64 = false; - 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; + WCHAR path[MAX_PATH] = { 0 }; + if (GetModuleFileNameW(nullptr, path, MAX_PATH) == 0) { + return GetLastError(); } - 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)) { + if (!CreateProcessW(nullptr, path, nullptr, nullptr, FALSE, CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi)) { return GetLastError(); } @@ -233,115 +91,153 @@ int OpenWeChat(DWORD *pid) CloseHandle(pi.hProcess); *pid = pi.dwProcessId; - return ERROR_SUCCESS; } -size_t GetWstringByAddress(UINT64 addr, wchar_t *buffer, UINT64 buffer_size) +static std::optional get_wechat_win_dll_path() { - size_t strLength = GET_DWORD(addr + 8); - if (strLength == 0) { - return 0; - } else if (strLength > buffer_size) { - strLength = buffer_size - 1; + char path[MAX_PATH] = { 0 }; + if (GetWeChatPath(path) != ERROR_SUCCESS) { + return std::nullopt; } - 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 get_file_version(const std::string &filePath) { - size_t strLength = GET_DWORD(addr + 8); - return Wstring2String(wstring(GET_WSTRING(addr), strLength)); + if (filePath.empty() || !PathFileExistsA(filePath.c_str())) { + return std::nullopt; + } + + DWORD handle = 0; + DWORD size = GetFileVersionInfoSizeA(filePath.c_str(), &handle); + if (size == 0) { + return std::nullopt; + } + + std::vector 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(&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); - return strLength ? string(GET_STRING(addr), strLength) : string(); + std::string version = ""; + + 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); - return strLength ? Wstring2String(wstring(GET_WSTRING(addr), strLength)) : string(); -} - -UINT32 GetMemoryIntByAddress(HANDLE hProcess, UINT64 addr) -{ - UINT32 value = 0; + uint32_t value = 0; + if (!addr || !hProcess) return value; unsigned char data[4] = { 0 }; - if (ReadProcessMemory(hProcess, (LPVOID)addr, data, 4, 0)) { - value = data[0] & 0xFF; - value |= ((data[1] << 8) & 0xFF00); - value |= ((data[2] << 16) & 0xFF0000); - value |= ((data[3] << 24) & 0xFF000000); + if (ReadProcessMemory(hProcess, reinterpret_cast(addr), data, sizeof(data), nullptr)) { + value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); } 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 strLen = GetMemoryIntByAddress(hProcess, address + 0x4); - if (strLen > 500) - return value; + uint64_t str_address = get_memory_int_by_address(hProcess, address); + uint64_t str_len = get_memory_int_by_address(hProcess, address + 0x4); + if (str_len > 500) return L""; 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); + if (ReadProcessMemory(hProcess, reinterpret_cast(str_address), cValue, (str_len + 1) * sizeof(wchar_t), + nullptr)) { + 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 - va_list vaArgs; - va_start(vaArgs, zcFormat); + if (!format) return; - // reliably acquire the size - // from a copy of the variable argument array - // 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); + va_list args; + va_start(args, format); - // return a formatted string without risking memory mismanagement - // and without assuming any compiler or platform specific behavior - std::vector zc(iLen + 1); - std::vsnprintf(zc.data(), zc.size(), zcFormat, vaArgs); - va_end(vaArgs); - std::string strText(zc.data(), iLen); + va_list args_copy; + va_copy(args_copy, args); + int len = vsnprintf(nullptr, 0, format, args_copy); + va_end(args_copy); - OutputDebugStringA(strText.c_str()); + std::vector 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)); } - -WxString *NewWxStringFromWstr(const wstring &ws) +std::unique_ptr new_wx_string(const char *str) { - WxString *p = (WxString *)HeapAlloc(GetProcessHeap(), 0, sizeof(WxString)); - wchar_t *pWstring = (wchar_t *)HeapAlloc(GetProcessHeap(), 0, (ws.size() + 1) * 2); - if (p == NULL || pWstring == NULL) { - LOG_ERROR("Out of Memory..."); - return NULL; + return new_wx_string(str ? std::string(str) : std::string()); +} + +std::unique_ptr new_wx_string(const std::string &str) { return std::make_unique(s2w(str)); } + +std::unique_ptr new_wx_string(const wchar_t *wstr) +{ + return new_wx_string(wstr ? std::wstring(wstr) : std::wstring()); +} + +std::unique_ptr new_wx_string(const std::wstring &wstr) { return std::make_unique(wstr); } + +std::vector parse_wxids(const std::string &wxids) +{ + std::vector wx_members; + std::wstringstream wss(s2w(wxids)); + std::wstring wstr; + while (getline(wss, wstr, L',')) { + wx_members.emplace_back(wstr); } - - 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; + return wx_members; } + +} // namespace util diff --git a/WeChatFerry/com/util.h b/WeChatFerry/com/util.h index 8f252df..9169ddd 100644 --- a/WeChatFerry/com/util.h +++ b/WeChatFerry/com/util.h @@ -1,41 +1,81 @@ #pragma once +#include #include #include "spy_types.h" -#define WECHAREXE L"WeChat.exe" -#define WECHATWINDLL L"WeChatWin.dll" -#define WCFSDKDLL L"sdk.dll" -#define WCFSPYDLL L"spy.dll" -#define WCFSPYDLL_DEBUG L"spy_debug.dll" +namespace util +{ -#define GET_UINT64(addr) ((UINT64) * (UINT64 *)(addr)) -#define GET_DWORD(addr) ((DWORD) * (UINT64 *)(addr)) -#define GET_QWORD(addr) ((UINT64) * (UINT64 *)(addr)) -#define GET_STRING(addr) ((CHAR *)(*(UINT64 *)(addr))) -#define GET_WSTRING(addr) ((WCHAR *)(*(UINT64 *)(addr))) -#define GET_STRING_FROM_P(addr) ((CHAR *)(addr)) -#define GET_WSTRING_FROM_P(addr) ((WCHAR *)(addr)) +inline constexpr wchar_t WECHATEXE[] = L"WeChat.exe"; +inline constexpr wchar_t WECHATWINDLL[] = L"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"; -typedef struct PortPath { +struct PortPath { int port; char path[MAX_PATH]; -} PortPath_t; +}; -DWORD GetWeChatPid(); -BOOL IsProcessX64(DWORD pid); -int OpenWeChat(DWORD *pid); -int GetWeChatVersion(wchar_t *version); -size_t GetWstringByAddress(UINT64 address, wchar_t *buffer, UINT64 buffer_size); -UINT32 GetMemoryIntByAddress(HANDLE hProcess, UINT64 address); -std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, UINT64 address); -std::wstring String2Wstring(std::string s); -std::string Wstring2String(std::wstring ws); -std::string GB2312ToUtf8(const char *gb2312); -std::string GetStringByAddress(UINT64 address); -std::string GetStringByStrAddr(UINT64 addr); -std::string GetStringByWstrAddr(UINT64 addr); -void DbgMsg(const char *zcFormat, ...); -WxString *NewWxStringFromStr(const std::string &str); -WxString *NewWxStringFromWstr(const std::wstring &ws); +inline DWORD get_dword(uint64_t addr) { return addr ? *reinterpret_cast(addr) : 0; } +inline QWORD get_qword(uint64_t addr) { return addr ? *reinterpret_cast(addr) : 0; } +inline uint64_t get_uint64(uint64_t addr) { return addr ? *reinterpret_cast(addr) : 0; } +inline std::string get_p_string(uint64_t addr) { return addr ? std::string(reinterpret_cast(addr)) : ""; } +inline std::string get_p_string(uint64_t addr, size_t len) +{ + return addr ? std::string(reinterpret_cast(addr), len) : ""; +} +inline std::wstring get_p_wstring(uint64_t addr) +{ + return addr ? std::wstring(reinterpret_cast(addr)) : L""; +} +inline std::wstring get_p_wstring(uint64_t addr, size_t len) +{ + return addr ? std::wstring(reinterpret_cast(addr), len) : L""; +} +inline std::string get_pp_string(uint64_t addr) +{ + if (!addr) return ""; + + const char *ptr = *reinterpret_cast(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(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(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(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 new_wx_string(const char *str); +std::unique_ptr new_wx_string(const wchar_t *wstr); +std::unique_ptr new_wx_string(const std::string &str); +std::unique_ptr new_wx_string(const std::wstring &wstr); + +std::vector parse_wxids(const std::string &wxids); + +} // namespace util diff --git a/WeChatFerry/sdk/injector.cpp b/WeChatFerry/sdk/injector.cpp index cc06298..975faa9 100644 --- a/WeChatFerry/sdk/injector.cpp +++ b/WeChatFerry/sdk/injector.cpp @@ -80,7 +80,7 @@ HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase) WaitForSingleObject(hThread, -1); 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); // CloseHandle(hProcess); // Close when exit diff --git a/WeChatFerry/sdk/sdk.cpp b/WeChatFerry/sdk/sdk.cpp index 8b1c790..fca3b0f 100644 --- a/WeChatFerry/sdk/sdk.cpp +++ b/WeChatFerry/sdk/sdk.cpp @@ -28,7 +28,7 @@ static std::optional ReadDisclaimerText(const char *filePath) } std::string content((std::istreambuf_iterator(file)), std::istreambuf_iterator()); - return String2Wstring(content); + return util::s2w(content); } static bool ShowDisclaimer() @@ -94,7 +94,7 @@ int WxInitSDK(bool debug, int port) return ERROR_FILE_NOT_FOUND; // DLL 文件路径不存在 } - status = OpenWeChat(&wcPid); + status = util::open_wechat(&wcPid); if (status != 0) { MessageBox(NULL, L"打开微信失败", L"WxInitSDK", 0); return status; diff --git a/WeChatFerry/spy/chatroom_mgmt.cpp b/WeChatFerry/spy/chatroom_mgmt.cpp index db496b3..589fd52 100644 --- a/WeChatFerry/spy/chatroom_mgmt.cpp +++ b/WeChatFerry/spy/chatroom_mgmt.cpp @@ -24,7 +24,7 @@ using invite_member_to_chatroom_t = QWORD (*)(QWORD, QWORD, QWORD, QWORD); static vector parse_wxids(const string &wxids) { vector wx_members; - wstringstream wss(String2Wstring(wxids)); + wstringstream wss(util::s2w(wxids)); wstring wstr; while (getline(wss, wstr, L',')) { wx_members.emplace_back(wstr); diff --git a/WeChatFerry/spy/contact_mgmt.cpp b/WeChatFerry/spy/contact_mgmt.cpp index 192b20f..85c5740 100644 --- a/WeChatFerry/spy/contact_mgmt.cpp +++ b/WeChatFerry/spy/contact_mgmt.cpp @@ -1,6 +1,7 @@ #pragma execution_character_set("utf-8") #include "contact_mgmt.h" + #include "fill_response.h" #include "log.hpp" #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 Wstring2String(wstring(GET_WSTRING_FROM_P(pfeat + FEAT_LEN + 4), lfeat)); + return util::w2s(util::get_p_wstring(pfeat + FEAT_LEN + 4, lfeat)); } vector get_contacts() @@ -80,10 +81,10 @@ vector get_contacts() QWORD pbin = GET_QWORD(pstart + OS_CONTACT_BIN); QWORD lenbin = GET_DWORD(pstart + OS_CONTACT_BIN_LEN); - cnt.wxid = GetStringByWstrAddr(pstart + OS_CONTACT_WXID); - cnt.code = GetStringByWstrAddr(pstart + OS_CONTACT_CODE); - cnt.remark = GetStringByWstrAddr(pstart + OS_CONTACT_REMARK); - cnt.name = GetStringByWstrAddr(pstart + OS_CONTACT_NAME); + cnt.wxid = util::get_str_by_wstr_addr(pstart + OS_CONTACT_WXID); + cnt.code = util::get_str_by_wstr_addr(pstart + OS_CONTACT_CODE); + cnt.remark = util::get_str_by_wstr_addr(pstart + OS_CONTACT_REMARK); + 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.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); - wstring ws_v3 = String2Wstring(v3); - wstring ws_v4 = String2Wstring(v4); + wstring ws_v3 = util::s2w(v3); + wstring ws_v4 = util::s2w(v4); WxString wx_v3(ws_v3); WxString wx_v4(ws_v4); @@ -154,7 +155,7 @@ RpcContact_t get_contact_by_wxid(const string &wxid) RpcContact_t contact; #if 0 char buff[0x440] = { 0 }; - wstring ws_wxid = String2Wstring(wxid); + wstring ws_wxid = util::s2w(wxid); WxString pri(ws_wxid); DWORD contact_mgr_addr = g_WeChatWinDllAddr + 0x75A4A0; @@ -176,9 +177,9 @@ RpcContact_t get_contact_by_wxid(const string &wxid) } contact.wxid = wxid; - contact.code = GetStringByWstrAddr(reinterpret_cast(buff) + g_WxCalls.contact.wxCode); - contact.remark = GetStringByWstrAddr(reinterpret_cast(buff) + g_WxCalls.contact.wxRemark); - contact.name = GetStringByWstrAddr(reinterpret_cast(buff) + g_WxCalls.contact.wxName); + contact.code = util::get_str_by_wstr_addr(reinterpret_cast(buff) + g_WxCalls.contact.wxCode); + contact.remark = util::get_str_by_wstr_addr(reinterpret_cast(buff) + g_WxCalls.contact.wxRemark); + contact.name = util::get_str_by_wstr_addr(reinterpret_cast(buff) + g_WxCalls.contact.wxName); contact.gender = GET_DWORD(reinterpret_cast(buff) + 0x148); __asm { diff --git a/WeChatFerry/spy/exec_sql.cpp b/WeChatFerry/spy/exec_sql.cpp index 0ed9982..89678c1 100644 --- a/WeChatFerry/spy/exec_sql.cpp +++ b/WeChatFerry/spy/exec_sql.cpp @@ -1,7 +1,8 @@ -#include +#include "exec_sql.h" + +#include #include -#include "exec_sql.h" #include "fill_response.h" #include "log.hpp" #include "pb_util.h" @@ -29,7 +30,7 @@ static db_map_t db_map; static void get_db_handle(QWORD base, QWORD offset) { auto *wsp = reinterpret_cast(*(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); } @@ -41,12 +42,12 @@ static void get_msg_db_handle(QWORD msg_mgr_addr) QWORD db_addr = GET_QWORD(p_start + i * 0x08); if (db_addr) { // 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); // MediaMsgi.db 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); } } @@ -199,7 +200,7 @@ int get_local_id_and_dbidx(uint64_t id, uint64_t *local_id, uint32_t *db_idx) 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); std::string sql = "SELECT localId FROM MSG WHERE MsgSvrID=" + std::to_string(id) + ";"; diff --git a/WeChatFerry/spy/funcs.cpp b/WeChatFerry/spy/funcs.cpp index 0ec2959..94b8b64 100644 --- a/WeChatFerry/spy/funcs.cpp +++ b/WeChatFerry/spy/funcs.cpp @@ -1,12 +1,13 @@ #pragma warning(disable : 4244) +#include "funcs.h" -#include "framework.h" #include #include +#include "framework.h" + #include "codec.h" #include "exec_sql.h" -#include "funcs.h" #include "log.hpp" #include "receive_msg.h" #include "spy_types.h" @@ -342,7 +343,7 @@ OcrResult_t GetOcrResult(string path) QWORD *pUnk1 = &unk1; 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); vector *pv = (vector *)HeapAlloc(GetProcessHeap(), 0, 0x20); RawVector_t *pRv = (RawVector_t *)pv; @@ -358,7 +359,7 @@ OcrResult_t GetOcrResult(string path) QWORD header = GET_QWORD(buff); for (QWORD i = 0; i < count; i++) { QWORD content = GET_QWORD(header); - ret.result += Wstring2String(GET_WSTRING(content + 0x28)); + ret.result += util::w2s(get_pp_wstring(content + 0x28)); ret.result += "\n"; header = content; } diff --git a/WeChatFerry/spy/receive_msg.cpp b/WeChatFerry/spy/receive_msg.cpp index 5becce8..6ce84a2 100644 --- a/WeChatFerry/spy/receive_msg.cpp +++ b/WeChatFerry/spy/receive_msg.cpp @@ -1,4 +1,5 @@ - +#include "receive_msg.h" + #include #include #include @@ -6,7 +7,6 @@ #include "framework.h" #include "log.hpp" -#include "receive_msg.h" #include "user_info.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.is_self = GET_DWORD(arg2 + OS_RECV_MSG_SELF); wxMsg.ts = GET_DWORD(arg2 + OS_RECV_MSG_TS); - wxMsg.content = GetStringByWstrAddr(arg2 + OS_RECV_MSG_CONTENT); - wxMsg.sign = GetStringByWstrAddr(arg2 + OS_RECV_MSG_SIGN); - wxMsg.xml = GetStringByWstrAddr(arg2 + OS_RECV_MSG_XML); - wxMsg.roomid = GetStringByWstrAddr(arg2 + OS_RECV_MSG_ROOMID); + wxMsg.content = util::get_str_by_wstr_addr(arg2 + OS_RECV_MSG_CONTENT); + wxMsg.sign = util::get_str_by_wstr_addr(arg2 + OS_RECV_MSG_SIGN); + wxMsg.xml = util::get_str_by_wstr_addr(arg2 + OS_RECV_MSG_XML); + wxMsg.roomid = util::get_str_by_wstr_addr(arg2 + OS_RECV_MSG_ROOMID); if (wxMsg.roomid.find("@chatroom") != std::string::npos) { 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 { wxMsg.is_group = false; wxMsg.sender = wxMsg.is_self ? user_info::get_self_wxid() : wxMsg.roomid; } } 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; } - LOG_INFO("【WX】\n{}", GB2312ToUtf8((char *)p)); + LOG_INFO("【WX】\n{}", util::gb2312_to_utf8((char *)p)); return p; } @@ -99,9 +100,9 @@ void MessageHandler::DispatchPyq(QWORD arg1, QWORD arg2, QWORD arg3) wxMsg.is_group = false; wxMsg.id = GET_QWORD(startAddr); wxMsg.ts = GET_DWORD(startAddr + OS_PYQ_MSG_TS); - wxMsg.xml = GetStringByWstrAddr(startAddr + OS_PYQ_MSG_XML); - wxMsg.sender = GetStringByWstrAddr(startAddr + OS_PYQ_MSG_SENDER); - wxMsg.content = GetStringByWstrAddr(startAddr + OS_PYQ_MSG_CONTENT); + wxMsg.xml = util::get_str_by_wstr_addr(startAddr + OS_PYQ_MSG_XML); + wxMsg.sender = util::get_str_by_wstr_addr(startAddr + OS_PYQ_MSG_SENDER); + wxMsg.content = util::get_str_by_wstr_addr(startAddr + OS_PYQ_MSG_CONTENT); { std::unique_lock lock(handler.mutex_); diff --git a/WeChatFerry/spy/rpc_server.cpp b/WeChatFerry/spy/rpc_server.cpp index f4419ac..111a0a1 100644 --- a/WeChatFerry/spy/rpc_server.cpp +++ b/WeChatFerry/spy/rpc_server.cpp @@ -1,5 +1,7 @@ #pragma warning(disable : 4251) +#include "rpc_server.h" + #include #include #include @@ -26,7 +28,6 @@ #include "pb_types.h" #include "pb_util.h" #include "receive_msg.h" -#include "rpc_server.h" #include "send_msg.h" #include "spy.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)) { LOG_ERROR("Empty path or receiver."); rsp.msg.status = -1; - } else if (!fs::exists(String2Wstring(path))) { + } else if (!fs::exists(util::s2w(path))) { LOG_ERROR("Path does not exist: {}", path); rsp.msg.status = -2; } 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)) { LOG_ERROR("Empty path or receiver."); rsp.msg.status = -1; - } else if (!fs::exists(String2Wstring(path))) { + } else if (!fs::exists(util::s2w(path))) { LOG_ERROR("Path does not exist: {}", path); rsp.msg.status = -2; } else { @@ -685,7 +686,7 @@ static int RunRpcServer() } } } catch (const std::exception &e) { - LOG_ERROR(GB2312ToUtf8(e.what())); + LOG_ERROR(util::gb2312_to_utf8(e.what())); } catch (...) { LOG_ERROR("Unknow exception."); } diff --git a/WeChatFerry/spy/send_msg.cpp b/WeChatFerry/spy/send_msg.cpp index 153f12a..1134cbd 100644 --- a/WeChatFerry/spy/send_msg.cpp +++ b/WeChatFerry/spy/send_msg.cpp @@ -56,13 +56,13 @@ std::unique_ptr SendMsgManager::new_wx_string(const char *str) } std::unique_ptr SendMsgManager::new_wx_string(const std::string &str) { - return std::make_unique(String2Wstring(str)); + return std::make_unique(util::s2w(str)); } std::vector SendMsgManager::parse_wxids(const string &wxids) { vector wx_members; - wstringstream wss(String2Wstring(wxids)); + wstringstream wss(util::s2w(wxids)); wstring wstr; while (getline(wss, wstr, L',')) { wx_members.emplace_back(wstr); diff --git a/WeChatFerry/spy/spy.cpp b/WeChatFerry/spy/spy.cpp index e179aa0..f78b65d 100644 --- a/WeChatFerry/spy/spy.cpp +++ b/WeChatFerry/spy/spy.cpp @@ -1,44 +1,37 @@ -#include +#include "spy.h" + +#include +#include #include "log.hpp" #include "rpc_server.h" -#include "spy.h" #include "util.h" +constexpr std::string_view SUPPORT_VERSION = "3.9.11.25"; + 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) { - - wchar_t version[16] = { 0 }; - PortPath_t *pp = (PortPath_t *)args; + auto *pp = static_cast(args); Log::InitLogger(pp->path); - g_WeChatWinDllAddr = (UINT64)GetModuleHandle(L"WeChatWin.dll"); // 获取wechatWin模块地址 - if (g_WeChatWinDllAddr == 0) { - LOG_ERROR("获取 wechatWin.dll 模块地址失败"); + if (auto dll_addr = GetModuleHandle(L"WeChatWin.dll")) { + g_WeChatWinDllAddr = reinterpret_cast(dll_addr); + } else { + LOG_ERROR("获取 WeChatWin.dll 模块地址失败"); return; // TODO: 退出进程,避免后面操作失败 } - if (!GetWeChatVersion(version)) { // 获取微信版本 - LOG_ERROR("获取微信版本失败"); - return; - } - LOG_INFO("WeChat version: {}", Wstring2String(version).c_str()); - if (!IsWxVersionMatched(version)) { - LOG_ERROR("不支持当前版本"); - MessageBox(NULL, L"不支持当前版本", L"错误", 0); + std::string version = util::get_wechat_version(); + std::string msg = "WCF 支持版本: " + SUPPORT_VERSION + ",当前版本: " + version; + if (version != SUPPORT_VERSION) { + LOG_ERROR(msg); + MessageBoxA(NULL, msg.c_str(), "错误", MB_ICONERROR); return; } + LOG_INFO(msg); RpcStartServer(pp->port); } diff --git a/WeChatFerry/spy/spy.h b/WeChatFerry/spy/spy.h index 525109a..3aa41dd 100644 --- a/WeChatFerry/spy/spy.h +++ b/WeChatFerry/spy/spy.h @@ -2,7 +2,5 @@ #include "framework.h" -#define SUPPORT_VERSION L"3.9.11.25" - void InitSpy(int port); void CleanupSpy(); diff --git a/WeChatFerry/spy/user_info.cpp b/WeChatFerry/spy/user_info.cpp index 6cf95b7..2515d44 100644 --- a/WeChatFerry/spy/user_info.cpp +++ b/WeChatFerry/spy/user_info.cpp @@ -1,9 +1,10 @@ -#include +#include "user_info.h" + +#include #include #include "fill_response.h" #include "log.hpp" -#include "user_info.h" #include "util.h" extern UINT64 g_WeChatWinDllAddr; @@ -15,14 +16,13 @@ namespace user_info #define OS_USER_NAME 0x595C3D8 #define OS_USER_MOBILE 0x595C318 - std::string - get_home_path() +std::string get_home_path() { static std::once_flag flag; static std::string home_path; 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(); }); @@ -39,9 +39,9 @@ std::string get_self_wxid() try { wxid_type = GET_UINT64(g_WeChatWinDllAddr + OS_USER_WXID + 0x18); 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 { - wxid = GET_STRING(g_WeChatWinDllAddr + OS_USER_WXID); + wxid = util::get_pp_string(g_WeChatWinDllAddr + OS_USER_WXID); } } catch (...) { @@ -59,10 +59,10 @@ UserInfo_t get_user_info() ui.wxid = get_self_wxid(); 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) - : GET_STRING(g_WeChatWinDllAddr + OS_USER_NAME); + ui.name = (name_type == 0xF) ? util::get_p_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(); return ui;