Refactoring
This commit is contained in:
parent
c96d85db30
commit
dc51b7b5a7
@ -2,14 +2,13 @@
|
|||||||
|
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <memory>
|
#include <optional>
|
||||||
#include <string.h>
|
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
#include <tlhelp32.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
#include "framework.h"
|
#include "framework.h"
|
||||||
|
#include <Shlwapi.h>
|
||||||
|
#include <tlhelp32.h>
|
||||||
|
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
|
|
||||||
@ -61,7 +60,7 @@ DWORD get_wechat_pid()
|
|||||||
|
|
||||||
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
|
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
|
||||||
while (Process32Next(hSnapshot, &pe32)) {
|
while (Process32Next(hSnapshot, &pe32)) {
|
||||||
if (std::wstring(pe32.szExeFile) == WECHATEXE) {
|
if (w2s(pe32.szExeFile) == WECHATEXE) {
|
||||||
pid = pe32.th32ProcessID;
|
pid = pe32.th32ProcessID;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -70,100 +69,125 @@ DWORD get_wechat_pid()
|
|||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
int open_wechat(DWORD *pid)
|
int open_wechat(DWORD &pid)
|
||||||
{
|
{
|
||||||
*pid = get_wechat_pid();
|
pid = get_wechat_pid();
|
||||||
if (*pid) return ERROR_SUCCESS;
|
if (pid != 0) {
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
WCHAR path[MAX_PATH] = { 0 };
|
auto wechat_path = util::get_wechat_path();
|
||||||
if (GetModuleFileNameW(nullptr, path, MAX_PATH) == 0) {
|
if (!wechat_path) {
|
||||||
return GetLastError();
|
LOG_ERROR("获取 WeChat 安装路径失败");
|
||||||
|
return ERROR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
STARTUPINFO si = { sizeof(si) };
|
STARTUPINFO si = { sizeof(si) };
|
||||||
PROCESS_INFORMATION pi = { 0 };
|
PROCESS_INFORMATION pi = {};
|
||||||
|
if (!CreateProcessA(wechat_path->c_str(), nullptr, nullptr, nullptr, FALSE, CREATE_NEW_CONSOLE, nullptr, nullptr,
|
||||||
if (!CreateProcessW(nullptr, path, nullptr, nullptr, FALSE, CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi)) {
|
&si, &pi)) {
|
||||||
return GetLastError();
|
return GetLastError();
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
CloseHandle(pi.hProcess);
|
CloseHandle(pi.hProcess);
|
||||||
|
|
||||||
*pid = pi.dwProcessId;
|
pid = pi.dwProcessId;
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::optional<std::string> get_wechat_win_dll_path()
|
std::optional<std::string> get_wechat_path()
|
||||||
{
|
{
|
||||||
char path[MAX_PATH] = { 0 };
|
HKEY hKey;
|
||||||
if (GetWeChatPath(path) != ERROR_SUCCESS) {
|
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Tencent\\WeChat", 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
|
||||||
|
LOG_ERROR("无法打开注册表项");
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
PathRemoveFileSpecA(path);
|
char path[MAX_PATH] = { 0 };
|
||||||
PathAppendA(path, WECHATWINDLL);
|
DWORD type = REG_SZ;
|
||||||
|
DWORD size = sizeof(path);
|
||||||
if (!PathFileExistsA(path)) {
|
if (RegQueryValueExA(hKey, "InstallPath", nullptr, &type, reinterpret_cast<LPBYTE>(path), &size) != ERROR_SUCCESS) {
|
||||||
// 微信 3.7+ 版本增加了一层目录
|
RegCloseKey(hKey);
|
||||||
PathRemoveFileSpecA(path);
|
LOG_ERROR("无法读取注册表中的 InstallPath");
|
||||||
_finddata_t findData;
|
return std::nullopt;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
RegCloseKey(hKey);
|
||||||
|
|
||||||
|
PathAppendA(path, WECHATEXE);
|
||||||
return std::string(path);
|
return std::string(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::optional<std::string> get_file_version(const std::string &filePath)
|
std::optional<std::string> get_wechat_win_dll_path()
|
||||||
{
|
{
|
||||||
if (filePath.empty() || !PathFileExistsA(filePath.c_str())) {
|
auto wechat_path = get_wechat_path();
|
||||||
|
if (!wechat_path) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD handle = 0;
|
std::string dll_path = *wechat_path;
|
||||||
DWORD size = GetFileVersionInfoSizeA(filePath.c_str(), &handle);
|
PathRemoveFileSpecA(dll_path.data());
|
||||||
|
PathAppendA(dll_path.data(), WECHATWINDLL);
|
||||||
|
|
||||||
|
if (PathFileExistsA(dll_path.c_str())) {
|
||||||
|
return dll_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 微信从(大约)3.7开始,增加了一层版本目录: [3.7.0.29]
|
||||||
|
PathRemoveFileSpecA(dll_path.data());
|
||||||
|
WIN32_FIND_DATAA find_data;
|
||||||
|
HANDLE hFind = FindFirstFileA((dll_path + "\\*.*").c_str(), &find_data);
|
||||||
|
if (hFind == INVALID_HANDLE_VALUE) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
FindClose(hFind);
|
||||||
|
|
||||||
|
std::string versioned_path = dll_path + "\\" + find_data.cFileName + WECHATWINDLL;
|
||||||
|
return PathFileExistsA(versioned_path.c_str()) ? std::optional<std::string>(versioned_path) : std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> get_file_version(const std::string &file_path)
|
||||||
|
{
|
||||||
|
if (!PathFileExistsA(file_path.c_str())) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD dummy = 0;
|
||||||
|
DWORD size = GetFileVersionInfoSizeA(file_path.c_str(), &dummy);
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<BYTE> data(size);
|
std::vector<BYTE> buffer(size);
|
||||||
if (!GetFileVersionInfoA(filePath.c_str(), 0, size, data.data())) {
|
if (!GetFileVersionInfoA(file_path.c_str(), 0, size, buffer.data())) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
VS_FIXEDFILEINFO *verInfo = nullptr;
|
VS_FIXEDFILEINFO *ver_info = nullptr;
|
||||||
UINT len = 0;
|
UINT ver_size = 0;
|
||||||
if (!VerQueryValueA(data.data(), "\\", reinterpret_cast<void **>(&verInfo), &len) || len == 0) {
|
if (!VerQueryValueA(buffer.data(), "\\", reinterpret_cast<LPVOID *>(&ver_info), &ver_size)) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
char version[32];
|
return fmt::format("{}.{}.{}.{}", HIWORD(ver_info->dwFileVersionMS), LOWORD(ver_info->dwFileVersionMS),
|
||||||
StringCbPrintfA(version, sizeof(version), "%d.%d.%d.%d", HIWORD(verInfo->dwFileVersionMS),
|
HIWORD(ver_info->dwFileVersionLS), LOWORD(ver_info->dwFileVersionLS));
|
||||||
LOWORD(verInfo->dwFileVersionMS), HIWORD(verInfo->dwFileVersionLS),
|
|
||||||
LOWORD(verInfo->dwFileVersionLS));
|
|
||||||
|
|
||||||
return std::string(version);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_wechat_version()
|
std::string get_wechat_version()
|
||||||
{
|
{
|
||||||
std::string version = "";
|
auto dll_path = get_wechat_win_dll_path();
|
||||||
|
if (!dll_path) {
|
||||||
auto dllPath = get_wechat_win_dll_path();
|
LOG_ERROR("无法获取 WeChatWin.dll 路径");
|
||||||
if (!dllPath) {
|
return "";
|
||||||
return version;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
version = get_file_version(*dllPath);
|
auto version = get_file_version(*dll_path);
|
||||||
return version ? version : "";
|
if (!version) {
|
||||||
|
LOG_ERROR("无法获取 WeChat 版本信息");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return *version;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t get_memory_int_by_address(HANDLE hProcess, uint64_t addr)
|
uint32_t get_memory_int_by_address(HANDLE hProcess, uint64_t addr)
|
||||||
@ -171,10 +195,7 @@ uint32_t get_memory_int_by_address(HANDLE hProcess, uint64_t addr)
|
|||||||
uint32_t value = 0;
|
uint32_t value = 0;
|
||||||
if (!addr || !hProcess) return value;
|
if (!addr || !hProcess) return value;
|
||||||
|
|
||||||
unsigned char data[4] = { 0 };
|
ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(addr), &value, sizeof(value), nullptr);
|
||||||
if (ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(addr), data, sizeof(data), nullptr)) {
|
|
||||||
value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "spy_types.h"
|
#include "spy_types.h"
|
||||||
|
|
||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
|
|
||||||
inline constexpr wchar_t WECHATEXE[] = L"WeChat.exe";
|
inline constexpr char WECHATEXE[] = "WeChat.exe";
|
||||||
inline constexpr wchar_t WECHATWINDLL[] = L"WeChatWin.dll";
|
inline constexpr char WECHATWINDLL[] = "WeChatWin.dll";
|
||||||
inline constexpr wchar_t WCFSDKDLL[] = L"sdk.dll";
|
inline constexpr wchar_t WCFSDKDLL[] = L"sdk.dll";
|
||||||
inline constexpr wchar_t WCFSPYDLL[] = L"spy.dll";
|
inline constexpr wchar_t WCFSPYDLL[] = L"spy.dll";
|
||||||
inline constexpr wchar_t WCFSPYDLL_DEBUG[] = L"spy_debug.dll";
|
inline constexpr wchar_t WCFSPYDLL_DEBUG[] = L"spy_debug.dll";
|
||||||
@ -19,6 +21,16 @@ struct PortPath {
|
|||||||
char path[MAX_PATH];
|
char path[MAX_PATH];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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, ...);
|
||||||
|
|
||||||
inline DWORD get_dword(uint64_t addr) { return addr ? *reinterpret_cast<DWORD *>(addr) : 0; }
|
inline DWORD get_dword(uint64_t addr) { return addr ? *reinterpret_cast<DWORD *>(addr) : 0; }
|
||||||
inline QWORD get_qword(uint64_t addr) { return addr ? *reinterpret_cast<QWORD *>(addr) : 0; }
|
inline QWORD get_qword(uint64_t addr) { return addr ? *reinterpret_cast<QWORD *>(addr) : 0; }
|
||||||
inline uint64_t get_uint64(uint64_t addr) { return addr ? *reinterpret_cast<uint64_t *>(addr) : 0; }
|
inline uint64_t get_uint64(uint64_t addr) { return addr ? *reinterpret_cast<uint64_t *>(addr) : 0; }
|
||||||
@ -47,12 +59,12 @@ inline std::wstring get_pp_wstring(uint64_t addr)
|
|||||||
if (!addr) return L"";
|
if (!addr) return L"";
|
||||||
|
|
||||||
const wchar_t *ptr = *reinterpret_cast<const wchar_t **>(addr);
|
const wchar_t *ptr = *reinterpret_cast<const wchar_t **>(addr);
|
||||||
return (ptr && *ptr) ? std::wstring(ptr) : "";
|
return (ptr && *ptr) ? std::wstring(ptr) : L"";
|
||||||
}
|
}
|
||||||
inline std::string get_pp_len_string(uint64_t addr)
|
inline std::string get_pp_len_string(uint64_t addr)
|
||||||
{
|
{
|
||||||
size_t len = get_dword(addr + 8);
|
size_t len = get_dword(addr + 8);
|
||||||
return (addr && len) ? std::string(*reinterpret_cast<const char **>(addr), len) : L"";
|
return (addr && len) ? std::string(*reinterpret_cast<const char **>(addr), len) : "";
|
||||||
}
|
}
|
||||||
inline std::wstring get_pp_len_wstring(uint64_t addr)
|
inline std::wstring get_pp_len_wstring(uint64_t addr)
|
||||||
{
|
{
|
||||||
@ -61,16 +73,6 @@ inline std::wstring get_pp_len_wstring(uint64_t addr)
|
|||||||
}
|
}
|
||||||
inline std::string get_str_by_wstr_addr(uint64_t addr) { return w2s(get_pp_len_wstring(addr)); }
|
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 char *str);
|
||||||
std::unique_ptr<WxString> new_wx_string(const wchar_t *wstr);
|
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::string &str);
|
||||||
|
@ -45,10 +45,10 @@ int add_chatroom_member(const string &roomid, const string &wxids)
|
|||||||
= reinterpret_cast<add_member_to_chatroom_t>(g_WeChatWinDllAddr + OS_ADD_MEMBERS);
|
= reinterpret_cast<add_member_to_chatroom_t>(g_WeChatWinDllAddr + OS_ADD_MEMBERS);
|
||||||
|
|
||||||
vector<WxString> wx_members = parse_wxids(wxids);
|
vector<WxString> wx_members = parse_wxids(wxids);
|
||||||
WxString *p_wx_roomid = NewWxStringFromStr(roomid);
|
auto wx_roomid = util::new_wx_string(roomid);
|
||||||
QWORD p_members = reinterpret_cast<QWORD>(&wx_members.front());
|
QWORD p_members = reinterpret_cast<QWORD>(&wx_members.front());
|
||||||
|
|
||||||
return static_cast<int>(add_members(get_chatroom_mgr(), p_members, reinterpret_cast<QWORD>(p_wx_roomid), 0));
|
return static_cast<int>(add_members(get_chatroom_mgr(), p_members, reinterpret_cast<QWORD>(wx_roomid.get()), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
int del_chatroom_member(const string &roomid, const string &wxids)
|
int del_chatroom_member(const string &roomid, const string &wxids)
|
||||||
@ -64,10 +64,10 @@ int del_chatroom_member(const string &roomid, const string &wxids)
|
|||||||
= reinterpret_cast<del_member_from_chatroom_t>(g_WeChatWinDllAddr + OS_DELETE_MEMBERS);
|
= reinterpret_cast<del_member_from_chatroom_t>(g_WeChatWinDllAddr + OS_DELETE_MEMBERS);
|
||||||
|
|
||||||
vector<WxString> wx_members = parse_wxids(wxids);
|
vector<WxString> wx_members = parse_wxids(wxids);
|
||||||
WxString *p_wx_roomid = NewWxStringFromStr(roomid);
|
auto wx_roomid = util::new_wx_string(roomid);
|
||||||
QWORD p_members = reinterpret_cast<QWORD>(&wx_members.front());
|
QWORD p_members = reinterpret_cast<QWORD>(&wx_members.front());
|
||||||
|
|
||||||
return static_cast<int>(del_members(get_chatroom_mgr(), p_members, reinterpret_cast<QWORD>(p_wx_roomid)));
|
return static_cast<int>(del_members(get_chatroom_mgr(), p_members, reinterpret_cast<QWORD>(wx_roomid.get())));
|
||||||
}
|
}
|
||||||
|
|
||||||
int invite_chatroom_member(const string &roomid, const string &wxids)
|
int invite_chatroom_member(const string &roomid, const string &wxids)
|
||||||
@ -81,11 +81,11 @@ int invite_chatroom_member(const string &roomid, const string &wxids)
|
|||||||
= reinterpret_cast<invite_member_to_chatroom_t>(g_WeChatWinDllAddr + OS_INVITE_MEMBERS);
|
= reinterpret_cast<invite_member_to_chatroom_t>(g_WeChatWinDllAddr + OS_INVITE_MEMBERS);
|
||||||
|
|
||||||
vector<WxString> wx_members = parse_wxids(wxids);
|
vector<WxString> wx_members = parse_wxids(wxids);
|
||||||
WxString *p_wx_roomid = NewWxStringFromStr(roomid);
|
auto wx_roomid = util::new_wx_string(roomid);
|
||||||
QWORD p_members = reinterpret_cast<QWORD>(&wx_members.front());
|
QWORD p_members = reinterpret_cast<QWORD>(&wx_members.front());
|
||||||
|
|
||||||
return static_cast<int>(invite_members(reinterpret_cast<QWORD>(p_wx_roomid->wptr), p_members,
|
return static_cast<int>(invite_members(reinterpret_cast<QWORD>(wx_roomid.get()->wptr), p_members,
|
||||||
reinterpret_cast<QWORD>(p_wx_roomid), 0));
|
reinterpret_cast<QWORD>(wx_roomid.get()), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rpc_add_chatroom_member(const string &roomid, const string &wxids, uint8_t *out, size_t *len)
|
bool rpc_add_chatroom_member(const string &roomid, const string &wxids, uint8_t *out, size_t *len)
|
||||||
|
@ -51,7 +51,7 @@ static string get_cnt_string(QWORD start, QWORD end, const uint8_t *feat, size_t
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD lfeat = GET_DWORD(pfeat + len);
|
DWORD lfeat = util::get_dword(pfeat + len);
|
||||||
if (lfeat <= 2) {
|
if (lfeat <= 2) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -78,8 +78,8 @@ vector<RpcContact_t> get_contacts()
|
|||||||
QWORD pend = addr[2];
|
QWORD pend = addr[2];
|
||||||
while (pstart < pend) {
|
while (pstart < pend) {
|
||||||
RpcContact_t cnt;
|
RpcContact_t cnt;
|
||||||
QWORD pbin = GET_QWORD(pstart + OS_CONTACT_BIN);
|
QWORD pbin = util::get_qword(pstart + OS_CONTACT_BIN);
|
||||||
QWORD lenbin = GET_DWORD(pstart + OS_CONTACT_BIN_LEN);
|
QWORD lenbin = util::get_dword(pstart + OS_CONTACT_BIN_LEN);
|
||||||
|
|
||||||
cnt.wxid = util::get_str_by_wstr_addr(pstart + OS_CONTACT_WXID);
|
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.code = util::get_str_by_wstr_addr(pstart + OS_CONTACT_CODE);
|
||||||
@ -180,7 +180,7 @@ RpcContact_t get_contact_by_wxid(const string &wxid)
|
|||||||
contact.code = util::get_str_by_wstr_addr(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 = util::get_str_by_wstr_addr(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 = util::get_str_by_wstr_addr(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 = util::get_dword(reinterpret_cast<DWORD>(buff) + 0x148);
|
||||||
|
|
||||||
__asm {
|
__asm {
|
||||||
PUSHAD
|
PUSHAD
|
||||||
|
@ -31,24 +31,24 @@ 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 = util::w2s(std::wstring(wsp));
|
std::string dbname = util::w2s(std::wstring(wsp));
|
||||||
db_map[dbname] = GET_QWORD(base + offset);
|
db_map[dbname] = util::get_qword(base + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_msg_db_handle(QWORD msg_mgr_addr)
|
static void get_msg_db_handle(QWORD msg_mgr_addr)
|
||||||
{
|
{
|
||||||
QWORD db_index = GET_QWORD(msg_mgr_addr + 0x68);
|
QWORD db_index = util::get_qword(msg_mgr_addr + 0x68);
|
||||||
QWORD p_start = GET_QWORD(msg_mgr_addr + 0x50);
|
QWORD p_start = util::get_qword(msg_mgr_addr + 0x50);
|
||||||
for (uint32_t i = 0; i < db_index; i++) {
|
for (uint32_t i = 0; i < db_index; i++) {
|
||||||
QWORD db_addr = GET_QWORD(p_start + i * 0x08);
|
QWORD db_addr = util::get_qword(p_start + i * 0x08);
|
||||||
if (db_addr) {
|
if (db_addr) {
|
||||||
// MSGi.db
|
// MSGi.db
|
||||||
std::string dbname = util::w2s(get_pp_wstring(db_addr));
|
std::string dbname = util::w2s(util::get_pp_wstring(db_addr));
|
||||||
db_map[dbname] = GET_QWORD(db_addr + 0x78);
|
db_map[dbname] = util::get_qword(db_addr + 0x78);
|
||||||
|
|
||||||
// MediaMsgi.db
|
// MediaMsgi.db
|
||||||
QWORD mmdb_addr = GET_QWORD(db_addr + 0x20);
|
QWORD mmdb_addr = util::get_qword(db_addr + 0x20);
|
||||||
std::string mmdbname = util::w2s(get_pp_wstring(mmdb_addr + 0x78));
|
std::string mmdbname = util::w2s(util::get_pp_wstring(mmdb_addr + 0x78));
|
||||||
db_map[mmdbname] = GET_QWORD(mmdb_addr + 0x50);
|
db_map[mmdbname] = util::get_qword(mmdb_addr + 0x50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ static void get_msg_db_handle(QWORD msg_mgr_addr)
|
|||||||
db_map_t get_db_handles()
|
db_map_t get_db_handles()
|
||||||
{
|
{
|
||||||
db_map.clear();
|
db_map.clear();
|
||||||
QWORD db_instance_addr = GET_QWORD(g_WeChatWinDllAddr + OFFSET_DB_INSTANCE);
|
QWORD db_instance_addr = util::get_qword(g_WeChatWinDllAddr + OFFSET_DB_INSTANCE);
|
||||||
|
|
||||||
get_db_handle(db_instance_addr, OFFSET_DB_MICROMSG); // MicroMsg.db
|
get_db_handle(db_instance_addr, OFFSET_DB_MICROMSG); // MicroMsg.db
|
||||||
get_db_handle(db_instance_addr, OFFSET_DB_CHAT_MSG); // ChatMsg.db
|
get_db_handle(db_instance_addr, OFFSET_DB_CHAT_MSG); // ChatMsg.db
|
||||||
@ -65,7 +65,7 @@ db_map_t get_db_handles()
|
|||||||
get_db_handle(db_instance_addr, OFFSET_DB_MEDIA); // Media.db
|
get_db_handle(db_instance_addr, OFFSET_DB_MEDIA); // Media.db
|
||||||
get_db_handle(db_instance_addr, OFFSET_DB_FUNCTION_MSG); // Function.db
|
get_db_handle(db_instance_addr, OFFSET_DB_FUNCTION_MSG); // Function.db
|
||||||
|
|
||||||
get_msg_db_handle(GET_QWORD(g_WeChatWinDllAddr + OFFSET_DB_MSG_MGR)); // MSGi.db & MediaMsgi.db
|
get_msg_db_handle(util::get_qword(g_WeChatWinDllAddr + OFFSET_DB_MSG_MGR)); // MSGi.db & MediaMsgi.db
|
||||||
|
|
||||||
return db_map;
|
return db_map;
|
||||||
}
|
}
|
||||||
@ -189,19 +189,19 @@ int get_local_id_and_dbidx(uint64_t id, uint64_t *local_id, uint32_t *db_idx)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWORD msg_mgr_addr = GET_QWORD(g_WeChatWinDllAddr + OFFSET_DB_MSG_MGR);
|
QWORD msg_mgr_addr = util::get_qword(g_WeChatWinDllAddr + OFFSET_DB_MSG_MGR);
|
||||||
int db_index = static_cast<int>(GET_QWORD(msg_mgr_addr + 0x68)); // 总不能 int 还不够吧?
|
int db_index = static_cast<int>(util::get_qword(msg_mgr_addr + 0x68)); // 总不能 int 还不够吧?
|
||||||
QWORD p_start = GET_QWORD(msg_mgr_addr + 0x50);
|
QWORD p_start = util::get_qword(msg_mgr_addr + 0x50);
|
||||||
|
|
||||||
*db_idx = 0;
|
*db_idx = 0;
|
||||||
for (int i = db_index - 1; i >= 0; i--) { // 从后往前遍历
|
for (int i = db_index - 1; i >= 0; i--) { // 从后往前遍历
|
||||||
QWORD db_addr = GET_QWORD(p_start + i * 0x08);
|
QWORD db_addr = util::get_qword(p_start + i * 0x08);
|
||||||
if (!db_addr) {
|
if (!db_addr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dbname = util::w2s(get_pp_wstring(db_addr));
|
std::string dbname = util::w2s(util::get_pp_wstring(db_addr));
|
||||||
db_map[dbname] = GET_QWORD(db_addr + 0x78);
|
db_map[dbname] = util::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) + ";";
|
||||||
DbRows_t rows = exec_db_query(dbname, sql);
|
DbRows_t rows = exec_db_query(dbname, sql);
|
||||||
@ -223,7 +223,7 @@ int get_local_id_and_dbidx(uint64_t id, uint64_t *local_id, uint32_t *db_idx)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
*db_idx = static_cast<uint32_t>(GET_QWORD(GET_QWORD(db_addr + 0x28) + 0x1E8) >> 32);
|
*db_idx = static_cast<uint32_t>(util::get_qword(util::get_qword(db_addr + 0x28) + 0x1E8) >> 32);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,8 +232,8 @@ int get_local_id_and_dbidx(uint64_t id, uint64_t *local_id, uint32_t *db_idx)
|
|||||||
|
|
||||||
std::vector<uint8_t> get_audio_data(uint64_t id)
|
std::vector<uint8_t> get_audio_data(uint64_t id)
|
||||||
{
|
{
|
||||||
QWORD msg_mgr_addr = GET_QWORD(g_WeChatWinDllAddr + OFFSET_DB_MSG_MGR);
|
QWORD msg_mgr_addr = util::get_qword(g_WeChatWinDllAddr + OFFSET_DB_MSG_MGR);
|
||||||
int db_index = static_cast<int>(GET_QWORD(msg_mgr_addr + 0x68));
|
int db_index = static_cast<int>(util::get_qword(msg_mgr_addr + 0x68));
|
||||||
|
|
||||||
std::string sql = "SELECT Buf FROM Media WHERE Reserved0=" + std::to_string(id) + ";";
|
std::string sql = "SELECT Buf FROM Media WHERE Reserved0=" + std::to_string(id) + ";";
|
||||||
for (int i = db_index - 1; i >= 0; i--) {
|
for (int i = db_index - 1; i >= 0; i--) {
|
||||||
|
@ -51,7 +51,7 @@ typedef QWORD (*PushAttachTask_t)(QWORD, QWORD, QWORD, QWORD);
|
|||||||
typedef QWORD (*GetOCRManager_t)();
|
typedef QWORD (*GetOCRManager_t)();
|
||||||
typedef QWORD (*DoOCRTask_t)(QWORD, QWORD, QWORD, QWORD, QWORD, QWORD);
|
typedef QWORD (*DoOCRTask_t)(QWORD, QWORD, QWORD, QWORD, QWORD, QWORD);
|
||||||
|
|
||||||
int IsLogin(void) { return (int)GET_QWORD(g_WeChatWinDllAddr + OS_LOGIN_STATUS); }
|
int IsLogin(void) { return (int)util::get_qword(g_WeChatWinDllAddr + OS_LOGIN_STATUS); }
|
||||||
|
|
||||||
static string get_key(uint8_t header1, uint8_t header2, uint8_t *key)
|
static string get_key(uint8_t header1, uint8_t header2, uint8_t *key)
|
||||||
{
|
{
|
||||||
@ -230,7 +230,7 @@ int DownloadAttach(QWORD id, string thumb, string extra)
|
|||||||
GetChatMgr();
|
GetChatMgr();
|
||||||
GetMgrByPrefixLocalId(l.QuadPart, pChatMsg);
|
GetMgrByPrefixLocalId(l.QuadPart, pChatMsg);
|
||||||
|
|
||||||
QWORD type = GET_QWORD(buff + 0x38);
|
QWORD type = util::get_qword(reinterpret_cast<QWORD>(buff) + 0x38);
|
||||||
|
|
||||||
string save_path = "";
|
string save_path = "";
|
||||||
string thumb_path = "";
|
string thumb_path = "";
|
||||||
@ -262,12 +262,12 @@ int DownloadAttach(QWORD id, string thumb, string extra)
|
|||||||
// 创建父目录,由于路径来源于微信,不做检查
|
// 创建父目录,由于路径来源于微信,不做检查
|
||||||
fs::create_directory(fs::path(save_path).parent_path().string());
|
fs::create_directory(fs::path(save_path).parent_path().string());
|
||||||
|
|
||||||
int temp = 1;
|
int temp = 1;
|
||||||
WxString *pSavePath = NewWxStringFromStr(save_path);
|
auto wx_save_path = util::new_wx_string(save_path);
|
||||||
WxString *pThumbPath = NewWxStringFromStr(thumb_path);
|
auto wx_thumb_path = util::new_wx_string(thumb_path);
|
||||||
|
|
||||||
memcpy(&buff[0x280], pThumbPath, sizeof(WxString));
|
memcpy(&buff[0x280], wx_thumb_path.get(), sizeof(WxString));
|
||||||
memcpy(&buff[0x2A0], pSavePath, sizeof(WxString));
|
memcpy(&buff[0x2A0], wx_save_path.get(), sizeof(WxString));
|
||||||
memcpy(&buff[0x40C], &temp, sizeof(temp));
|
memcpy(&buff[0x40C], &temp, sizeof(temp));
|
||||||
|
|
||||||
QWORD mgr = GetPreDownLoadMgr();
|
QWORD mgr = GetPreDownLoadMgr();
|
||||||
@ -354,11 +354,11 @@ OcrResult_t GetOcrResult(string path)
|
|||||||
QWORD mgr = GetOCRManager();
|
QWORD mgr = GetOCRManager();
|
||||||
ret.status = (int)DoOCRTask(mgr, (QWORD)&wxPath, unused, (QWORD)buff, (QWORD)&pUnk1, (QWORD)&pUnk2);
|
ret.status = (int)DoOCRTask(mgr, (QWORD)&wxPath, unused, (QWORD)buff, (QWORD)&pUnk1, (QWORD)&pUnk2);
|
||||||
|
|
||||||
QWORD count = GET_QWORD(buff + 0x8);
|
QWORD count = util::get_qword(buff + 0x8);
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
QWORD header = GET_QWORD(buff);
|
QWORD header = util::get_qword(buff);
|
||||||
for (QWORD i = 0; i < count; i++) {
|
for (QWORD i = 0; i < count; i++) {
|
||||||
QWORD content = GET_QWORD(header);
|
QWORD content = util::get_qword(header);
|
||||||
ret.result += util::w2s(get_pp_wstring(content + 0x28));
|
ret.result += util::w2s(get_pp_wstring(content + 0x28));
|
||||||
ret.result += "\n";
|
ret.result += "\n";
|
||||||
header = content;
|
header = content;
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "pb_types.h"
|
||||||
|
|
||||||
int IsLogin(void);
|
int IsLogin(void);
|
||||||
std::string GetAudio(uint64_t id, std::string dir);
|
std::string GetAudio(uint64_t id, std::string dir);
|
||||||
std::string GetPCMAudio(uint64_t id, std::string dir, int32_t sr);
|
std::string GetPCMAudio(uint64_t id, std::string dir, int32_t sr);
|
||||||
@ -11,5 +13,5 @@ int RefreshPyq(uint64_t id);
|
|||||||
int DownloadAttach(uint64_t id, std::string thumb, std::string extra);
|
int DownloadAttach(uint64_t id, std::string thumb, std::string extra);
|
||||||
int RevokeMsg(uint64_t id);
|
int RevokeMsg(uint64_t id);
|
||||||
OcrResult_t GetOcrResult(std::string path);
|
OcrResult_t GetOcrResult(std::string path);
|
||||||
string GetLoginUrl();
|
std::string GetLoginUrl();
|
||||||
int ReceiveTransfer(std::string wxid, std::string transferid, std::string transactionid);
|
int ReceiveTransfer(std::string wxid, std::string transferid, std::string transactionid);
|
||||||
|
@ -38,10 +38,10 @@ QWORD MessageHandler::DispatchMsg(QWORD arg1, QWORD arg2)
|
|||||||
auto &handler = getInstance();
|
auto &handler = getInstance();
|
||||||
WxMsg_t wxMsg = {};
|
WxMsg_t wxMsg = {};
|
||||||
try {
|
try {
|
||||||
wxMsg.id = GET_QWORD(arg2 + OS_RECV_MSG_ID);
|
wxMsg.id = util::get_qword(arg2 + OS_RECV_MSG_ID);
|
||||||
wxMsg.type = GET_DWORD(arg2 + OS_RECV_MSG_TYPE);
|
wxMsg.type = util::get_dword(arg2 + OS_RECV_MSG_TYPE);
|
||||||
wxMsg.is_self = GET_DWORD(arg2 + OS_RECV_MSG_SELF);
|
wxMsg.is_self = util::get_dword(arg2 + OS_RECV_MSG_SELF);
|
||||||
wxMsg.ts = GET_DWORD(arg2 + OS_RECV_MSG_TS);
|
wxMsg.ts = util::get_dword(arg2 + OS_RECV_MSG_TS);
|
||||||
wxMsg.content = util::get_str_by_wstr_addr(arg2 + OS_RECV_MSG_CONTENT);
|
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.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.xml = util::get_str_by_wstr_addr(arg2 + OS_RECV_MSG_XML);
|
||||||
@ -98,8 +98,8 @@ void MessageHandler::DispatchPyq(QWORD arg1, QWORD arg2, QWORD arg3)
|
|||||||
wxMsg.type = 0x00;
|
wxMsg.type = 0x00;
|
||||||
wxMsg.is_self = false;
|
wxMsg.is_self = false;
|
||||||
wxMsg.is_group = false;
|
wxMsg.is_group = false;
|
||||||
wxMsg.id = GET_QWORD(startAddr);
|
wxMsg.id = util::get_qword(startAddr);
|
||||||
wxMsg.ts = GET_DWORD(startAddr + OS_PYQ_MSG_TS);
|
wxMsg.ts = util::get_dword(startAddr + OS_PYQ_MSG_TS);
|
||||||
wxMsg.xml = util::get_str_by_wstr_addr(startAddr + OS_PYQ_MSG_XML);
|
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.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);
|
wxMsg.content = util::get_str_by_wstr_addr(startAddr + OS_PYQ_MSG_CONTENT);
|
||||||
|
@ -5,11 +5,11 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include "MinHook.h"
|
#include "MinHook.h"
|
||||||
|
|
||||||
#include "pb_types.h"
|
#include "pb_types.h"
|
||||||
|
#include "spy_types.h"
|
||||||
|
|
||||||
class MessageHandler
|
class MessageHandler
|
||||||
{
|
{
|
||||||
|
@ -13,7 +13,7 @@ UINT64 g_WeChatWinDllAddr = 0;
|
|||||||
|
|
||||||
void InitSpy(LPVOID args)
|
void InitSpy(LPVOID args)
|
||||||
{
|
{
|
||||||
auto *pp = static_cast<PortPath_t *>(args);
|
auto *pp = static_cast<util::PortPath *>(args);
|
||||||
|
|
||||||
Log::InitLogger(pp->path);
|
Log::InitLogger(pp->path);
|
||||||
if (auto dll_addr = GetModuleHandle(L"WeChatWin.dll")) {
|
if (auto dll_addr = GetModuleHandle(L"WeChatWin.dll")) {
|
||||||
|
@ -22,7 +22,7 @@ std::string get_home_path()
|
|||||||
static std::string home_path;
|
static std::string home_path;
|
||||||
|
|
||||||
std::call_once(flag, [] {
|
std::call_once(flag, [] {
|
||||||
std::string path = util::w2s(get_pp_wstring(g_WeChatWinDllAddr + OS_USER_HOME)) + "\\WeChat Files\\";
|
std::string path = util::w2s(util::get_pp_wstring(g_WeChatWinDllAddr + OS_USER_HOME)) + "\\WeChat Files\\";
|
||||||
home_path = std::filesystem::absolute(path).string();
|
home_path = std::filesystem::absolute(path).string();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ std::string get_self_wxid()
|
|||||||
std::call_once(flag, [] {
|
std::call_once(flag, [] {
|
||||||
UINT64 wxid_type = 0;
|
UINT64 wxid_type = 0;
|
||||||
try {
|
try {
|
||||||
wxid_type = GET_UINT64(g_WeChatWinDllAddr + OS_USER_WXID + 0x18);
|
wxid_type = util::get_qword(g_WeChatWinDllAddr + OS_USER_WXID + 0x18);
|
||||||
if (wxid_type == 0xF) {
|
if (wxid_type == 0xF) {
|
||||||
wxid = util::get_p_string(g_WeChatWinDllAddr + OS_USER_WXID);
|
wxid = util::get_p_string(g_WeChatWinDllAddr + OS_USER_WXID);
|
||||||
} else {
|
} else {
|
||||||
@ -58,7 +58,7 @@ UserInfo_t get_user_info()
|
|||||||
UserInfo_t ui;
|
UserInfo_t ui;
|
||||||
ui.wxid = get_self_wxid();
|
ui.wxid = get_self_wxid();
|
||||||
|
|
||||||
UINT64 name_type = GET_UINT64(g_WeChatWinDllAddr + OS_USER_NAME + 0x18);
|
UINT64 name_type = util::get_qword(g_WeChatWinDllAddr + OS_USER_NAME + 0x18);
|
||||||
ui.name = (name_type == 0xF) ? util::get_p_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);
|
: util::get_pp_string(g_WeChatWinDllAddr + OS_USER_NAME);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user