diff --git a/WeChatFerry/spy/account_manager.cpp b/WeChatFerry/spy/account_manager.cpp index 3043c0f..b7c0306 100644 --- a/WeChatFerry/spy/account_manager.cpp +++ b/WeChatFerry/spy/account_manager.cpp @@ -5,10 +5,9 @@ #include "log.hpp" #include "offsets.h" #include "rpc_helper.h" +#include "spy.h" #include "util.h" -extern UINT64 g_WeChatWinDllAddr; - namespace account { @@ -28,7 +27,7 @@ static void clear_cached_home_path() { cachedHomePath.reset(); } static uint64_t get_account_service() { - static auto GetService = reinterpret_cast(g_WeChatWinDllAddr + OsAcc::SERVICE); + static auto GetService = Spy::getFunction(OsAcc::SERVICE); return GetService ? GetService() : 0; } @@ -52,7 +51,7 @@ fs::path get_home_path() return *cachedHomePath; } WxString home; - auto GetDataPath = reinterpret_cast(g_WeChatWinDllAddr + OsAcc::PATH); + auto GetDataPath = Spy::getFunction(OsAcc::PATH); int64_t service_addr = get_account_service(); GetDataPath((QWORD)&home); if (home.wptr) { diff --git a/WeChatFerry/spy/chatroom_manager.cpp b/WeChatFerry/spy/chatroom_manager.cpp index bd47ad5..912bda2 100644 --- a/WeChatFerry/spy/chatroom_manager.cpp +++ b/WeChatFerry/spy/chatroom_manager.cpp @@ -5,10 +5,9 @@ #include "offsets.h" #include "pb_util.h" #include "rpc_helper.h" +#include "spy.h" #include "util.h" -extern QWORD g_WeChatWinDllAddr; - namespace chatroom { namespace OsRoom = Offsets::Chatroom; @@ -32,8 +31,8 @@ bool rpc_chatroom_common(const MemberMgmt &m, uint8_t *out, size_t *len, Func fu int add_chatroom_member(const string &roomid, const string &wxids) { - auto get_chatroom_mgr = reinterpret_cast(g_WeChatWinDllAddr + OsRoom::MGR); - auto add_members = reinterpret_cast(g_WeChatWinDllAddr + OsRoom::ADD); + auto get_chatroom_mgr = Spy::getFunction(OsRoom::MGR); + auto add_members = Spy::getFunction(OsRoom::ADD); WxString *wx_roomid = util::CreateWxString(roomid); @@ -46,8 +45,8 @@ int add_chatroom_member(const string &roomid, const string &wxids) int del_chatroom_member(const string &roomid, const string &wxids) { - auto get_chatroom_mgr = reinterpret_cast(g_WeChatWinDllAddr + OsRoom::MGR); - auto del_members = reinterpret_cast(g_WeChatWinDllAddr + OsRoom::DEL); + auto get_chatroom_mgr = Spy::getFunction(OsRoom::MGR); + auto del_members = Spy::getFunction(OsRoom::DEL); WxString *wx_roomid = util::CreateWxString(roomid); auto wx_members = util::parse_wxids(wxids).wxWxids; @@ -58,7 +57,7 @@ int del_chatroom_member(const string &roomid, const string &wxids) int invite_chatroom_member(const string &roomid, const string &wxids) { - auto invite_members = reinterpret_cast(g_WeChatWinDllAddr + OsRoom::INV); + auto invite_members = Spy::getFunction(OsRoom::INV); wstring ws_roomid = util::s2w(roomid); WxString *wx_roomid = util::CreateWxString(roomid); diff --git a/WeChatFerry/spy/contact_manager.cpp b/WeChatFerry/spy/contact_manager.cpp index 591bbc9..64728ea 100644 --- a/WeChatFerry/spy/contact_manager.cpp +++ b/WeChatFerry/spy/contact_manager.cpp @@ -6,12 +6,11 @@ #include "offsets.h" #include "pb_util.h" #include "rpc_helper.h" +#include "spy.h" #include "util.h" using namespace std; -extern QWORD g_WeChatWinDllAddr; - namespace contact { namespace OsCon = Offsets::Contact; @@ -54,8 +53,8 @@ static string get_cnt_string(QWORD start, QWORD end, const uint8_t *feat, size_t vector get_contacts() { vector contacts; - get_contact_mgr_t func_get_contact_mgr = reinterpret_cast(g_WeChatWinDllAddr + OsCon::MGR); - get_contact_list_t func_get_contact_list = reinterpret_cast(g_WeChatWinDllAddr + OsCon::LIST); + auto func_get_contact_mgr = Spy::getFunction(OsCon::MGR); + auto func_get_contact_list = Spy::getFunction(OsCon::LIST); QWORD mgr = func_get_contact_mgr(); QWORD addr[3] = { 0 }; diff --git a/WeChatFerry/spy/database_executor.cpp b/WeChatFerry/spy/database_executor.cpp index 30a4944..42e0d9a 100644 --- a/WeChatFerry/spy/database_executor.cpp +++ b/WeChatFerry/spy/database_executor.cpp @@ -7,11 +7,10 @@ #include "offsets.h" #include "pb_util.h" #include "rpc_helper.h" +#include "spy.h" #include "sqlite3.h" #include "util.h" -extern UINT64 g_WeChatWinDllAddr; - namespace db { namespace OsDb = Offsets::Db; @@ -48,7 +47,7 @@ static void get_msg_db_handle(QWORD msg_mgr_addr) db_map_t get_db_handles() { db_map.clear(); - QWORD db_instance_addr = util::get_qword(g_WeChatWinDllAddr + OsDb::INSTANCE); + QWORD db_instance_addr = util::get_qword(Spy::WeChatDll.load() + OsDb::INSTANCE); get_db_handle(db_instance_addr, OsDb::MICROMSG); // MicroMsg.db get_db_handle(db_instance_addr, OsDb::CHAT_MSG); // ChatMsg.db @@ -57,7 +56,7 @@ db_map_t get_db_handles() get_db_handle(db_instance_addr, OsDb::MEDIA); // Media.db get_db_handle(db_instance_addr, OsDb::FUNCTION_MSG); // Function.db - get_msg_db_handle(util::get_qword(g_WeChatWinDllAddr + OsDb::MSG_I)); // MSGi.db & MediaMsgi.db + get_msg_db_handle(util::get_qword(Spy::WeChatDll.load() + OsDb::MSG_I)); // MSGi.db & MediaMsgi.db return db_map; } @@ -103,8 +102,8 @@ DbTables_t get_db_tables(const std::string &db) return tables; } - constexpr const char *sql = "SELECT name FROM sqlite_master WHERE type='table';"; - Sqlite3_exec p_sqlite3_exec = reinterpret_cast(g_WeChatWinDllAddr + OsDb::EXEC); + constexpr const char *sql = "SELECT name FROM sqlite_master WHERE type='table';"; + auto p_sqlite3_exec = Spy::getFunction(OsDb::EXEC); p_sqlite3_exec(it->second, sql, (Sqlite3_callback)cb_get_tables, (void *)&tables, nullptr); return tables; @@ -114,19 +113,14 @@ DbRows_t exec_db_query(const std::string &db, const std::string &sql) { DbRows_t rows; - Sqlite3_prepare func_prepare = reinterpret_cast(g_WeChatWinDllAddr + OsDb::PREPARE); - Sqlite3_step func_step = reinterpret_cast(g_WeChatWinDllAddr + OsDb::STEP); - Sqlite3_column_count func_column_count - = reinterpret_cast(g_WeChatWinDllAddr + OsDb::COLUMN_COUNT); - Sqlite3_column_name func_column_name - = reinterpret_cast(g_WeChatWinDllAddr + OsDb::COLUMN_NAME); - Sqlite3_column_type func_column_type - = reinterpret_cast(g_WeChatWinDllAddr + OsDb::COLUMN_TYPE); - Sqlite3_column_blob func_column_blob - = reinterpret_cast(g_WeChatWinDllAddr + OsDb::COLUMN_BLOB); - Sqlite3_column_bytes func_column_bytes - = reinterpret_cast(g_WeChatWinDllAddr + OsDb::COLUMN_BYTES); - Sqlite3_finalize func_finalize = reinterpret_cast(g_WeChatWinDllAddr + OsDb::FINALIZE); + auto func_prepare = Spy::getFunction(OsDb::PREPARE); + auto func_step = Spy::getFunction(OsDb::STEP); + auto func_column_count = Spy::getFunction(OsDb::COLUMN_COUNT); + auto func_column_name = Spy::getFunction(OsDb::COLUMN_NAME); + auto func_column_type = Spy::getFunction(OsDb::COLUMN_TYPE); + auto func_column_blob = Spy::getFunction(OsDb::COLUMN_BLOB); + auto func_column_bytes = Spy::getFunction(OsDb::COLUMN_BYTES); + auto func_finalize = Spy::getFunction(OsDb::FINALIZE); if (db_map.empty()) { db_map = get_db_handles(); @@ -180,7 +174,7 @@ int get_local_id_and_dbidx(uint64_t id, uint64_t *local_id, uint32_t *db_idx) return -1; } - QWORD msg_mgr_addr = util::get_qword(g_WeChatWinDllAddr + OsDb::MSG_I); + QWORD msg_mgr_addr = util::get_qword(Spy::WeChatDll.load() + OsDb::MSG_I); int db_index = static_cast(util::get_qword(msg_mgr_addr + 0x68)); // 总不能 int 还不够吧? QWORD p_start = util::get_qword(msg_mgr_addr + 0x50); @@ -223,7 +217,7 @@ int get_local_id_and_dbidx(uint64_t id, uint64_t *local_id, uint32_t *db_idx) std::vector get_audio_data(uint64_t id) { - QWORD msg_mgr_addr = util::get_qword(g_WeChatWinDllAddr + OsDb::MSG_I); + QWORD msg_mgr_addr = util::get_qword(Spy::WeChatDll.load() + OsDb::MSG_I); int db_index = static_cast(util::get_qword(msg_mgr_addr + 0x68)); std::string sql = "SELECT Buf FROM Media WHERE Reserved0=" + std::to_string(id) + ";"; diff --git a/WeChatFerry/spy/dllmain.cpp b/WeChatFerry/spy/dllmain.cpp index 580ec4c..66475e4 100644 --- a/WeChatFerry/spy/dllmain.cpp +++ b/WeChatFerry/spy/dllmain.cpp @@ -1,9 +1,5 @@ // dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "framework.h" -#include -#include - -#include "spy.h" BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { diff --git a/WeChatFerry/spy/message_handler.cpp b/WeChatFerry/spy/message_handler.cpp index 64c29cc..9537bf1 100644 --- a/WeChatFerry/spy/message_handler.cpp +++ b/WeChatFerry/spy/message_handler.cpp @@ -12,10 +12,9 @@ #include "offsets.h" #include "pb_util.h" #include "rpc_helper.h" +#include "spy.h" #include "util.h" -extern QWORD g_WeChatWinDllAddr; - namespace message { @@ -189,8 +188,8 @@ int Handler::EnableLog() { if (isLogging) return 1; - pLogLevel = reinterpret_cast(g_WeChatWinDllAddr + OsLog::LEVEL); - funcWxLog = reinterpret_cast(g_WeChatWinDllAddr + OsLog::CALL); + pLogLevel = reinterpret_cast(Spy::WeChatDll.load() + OsLog::LEVEL); + funcWxLog = Spy::getFunction(OsLog::CALL); if (InitializeHook() != MH_OK) return -1; if (MH_CreateHook(funcWxLog, &PrintWxLog, reinterpret_cast(&realWxLog)) != MH_OK) return -2; @@ -215,7 +214,7 @@ int Handler::ListenMsg() { if (isListeningMsg) return 1; - funcRecvMsg = reinterpret_cast(g_WeChatWinDllAddr + OsRecv::CALL); + funcRecvMsg = Spy::getFunction(OsRecv::CALL); if (InitializeHook() != MH_OK) return -1; if (MH_CreateHook(funcRecvMsg, &DispatchMsg, reinterpret_cast(&realRecvMsg)) != MH_OK) return -1; if (MH_EnableHook(funcRecvMsg) != MH_OK) return -1; @@ -237,7 +236,7 @@ int Handler::ListenPyq() { if (isListeningPyq) return 1; - funcRecvPyq = reinterpret_cast(g_WeChatWinDllAddr + OsRecv::PYQ_CALL); + funcRecvPyq = Spy::getFunction(OsRecv::PYQ_CALL); if (InitializeHook() != MH_OK) return -1; if (MH_CreateHook(funcRecvPyq, &DispatchPyq, reinterpret_cast(&realRecvPyq)) != MH_OK) return -1; if (MH_EnableHook(funcRecvPyq) != MH_OK) return -1; diff --git a/WeChatFerry/spy/message_sender.cpp b/WeChatFerry/spy/message_sender.cpp index 411da62..2cbfac3 100644 --- a/WeChatFerry/spy/message_sender.cpp +++ b/WeChatFerry/spy/message_sender.cpp @@ -8,11 +8,10 @@ #include "log.hpp" #include "offsets.h" #include "rpc_helper.h" +#include "spy.h" #include "spy_types.h" #include "util.h" -extern QWORD g_WeChatWinDllAddr; - namespace message { @@ -26,22 +25,22 @@ Sender &Sender::get_instance() Sender::Sender() { - func_new_chat_msg = reinterpret_cast(g_WeChatWinDllAddr + OsSend::INSTANCE); - func_free_chat_msg = reinterpret_cast(g_WeChatWinDllAddr + OsSend::FREE); - func_send_msg_mgr = reinterpret_cast(g_WeChatWinDllAddr + OsSend::MGR); - func_send_text = reinterpret_cast(g_WeChatWinDllAddr + OsSend::TEXT); - func_send_image = reinterpret_cast(g_WeChatWinDllAddr + OsSend::IMAGE); - func_get_app_mgr = reinterpret_cast(g_WeChatWinDllAddr + OsSend::APP_MGR); - func_send_file = reinterpret_cast(g_WeChatWinDllAddr + OsSend::FILE); - func_new_mmreader = reinterpret_cast(g_WeChatWinDllAddr + OsSend::NEW_MM_READER); - func_free_mmreader = reinterpret_cast(g_WeChatWinDllAddr + OsSend::FREE_MM_READER); - func_send_rich_text = reinterpret_cast(g_WeChatWinDllAddr + OsSend::RICH_TEXT); - func_send_pat = reinterpret_cast(g_WeChatWinDllAddr + OsSend::PAT); - func_forward = reinterpret_cast(g_WeChatWinDllAddr + OsSend::FORWARD); - func_get_emotion_mgr = reinterpret_cast(g_WeChatWinDllAddr + OsSend::EMOTION_MGR); - func_send_emotion = reinterpret_cast(g_WeChatWinDllAddr + OsSend::EMOTION); - func_send_xml = reinterpret_cast(g_WeChatWinDllAddr + OsSend::XML); - func_xml_buf_sign = reinterpret_cast(g_WeChatWinDllAddr + OsSend::XML_BUF_SIGN); + func_new_chat_msg = Spy::getFunction(OsSend::INSTANCE); + func_free_chat_msg = Spy::getFunction(OsSend::FREE); + func_send_msg_mgr = Spy::getFunction(OsSend::MGR); + func_send_text = Spy::getFunction(OsSend::TEXT); + func_send_image = Spy::getFunction(OsSend::IMAGE); + func_get_app_mgr = Spy::getFunction(OsSend::APP_MGR); + func_send_file = Spy::getFunction(OsSend::FILE); + func_new_mmreader = Spy::getFunction(OsSend::NEW_MM_READER); + func_free_mmreader = Spy::getFunction(OsSend::FREE_MM_READER); + func_send_rich_text = Spy::getFunction(OsSend::RICH_TEXT); + func_send_pat = Spy::getFunction(OsSend::PAT); + func_forward = Spy::getFunction(OsSend::FORWARD); + func_get_emotion_mgr = Spy::getFunction(OsSend::EMOTION_MGR); + func_send_emotion = Spy::getFunction(OsSend::EMOTION); + func_send_xml = Spy::getFunction(OsSend::XML); + func_xml_buf_sign = Spy::getFunction(OsSend::XML_BUF_SIGN); } void Sender::send_text(const std::string &wxid, const std::string &msg, const std::string &at_wxids) diff --git a/WeChatFerry/spy/misc_manager.cpp b/WeChatFerry/spy/misc_manager.cpp index dbfd47b..fa968c4 100644 --- a/WeChatFerry/spy/misc_manager.cpp +++ b/WeChatFerry/spy/misc_manager.cpp @@ -12,11 +12,10 @@ #include "message_handler.h" #include "offsets.h" #include "rpc_helper.h" +#include "spy.h" #include "spy_types.h" #include "util.h" -extern QWORD g_WeChatWinDllAddr; - namespace misc { using namespace std; @@ -105,8 +104,8 @@ static int get_first_page() { int status = -1; - get_sns_data_mgr_t GetSNSDataMgr = (get_sns_data_mgr_t)(g_WeChatWinDllAddr + OsSns::DATA_MGR); - get_sns_first_page_t GetSNSFirstPage = (get_sns_first_page_t)(g_WeChatWinDllAddr + OsSns::FIRST); + auto GetSNSDataMgr = Spy::getFunction(OsSns::DATA_MGR); + auto GetSNSFirstPage = Spy::getFunction(OsSns::FIRST); QWORD buff[16] = { 0 }; QWORD mgr = GetSNSDataMgr(); @@ -119,8 +118,8 @@ static int get_next_page(QWORD id) { int status = -1; - get_sns_timeline_mgr_t GetSnsTimeLineMgr = (get_sns_timeline_mgr_t)(g_WeChatWinDllAddr + OsSns::TIMELINE); - get_sns_next_page_scene_t GetSNSNextPageScene = (get_sns_next_page_scene_t)(g_WeChatWinDllAddr + OsSns::NEXT); + auto GetSnsTimeLineMgr = Spy::getFunction(OsSns::TIMELINE); + auto GetSNSNextPageScene = Spy::getFunction(OsSns::NEXT); QWORD mgr = GetSnsTimeLineMgr(); status = (int)GetSNSNextPageScene(mgr, id); @@ -167,13 +166,12 @@ int download_attachment(uint64_t id, const fs::path &thumb, const fs::path &extr return status; } - new_chat_msg_t NewChatMsg = (new_chat_msg_t)(g_WeChatWinDllAddr + OsMisc::INSATNCE); - free_chat_msg_t FreeChatMsg = (free_chat_msg_t)(g_WeChatWinDllAddr + OsMisc::FREE); - get_chat_mgr_t GetChatMgr = (get_chat_mgr_t)(g_WeChatWinDllAddr + OsMisc::CHAT_MGR); - get_pre_download_mgr_t GetPreDownLoadMgr = (get_pre_download_mgr_t)(g_WeChatWinDllAddr + OsMisc::PRE_DOWNLOAD_MGR); - push_attach_task_t PushAttachTask = (push_attach_task_t)(g_WeChatWinDllAddr + OsMisc::PUSH_ATTACH_TASK); - get_mgr_by_prefix_localid_t GetMgrByPrefixLocalId - = (get_mgr_by_prefix_localid_t)(g_WeChatWinDllAddr + OsMisc::PRE_LOCAL_ID_MGR); + auto NewChatMsg = Spy::getFunction(OsMisc::INSATNCE); + auto FreeChatMsg = Spy::getFunction(OsMisc::FREE); + auto GetChatMgr = Spy::getFunction(OsMisc::CHAT_MGR); + auto GetPreDownLoadMgr = Spy::getFunction(OsMisc::PRE_DOWNLOAD_MGR); + auto PushAttachTask = Spy::getFunction(OsMisc::PUSH_ATTACH_TASK); + auto GetMgrByPrefixLocalId = Spy::getFunction(OsMisc::PRE_LOCAL_ID_MGR); LARGE_INTEGER l; l.HighPart = dbIdx; @@ -336,7 +334,7 @@ int revoke_message(uint64_t id) std::string get_login_url() { std::string uri; - get_qr_code_mgr_t get_qr_code_mgr = (get_qr_code_mgr_t)(g_WeChatWinDllAddr + OsMisc::QR_CODE); + auto get_qr_code_mgr = Spy::getFunction(OsMisc::QR_CODE); uint64_t addr = get_qr_code_mgr() + 0x68; uint64_t len = *(uint64_t *)(addr + 0x10); diff --git a/WeChatFerry/spy/spy.cpp b/WeChatFerry/spy/spy.cpp index b721e9f..ae5ee39 100644 --- a/WeChatFerry/spy/spy.cpp +++ b/WeChatFerry/spy/spy.cpp @@ -1,23 +1,21 @@ #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.12.17"; - -UINT64 g_WeChatWinDllAddr = 0; - -int InitSpy(LPVOID args) +namespace Spy +{ +int Init(void *args) { auto *pp = static_cast(args); Log::InitLogger(pp->path); if (auto dll_addr = GetModuleHandle(L"WeChatWin.dll")) { - g_WeChatWinDllAddr = reinterpret_cast(dll_addr); + WeChatDll.store(reinterpret_cast(dll_addr)); } else { LOG_ERROR("获取 WeChatWin.dll 模块地址失败"); return -1; @@ -37,8 +35,14 @@ int InitSpy(LPVOID args) return 0; } -void CleanupSpy() +void Cleanup() { LOG_DEBUG("CleanupSpy"); RpcServer::destroyInstance(); } +} + +extern "C" { +__declspec(dllexport) int InitSpy(void *args) { return Spy::Init(args); } +__declspec(dllexport) void CleanupSpy() { Spy::Cleanup(); } +} diff --git a/WeChatFerry/spy/spy.h b/WeChatFerry/spy/spy.h index 07825e6..ae8f402 100644 --- a/WeChatFerry/spy/spy.h +++ b/WeChatFerry/spy/spy.h @@ -1,6 +1,20 @@ #pragma once -#include "framework.h" +#include +#include +#include -int InitSpy(int port); -void CleanupSpy(); +namespace Spy +{ +constexpr std::string_view SUPPORT_VERSION = "3.9.12.17"; +inline std::atomic WeChatDll { 0 }; + +template inline T getFunction(std::uintptr_t offset) { return reinterpret_cast(WeChatDll + offset); } +template inline T getFunction(std::uintptr_t base, std::uintptr_t offset) +{ + return reinterpret_cast(base + offset); +} + +int Init(void *args); +void Cleanup(); +}