From b8393e1e74b5f1b1ebeb62d99d2c500596f103ca Mon Sep 17 00:00:00 2001 From: Changhua Date: Mon, 15 Apr 2024 21:42:04 +0800 Subject: [PATCH 01/25] Port to x64 --- WeChatFerry/WeChatFerry.sln | 24 +++++------ WeChatFerry/sdk/SDK.vcxproj | 24 +++++++++-- WeChatFerry/spy/Spy.vcxproj | 62 ++++++++++++++++++++++++--- WeChatFerry/spy/chatroom_mgmt.cpp | 3 +- WeChatFerry/spy/contact_mgmt.cpp | 3 +- WeChatFerry/spy/exec_sql.cpp | 3 +- WeChatFerry/spy/funcs.cpp | 3 +- WeChatFerry/spy/receive_msg.cpp | 3 +- WeChatFerry/spy/receive_transfer.cpp | 3 +- WeChatFerry/spy/rpc_server.cpp | 8 ++-- WeChatFerry/spy/send_msg.cpp | 3 +- WeChatFerry/spy/spy.aps | Bin 2612 -> 2612 bytes WeChatFerry/spy/spy.rc | 8 ++-- WeChatFerry/wcf/wcf.vcxproj | 19 +++++++- 14 files changed, 127 insertions(+), 39 deletions(-) diff --git a/WeChatFerry/WeChatFerry.sln b/WeChatFerry/WeChatFerry.sln index 8e49373..4573c46 100644 --- a/WeChatFerry/WeChatFerry.sln +++ b/WeChatFerry/WeChatFerry.sln @@ -17,20 +17,20 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wcf", "wcf\wcf.vcxproj", "{ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x86 = Debug|x86 - Release|x86 = Release|x86 + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Debug|x86.ActiveCfg = Debug|Win32 - {4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Debug|x86.Build.0 = Debug|Win32 - {4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Release|x86.ActiveCfg = Release|Win32 - {4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Release|x86.Build.0 = Release|Win32 - {ABFCB647-137F-478B-A73E-F0B1E3ADC215}.Debug|x86.ActiveCfg = Release|Win32 - {ABFCB647-137F-478B-A73E-F0B1E3ADC215}.Release|x86.ActiveCfg = Release|Win32 - {ABFCB647-137F-478B-A73E-F0B1E3ADC215}.Release|x86.Build.0 = Release|Win32 - {02747CE0-AD9F-4812-B019-FCF9867F7514}.Debug|x86.ActiveCfg = Release|Win32 - {02747CE0-AD9F-4812-B019-FCF9867F7514}.Release|x86.ActiveCfg = Release|Win32 - {02747CE0-AD9F-4812-B019-FCF9867F7514}.Release|x86.Build.0 = Release|Win32 + {4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Debug|x64.ActiveCfg = Debug|x64 + {4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Debug|x64.Build.0 = Debug|x64 + {4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Release|x64.ActiveCfg = Release|x64 + {4DE80B82-5F6A-4C4C-9D16-1574308110FA}.Release|x64.Build.0 = Release|x64 + {ABFCB647-137F-478B-A73E-F0B1E3ADC215}.Debug|x64.ActiveCfg = Debug|x64 + {ABFCB647-137F-478B-A73E-F0B1E3ADC215}.Release|x64.ActiveCfg = Release|x64 + {ABFCB647-137F-478B-A73E-F0B1E3ADC215}.Release|x64.Build.0 = Release|x64 + {02747CE0-AD9F-4812-B019-FCF9867F7514}.Debug|x64.ActiveCfg = Debug|x64 + {02747CE0-AD9F-4812-B019-FCF9867F7514}.Release|x64.ActiveCfg = Release|x64 + {02747CE0-AD9F-4812-B019-FCF9867F7514}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/WeChatFerry/sdk/SDK.vcxproj b/WeChatFerry/sdk/SDK.vcxproj index d781815..b8bd869 100644 --- a/WeChatFerry/sdk/SDK.vcxproj +++ b/WeChatFerry/sdk/SDK.vcxproj @@ -86,6 +86,10 @@ true x86-windows-static + + true + x64-windows-static + Level3 @@ -154,19 +158,31 @@ true true true - NDEBUG;SDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + WIN32;NDEBUG;SDK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true - Use - pch.h + NotUsing + + + stdcpp17 + $(SolutionDir)spy;C:\Tools\vcpkg\installed\x64-windows-static\include + + true + MultiThreaded Windows true true - true + false false sdk.def + + xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)Out + + + Copy files + diff --git a/WeChatFerry/spy/Spy.vcxproj b/WeChatFerry/spy/Spy.vcxproj index f3ca5a3..4c1d724 100644 --- a/WeChatFerry/spy/Spy.vcxproj +++ b/WeChatFerry/spy/Spy.vcxproj @@ -94,6 +94,12 @@ true Release + + true + + + true + Level3 @@ -191,10 +197,20 @@ $(SolutionDir)rpc\tool\protoc --nanopb_out=. wcf.proto Level3 true - _DEBUG;SPY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + WIN32;NDEBUG;SPY_EXPORTS;_WINDOWS;_USRDLL;ENABLE_DEBUG_LOG;%(PreprocessorDefinitions) true - Use - pch.h + NotUsing + + + stdcpp17 + $(SolutionDir)rpc;$(SolutionDir)rpc\nanopb;$(SolutionDir)rpc\proto;$(SolutionDir)smc;$(SolutionDir)spy;C:\Tools\vcpkg\installed\x64-windows-static\include + true + false + MultiThreadedDebug + true + + 4251;4731;4819 + /EHa %(AdditionalOptions) Windows @@ -202,7 +218,28 @@ $(SolutionDir)rpc\tool\protoc --nanopb_out=. wcf.proto false spy.def /ignore:4099 %(AdditionalOptions) + $(SolutionDir)smc;%(AdditionalLibraryDirectories) + iphlpapi.lib;wsock32.lib;ws2_32.lib;crypt32.lib;Codec.lib;%(AdditionalDependencies) + true + + cd $(SolutionDir)rpc\proto +$(SolutionDir)rpc\tool\protoc --nanopb_out=. wcf.proto + + + Generating PB files + + + if not exist $(SolutionDir)Out md $(SolutionDir)Out +xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)Out +xcopy /y $(OutDir)$(TargetName).exp $(SolutionDir)Out +xcopy /y $(OutDir)$(TargetName).lib $(SolutionDir)Out +xcopy /y $(OutDir)$(TargetName).pdb $(SolutionDir)Out +xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferry + + + Copy spy.dll + @@ -210,18 +247,29 @@ $(SolutionDir)rpc\tool\protoc --nanopb_out=. wcf.proto true true true - NDEBUG;SPY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + WIN32;NDEBUG;SPY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true - Use - pch.h + NotUsing + + + stdcpp17 + $(SolutionDir)rpc;$(SolutionDir)rpc\nanopb;$(SolutionDir)rpc\proto;$(SolutionDir)smc;$(SolutionDir)spy;C:\Tools\vcpkg\installed\x64-windows-static\include + false + + 4251;4731;4819 + /EHa %(AdditionalOptions) + MultiThreaded Windows true true - true + false false spy.def + $(SolutionDir)smc;%(AdditionalLibraryDirectories) + iphlpapi.lib;wsock32.lib;ws2_32.lib;crypt32.lib;Codec.lib;%(AdditionalDependencies) + /ignore:4099 %(AdditionalOptions) diff --git a/WeChatFerry/spy/chatroom_mgmt.cpp b/WeChatFerry/spy/chatroom_mgmt.cpp index 5b32ffb..25bafcd 100644 --- a/WeChatFerry/spy/chatroom_mgmt.cpp +++ b/WeChatFerry/spy/chatroom_mgmt.cpp @@ -11,7 +11,7 @@ using namespace std; extern WxCalls_t g_WxCalls; extern DWORD g_WeChatWinDllAddr; - +#if 0 int AddChatroomMember(string roomid, string wxids) { if (roomid.empty() || wxids.empty()) { @@ -178,3 +178,4 @@ int InviteChatroomMember(string roomid, string wxids) } return 1; } +#endif diff --git a/WeChatFerry/spy/contact_mgmt.cpp b/WeChatFerry/spy/contact_mgmt.cpp index a88a178..28bbaa4 100644 --- a/WeChatFerry/spy/contact_mgmt.cpp +++ b/WeChatFerry/spy/contact_mgmt.cpp @@ -8,7 +8,7 @@ using namespace std; extern WxCalls_t g_WxCalls; extern DWORD g_WeChatWinDllAddr; - +#if 0 #define FEAT_LEN 5 static const uint8_t FEAT_COUNTRY[FEAT_LEN] = { 0xA4, 0xD9, 0x02, 0x4A, 0x18 }; static const uint8_t FEAT_PROVINCE[FEAT_LEN] = { 0xE2, 0xEA, 0xA8, 0xD1, 0x18 }; @@ -183,3 +183,4 @@ RpcContact_t GetContactByWxid(string wxid) return contact; } +#endif diff --git a/WeChatFerry/spy/exec_sql.cpp b/WeChatFerry/spy/exec_sql.cpp index 65e886b..04b4521 100644 --- a/WeChatFerry/spy/exec_sql.cpp +++ b/WeChatFerry/spy/exec_sql.cpp @@ -20,7 +20,7 @@ extern DWORD g_WeChatWinDllAddr; typedef map dbMap_t; static dbMap_t dbMap; - +#if 0 static void GetDbHandle(DWORD base, DWORD offset) { wchar_t *wsp; @@ -225,3 +225,4 @@ vector GetAudioData(uint64_t id) return vector(); } +#endif diff --git a/WeChatFerry/spy/funcs.cpp b/WeChatFerry/spy/funcs.cpp index 322133c..eeb63f0 100644 --- a/WeChatFerry/spy/funcs.cpp +++ b/WeChatFerry/spy/funcs.cpp @@ -24,7 +24,7 @@ namespace fs = std::filesystem; extern bool gIsListeningPyq; extern WxCalls_t g_WxCalls; extern DWORD g_WeChatWinDllAddr; - +#if 0 static string get_key(uint8_t header1, uint8_t header2, uint8_t *key) { // PNG? @@ -443,3 +443,4 @@ string GetLoginUrl() } return "http://weixin.qq.com/x/" + string(url); } +#endif diff --git a/WeChatFerry/spy/receive_msg.cpp b/WeChatFerry/spy/receive_msg.cpp index 91fa118..b9aba4e 100644 --- a/WeChatFerry/spy/receive_msg.cpp +++ b/WeChatFerry/spy/receive_msg.cpp @@ -31,7 +31,7 @@ static DWORD recvPyqHookAddr = 0; static DWORD recvPyqCallAddr = 0; static DWORD recvPyqJumpBackAddr = 0; static CHAR recvPyqBackupCode[5] = { 0 }; - +#if 0 MsgTypes_t GetMsgTypes() { const MsgTypes_t m = { @@ -259,3 +259,4 @@ void UnListenPyq() UnHookAddress(recvPyqHookAddr, recvPyqBackupCode); gIsListeningPyq = false; } +#endif diff --git a/WeChatFerry/spy/receive_transfer.cpp b/WeChatFerry/spy/receive_transfer.cpp index a31960d..5b66bb9 100644 --- a/WeChatFerry/spy/receive_transfer.cpp +++ b/WeChatFerry/spy/receive_transfer.cpp @@ -7,7 +7,7 @@ using namespace std; extern WxCalls_t g_WxCalls; extern DWORD g_WeChatWinDllAddr; - +#if 0 int ReceiveTransfer(string wxid, string transferid, string transactionid) { int rv = 0; @@ -53,3 +53,4 @@ int ReceiveTransfer(string wxid, string transferid, string transactionid) return rv; } +#endif diff --git a/WeChatFerry/spy/rpc_server.cpp b/WeChatFerry/spy/rpc_server.cpp index 72eb6fb..f1816a6 100644 --- a/WeChatFerry/spy/rpc_server.cpp +++ b/WeChatFerry/spy/rpc_server.cpp @@ -53,7 +53,7 @@ static DWORD lThreadId = 0; static bool lIsRunning = false; static nng_socket cmdSock, msgSock; // TODO: 断开检测 static uint8_t gBuffer[G_BUF_SIZE] = { 0 }; - +#if 0 bool func_is_login(uint8_t *out, size_t *len) { Response rsp = Response_init_default; @@ -837,7 +837,7 @@ bool func_invite_room_members(char *roomid, char *wxids, uint8_t *out, size_t *l return true; } - +#endif static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len) { bool ret = false; @@ -850,6 +850,7 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len } LOG_DEBUG("{:#04x}[{}] length: {}", (uint8_t)req.func, magic_enum::enum_name(req.func), in_len); +#if 0 switch (req.func) { case Functions_FUNC_IS_LOGIN: { ret = func_is_login(out, out_len); @@ -982,6 +983,7 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len break; } } +#endif pb_release(Request_fields, &req); return ret; } @@ -1065,7 +1067,7 @@ int RpcStopServer() if (lIsRunning) { nng_close(cmdSock); nng_close(msgSock); - UnListenMessage(); + // UnListenMessage(); lIsRunning = false; Sleep(1000); LOG_INFO("Server stoped."); diff --git a/WeChatFerry/spy/send_msg.cpp b/WeChatFerry/spy/send_msg.cpp index ab45561..2e2f57c 100644 --- a/WeChatFerry/spy/send_msg.cpp +++ b/WeChatFerry/spy/send_msg.cpp @@ -12,7 +12,7 @@ extern HANDLE g_hEvent; extern WxCalls_t g_WxCalls; extern DWORD g_WeChatWinDllAddr; extern string GetSelfWxid(); // Defined in spy.cpp - +#if 0 void SendTextMessage(string wxid, string msg, string atWxids) { int success = 0; @@ -438,3 +438,4 @@ int ForwardMessage(uint64_t msgid, string receiver) return status; } +#endif diff --git a/WeChatFerry/spy/spy.aps b/WeChatFerry/spy/spy.aps index 5fd638a3d071e3ba543c77d37d7edb4f22fda654..d525acb344e2a225385793d71ba024340800da17 100644 GIT binary patch delta 73 zcmdlYvPEP88$Tn1Is*uBGB7g;GjL7jXS>L3#K1ZEF`F{CA%h-+0T?q(7G!_VYyp&K T=FsFc1dAFnSZ+4u_|FIcx-1NR delta 73 zcmdlYvPEP88$SbsIs*d(F9Rn7GlMt-(`0_Oi_9hrT$3NODRUbz=rI^F7z0Uz$%5?f anavnDCo^+savA|ejDX?{n@u_XGXem>?hJ$g diff --git a/WeChatFerry/spy/spy.rc b/WeChatFerry/spy/spy.rc index f50e642..2aa2b4a 100644 --- a/WeChatFerry/spy/spy.rc +++ b/WeChatFerry/spy/spy.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 39,0,13,0 - PRODUCTVERSION 3,9,2,23 + FILEVERSION 39,1,0,0 + PRODUCTVERSION 3,9,10,19 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,12 +69,12 @@ BEGIN BEGIN VALUE "CompanyName", "WeChatFerry" VALUE "FileDescription", "WeChatFerry" - VALUE "FileVersion", "39.0.13.0" + VALUE "FileVersion", "39.1.0.0" VALUE "InternalName", "spy.dll" VALUE "LegalCopyright", "Copyright (C) 2023" VALUE "OriginalFilename", "spy.dll" VALUE "ProductName", "WeChatFerry" - VALUE "ProductVersion", "3.9.2.23" + VALUE "ProductVersion", "3.9.10.19" END END BLOCK "VarFileInfo" diff --git a/WeChatFerry/wcf/wcf.vcxproj b/WeChatFerry/wcf/wcf.vcxproj index 1f9b67f..f156940 100644 --- a/WeChatFerry/wcf/wcf.vcxproj +++ b/WeChatFerry/wcf/wcf.vcxproj @@ -86,6 +86,10 @@ true x86-windows-static + + true + x64-windows-static + Level3 @@ -143,15 +147,26 @@ xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferrytrue true true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;WCF;%(PreprocessorDefinitions) true + stdcpp17 + $(SolutionDir)sdk;$(SolutionDir)spy;C:\Tools\vcpkg\installed\x64-windows-static\include + MultiThreaded + 4996 Console true true - true + false + + xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)Out +xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferry + + + Copy files + From 651ab8959d3b61d218a6f447283b12950acb94d2 Mon Sep 17 00:00:00 2001 From: Changhua Date: Tue, 16 Apr 2024 19:42:40 +0800 Subject: [PATCH 02/25] Refactoring --- WeChatFerry/WeChatFerry.sln | 8 -- WeChatFerry/{spy => com}/log.cpp | 2 +- WeChatFerry/{spy => com}/log.h | 0 WeChatFerry/{spy => com}/util.cpp | 0 WeChatFerry/{spy => com}/util.h | 0 WeChatFerry/sdk/SDK.vcxproj | 10 +- WeChatFerry/sdk/SDK.vcxproj.filters | 24 ++-- WeChatFerry/sdk/injector.cpp | 55 ++++---- WeChatFerry/sdk/sdk.cpp | 23 ++-- WeChatFerry/spy/Spy.vcxproj | 27 +++- WeChatFerry/spy/Spy.vcxproj.filters | 24 ++-- WeChatFerry/spy/spy.cpp | 5 +- WeChatFerry/spy/spy_types.h | 4 +- WeChatFerry/wcf/main.cpp | 34 ----- WeChatFerry/wcf/wcf.vcxproj | 188 ---------------------------- WeChatFerry/wcf/wcf.vcxproj.filters | 51 -------- WeChatFerry/wcf/wcf.vcxproj.user | 4 - 17 files changed, 100 insertions(+), 359 deletions(-) rename WeChatFerry/{spy => com}/log.cpp (94%) rename WeChatFerry/{spy => com}/log.h (100%) rename WeChatFerry/{spy => com}/util.cpp (100%) rename WeChatFerry/{spy => com}/util.h (100%) delete mode 100644 WeChatFerry/wcf/main.cpp delete mode 100644 WeChatFerry/wcf/wcf.vcxproj delete mode 100644 WeChatFerry/wcf/wcf.vcxproj.filters delete mode 100644 WeChatFerry/wcf/wcf.vcxproj.user diff --git a/WeChatFerry/WeChatFerry.sln b/WeChatFerry/WeChatFerry.sln index 4573c46..2122ba1 100644 --- a/WeChatFerry/WeChatFerry.sln +++ b/WeChatFerry/WeChatFerry.sln @@ -10,11 +10,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdk", "sdk\sdk.vcxproj", "{ {4DE80B82-5F6A-4C4C-9D16-1574308110FA} = {4DE80B82-5F6A-4C4C-9D16-1574308110FA} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wcf", "wcf\wcf.vcxproj", "{02747CE0-AD9F-4812-B019-FCF9867F7514}" - ProjectSection(ProjectDependencies) = postProject - {4DE80B82-5F6A-4C4C-9D16-1574308110FA} = {4DE80B82-5F6A-4C4C-9D16-1574308110FA} - EndProjectSection -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -28,9 +23,6 @@ Global {ABFCB647-137F-478B-A73E-F0B1E3ADC215}.Debug|x64.ActiveCfg = Debug|x64 {ABFCB647-137F-478B-A73E-F0B1E3ADC215}.Release|x64.ActiveCfg = Release|x64 {ABFCB647-137F-478B-A73E-F0B1E3ADC215}.Release|x64.Build.0 = Release|x64 - {02747CE0-AD9F-4812-B019-FCF9867F7514}.Debug|x64.ActiveCfg = Debug|x64 - {02747CE0-AD9F-4812-B019-FCF9867F7514}.Release|x64.ActiveCfg = Release|x64 - {02747CE0-AD9F-4812-B019-FCF9867F7514}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/WeChatFerry/spy/log.cpp b/WeChatFerry/com/log.cpp similarity index 94% rename from WeChatFerry/spy/log.cpp rename to WeChatFerry/com/log.cpp index 6242800..e06c0e9 100644 --- a/WeChatFerry/spy/log.cpp +++ b/WeChatFerry/com/log.cpp @@ -40,7 +40,7 @@ static char buf[BUF_SIZE] = { 0 }; void log_buffer(uint8_t *buffer, size_t len) { - size_t j = sprintf_s(buf, BUF_SIZE, "BUF@%08X[%ld]: ", (uint32_t)buffer, len); + size_t j = sprintf_s(buf, BUF_SIZE, "BUF@%p[%zd]: ", buffer, len); for (size_t i = 0; i < len; i++) { j += sprintf_s(buf + j, BUF_SIZE, "%02X ", buffer[i]); if (j > BUF_SIZE - 3) { diff --git a/WeChatFerry/spy/log.h b/WeChatFerry/com/log.h similarity index 100% rename from WeChatFerry/spy/log.h rename to WeChatFerry/com/log.h diff --git a/WeChatFerry/spy/util.cpp b/WeChatFerry/com/util.cpp similarity index 100% rename from WeChatFerry/spy/util.cpp rename to WeChatFerry/com/util.cpp diff --git a/WeChatFerry/spy/util.h b/WeChatFerry/com/util.h similarity index 100% rename from WeChatFerry/spy/util.h rename to WeChatFerry/com/util.h diff --git a/WeChatFerry/sdk/SDK.vcxproj b/WeChatFerry/sdk/SDK.vcxproj index b8bd869..be6bfb4 100644 --- a/WeChatFerry/sdk/SDK.vcxproj +++ b/WeChatFerry/sdk/SDK.vcxproj @@ -164,7 +164,7 @@ stdcpp17 - $(SolutionDir)spy;C:\Tools\vcpkg\installed\x64-windows-static\include + $(SolutionDir)com;$(SolutionDir)spy;C:\Tools\vcpkg\installed\x64-windows-static\include true MultiThreaded @@ -185,15 +185,15 @@ - - + + - - + + diff --git a/WeChatFerry/sdk/SDK.vcxproj.filters b/WeChatFerry/sdk/SDK.vcxproj.filters index 8f8a4a5..f38f11a 100644 --- a/WeChatFerry/sdk/SDK.vcxproj.filters +++ b/WeChatFerry/sdk/SDK.vcxproj.filters @@ -21,32 +21,32 @@ 头文件 - - 头文件 - - - 头文件 - 头文件 + + 头文件 + + + 头文件 + 源文件 - - 源文件 - - - 源文件 - 源文件 源文件 + + 源文件 + + + 源文件 + diff --git a/WeChatFerry/sdk/injector.cpp b/WeChatFerry/sdk/injector.cpp index 9146f49..fa67e55 100644 --- a/WeChatFerry/sdk/injector.cpp +++ b/WeChatFerry/sdk/injector.cpp @@ -1,22 +1,5 @@ #include "injector.h" -typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL); - -static void ShowErrorMessage(DWORD dwError, HANDLE hProcess) -{ - BOOL bIsWow64 = FALSE; - WCHAR szErrorMessage[256] = { 0 }; - LPFN_ISWOW64PROCESS fnIsWow64Process - = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process"); - if (fnIsWow64Process != NULL && fnIsWow64Process(hProcess, &bIsWow64)) { - if (bIsWow64) { - wsprintf(szErrorMessage, L"LoadLibrary 调用失败,请检查应用版本/位数。错误码: %lu", dwError); - } - } - wsprintf(szErrorMessage, L"LoadLibrary 调用失败。错误码: %lu", dwError); - MessageBox(NULL, szErrorMessage, L"InjectDll", 0); -} - HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase) { HANDLE hThread; @@ -39,9 +22,20 @@ HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase) WriteProcessMemory(hProcess, pRemoteAddress, dllPath, cszDLL, NULL); // 3. 创建一个远程线程,让目标进程调用 LoadLibrary - hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibrary, pRemoteAddress, 0, NULL); + HMODULE k32 = GetModuleHandle(L"kernel32.dll"); + if (k32 == NULL) { + MessageBox(NULL, L"获取 kernel32 失败", L"InjectDll", 0); + return NULL; + } + + FARPROC libAddr = GetProcAddress(k32, "LoadLibraryW"); + if (!libAddr) { + MessageBox(NULL, L"获取 LoadLibrary 失败", L"InjectDll", 0); + return NULL; + } + + hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)libAddr, pRemoteAddress, 0, NULL); if (hThread == NULL) { - ShowErrorMessage(GetLastError(), hProcess); VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE); CloseHandle(hProcess); @@ -49,7 +43,7 @@ HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase) } WaitForSingleObject(hThread, -1); - GetExitCodeThread(hThread, (LPDWORD)injectedBase); + // GetExitCodeThread(hThread, (LPDWORD)injectedBase); CloseHandle(hThread); VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE); // CloseHandle(hProcess); // Close when exit @@ -62,7 +56,18 @@ bool EjectDll(HANDLE process, HMODULE dllBase) HANDLE hThread = NULL; // 使目标进程调用 FreeLibrary,卸载 DLL - hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)FreeLibrary, (LPVOID)dllBase, 0, NULL); + HMODULE k32 = GetModuleHandle(L"kernel32.dll"); + if (k32 == NULL) { + MessageBox(NULL, L"获取 kernel32 失败", L"InjectDll", 0); + return NULL; + } + + FARPROC libAddr = GetProcAddress(k32, "FreeLibrary"); + if (!libAddr) { + MessageBox(NULL, L"获取 FreeLibrary 失败", L"InjectDll", 0); + return NULL; + } + hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)libAddr, (LPVOID)dllBase, 0, NULL); if (hThread == NULL) { MessageBox(NULL, L"FreeLibrary 调用失败!", L"EjectDll", 0); return false; @@ -81,8 +86,8 @@ static void *GetFuncAddr(LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName) return NULL; } - void *absAddr = GetProcAddress(hLoaded, funcName); - DWORD offset = (DWORD)absAddr - (DWORD)hLoaded; + void *absAddr = GetProcAddress(hLoaded, funcName); + DWORD offset = (DWORD)absAddr - (DWORD)hLoaded; FreeLibrary(hLoaded); @@ -102,7 +107,7 @@ bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcNa } WaitForSingleObject(hThread, INFINITE); if (ret != NULL) { - GetExitCodeThread(hThread, ret); + GetExitCodeThread(hThread, (LPDWORD)ret); } CloseHandle(hThread); @@ -134,7 +139,7 @@ bool CallDllFuncEx(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR func WaitForSingleObject(hThread, INFINITE); VirtualFree(pRemoteAddress, 0, MEM_RELEASE); if (ret != NULL) { - GetExitCodeThread(hThread, ret); + GetExitCodeThread(hThread, (LPDWORD)ret); } CloseHandle(hThread); diff --git a/WeChatFerry/sdk/sdk.cpp b/WeChatFerry/sdk/sdk.cpp index 0b996bc..b657403 100644 --- a/WeChatFerry/sdk/sdk.cpp +++ b/WeChatFerry/sdk/sdk.cpp @@ -17,16 +17,16 @@ static WCHAR spyDllPath[MAX_PATH] = { 0 }; static int GetDllPath(bool debug, wchar_t *dllPath) { - GetModuleFileName(GetModuleHandle(WECHATSDKDLL), spyDllPath, MAX_PATH); - PathRemoveFileSpec(spyDllPath); + GetModuleFileName(GetModuleHandle(WECHATSDKDLL), dllPath, MAX_PATH); + PathRemoveFileSpec(dllPath); if (debug) { - PathAppend(spyDllPath, WECHATINJECTDLL_DEBUG); + PathAppend(dllPath, WECHATINJECTDLL_DEBUG); } else { - PathAppend(spyDllPath, WECHATINJECTDLL); + PathAppend(dllPath, WECHATINJECTDLL); } - if (!PathFileExists(spyDllPath)) { - MessageBox(NULL, spyDllPath, L"文件不存在", 0); + if (!PathFileExists(dllPath)) { + MessageBox(NULL, dllPath, L"文件不存在", 0); return ERROR_FILE_NOT_FOUND; } @@ -56,14 +56,17 @@ int WxInitSDK(bool debug, int port) return -1; } + return 0; + PortPath_t pp = { 0 }; pp.port = port; sprintf_s(pp.path, MAX_PATH, "%s", std::filesystem::current_path().string().c_str()); - if (!CallDllFuncEx(wcProcess, spyDllPath, spyBase, "InitSpy", (LPVOID)&pp, sizeof(PortPath_t), NULL)) { - MessageBox(NULL, L"初始化失败", L"WxInitSDK", 0); - return -1; - } + MessageBoxA(NULL, pp.path, "WxInitSDK", 0); + // if (!CallDllFuncEx(wcProcess, spyDllPath, spyBase, "InitSpy", (LPVOID)&pp, sizeof(PortPath_t), NULL)) { + // MessageBox(NULL, L"初始化失败", L"WxInitSDK", 0); + // return -1; + // } #ifdef WCF FILE *fd = fopen(WCF_LOCK, "wb"); diff --git a/WeChatFerry/spy/Spy.vcxproj b/WeChatFerry/spy/Spy.vcxproj index 4c1d724..c81c7d0 100644 --- a/WeChatFerry/spy/Spy.vcxproj +++ b/WeChatFerry/spy/Spy.vcxproj @@ -83,6 +83,7 @@ true + $(ProjectName)_debug false @@ -203,7 +204,7 @@ $(SolutionDir)rpc\tool\protoc --nanopb_out=. wcf.proto stdcpp17 - $(SolutionDir)rpc;$(SolutionDir)rpc\nanopb;$(SolutionDir)rpc\proto;$(SolutionDir)smc;$(SolutionDir)spy;C:\Tools\vcpkg\installed\x64-windows-static\include + $(SolutionDir)com;$(SolutionDir)rpc;$(SolutionDir)rpc\nanopb;$(SolutionDir)rpc\proto;$(SolutionDir)smc;$(SolutionDir)spy;C:\Tools\vcpkg\installed\x64-windows-static\include true false MultiThreadedDebug @@ -253,7 +254,7 @@ xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferry stdcpp17 - $(SolutionDir)rpc;$(SolutionDir)rpc\nanopb;$(SolutionDir)rpc\proto;$(SolutionDir)smc;$(SolutionDir)spy;C:\Tools\vcpkg\installed\x64-windows-static\include + $(SolutionDir)com;$(SolutionDir)rpc;$(SolutionDir)rpc\nanopb;$(SolutionDir)rpc\proto;$(SolutionDir)smc;$(SolutionDir)spy;C:\Tools\vcpkg\installed\x64-windows-static\include false 4251;4731;4819 @@ -271,8 +272,24 @@ xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferryiphlpapi.lib;wsock32.lib;ws2_32.lib;crypt32.lib;Codec.lib;%(AdditionalDependencies) /ignore:4099 %(AdditionalOptions) + + Generating PB files + cd $(SolutionDir)rpc\proto +$(SolutionDir)rpc\tool\protoc --nanopb_out=. wcf.proto + + + Copy spy.dll + if not exist $(SolutionDir)Out md $(SolutionDir)Out +xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)Out +xcopy /y $(OutDir)$(TargetName).exp $(SolutionDir)Out +xcopy /y $(OutDir)$(TargetName).lib $(SolutionDir)Out +xcopy /y $(OutDir)$(TargetName).pdb $(SolutionDir)Out +xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferry + + + @@ -287,7 +304,6 @@ xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferry - @@ -297,9 +313,10 @@ xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferry - + + @@ -311,14 +328,12 @@ xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferry - - diff --git a/WeChatFerry/spy/Spy.vcxproj.filters b/WeChatFerry/spy/Spy.vcxproj.filters index 1574f30..8bd6b31 100644 --- a/WeChatFerry/spy/Spy.vcxproj.filters +++ b/WeChatFerry/spy/Spy.vcxproj.filters @@ -24,9 +24,6 @@ 头文件 - - 头文件 - 头文件 @@ -48,9 +45,6 @@ 头文件 - - 头文件 - nnrpc @@ -93,6 +87,12 @@ 头文件 + + 头文件 + + + 头文件 + @@ -101,9 +101,6 @@ 源文件 - - 源文件 - 源文件 @@ -122,9 +119,6 @@ 源文件 - - 源文件 - nnrpc @@ -152,6 +146,12 @@ 源文件 + + 源文件 + + + 源文件 + diff --git a/WeChatFerry/spy/spy.cpp b/WeChatFerry/spy/spy.cpp index 55c98ba..ffabb53 100644 --- a/WeChatFerry/spy/spy.cpp +++ b/WeChatFerry/spy/spy.cpp @@ -11,6 +11,8 @@ DWORD g_WeChatWinDllAddr = 0; void InitSpy(LPVOID args) { + MessageBox(NULL, L"InitSpy", L"InitSpy", 0); +#if 0 wchar_t version[16] = { 0 }; PortPath_t *pp = (PortPath_t *)args; int port = pp->port; @@ -35,8 +37,9 @@ void InitSpy(LPVOID args) } RpcStartServer(port); +#endif } -void CleanupSpy() { RpcStopServer(); } +void CleanupSpy() { /*RpcStopServer();*/ } int IsLogin(void) { return (int)GET_DWORD(g_WeChatWinDllAddr + g_WxCalls.login); } diff --git a/WeChatFerry/spy/spy_types.h b/WeChatFerry/spy/spy_types.h index 08fa4ae..2bb396a 100644 --- a/WeChatFerry/spy/spy_types.h +++ b/WeChatFerry/spy/spy_types.h @@ -206,8 +206,8 @@ struct WxString { WxString(std::wstring &ws) { wptr = ws.c_str(); - size = ws.size(); - capacity = ws.capacity(); + size = (DWORD)ws.size(); + capacity = (DWORD)ws.capacity(); ptr = NULL; clen = 0; } diff --git a/WeChatFerry/wcf/main.cpp b/WeChatFerry/wcf/main.cpp deleted file mode 100644 index 43d797b..0000000 --- a/WeChatFerry/wcf/main.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include -#include - -#include "sdk.h" - -void help() -{ - printf("\nUsage: \n启动: wcf.exe start port [debug]\n关闭: wcf.exe stop\nport: 命令端口, 消息端口为命令端口+1\n"); -} - -int main(int argc, char *argv[]) -{ - int ret = -1; - bool debug = false; - - if ((argc < 2) || (argc > 4)) { - help(); - } else if (argc == 4) { - debug = (strcmp(argv[3], "debug") == 0); - } - - if (strcmp(argv[1], "start") == 0) { - int port = strtol(argv[2], NULL, 10); - - ret = WxInitSDK(debug, port); - } else if (strcmp(argv[1], "stop") == 0) { - ret = WxDestroySDK(); - } else { - help(); - } - - return ret; -} diff --git a/WeChatFerry/wcf/wcf.vcxproj b/WeChatFerry/wcf/wcf.vcxproj deleted file mode 100644 index f156940..0000000 --- a/WeChatFerry/wcf/wcf.vcxproj +++ /dev/null @@ -1,188 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 16.0 - Win32Proj - {02747ce0-ad9f-4812-b019-fcf9867f7514} - wcf - 10.0 - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - - - false - - - true - - - false - - - true - x86-windows-static - - - true - x64-windows-static - - - - Level3 - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_CONSOLE;WCF;%(PreprocessorDefinitions) - true - $(SolutionDir)sdk;$(SolutionDir)spy;C:\Tools\vcpkg\installed\x86-windows-static\include - MultiThreaded - stdcpp17 - 4996 - - - Console - true - true - true - - - xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)Out -xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferry - - - Copy files - - - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_CONSOLE;WCF;%(PreprocessorDefinitions) - true - stdcpp17 - $(SolutionDir)sdk;$(SolutionDir)spy;C:\Tools\vcpkg\installed\x64-windows-static\include - MultiThreaded - 4996 - - - Console - true - true - false - - - xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)Out -xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferry - - - Copy files - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/WeChatFerry/wcf/wcf.vcxproj.filters b/WeChatFerry/wcf/wcf.vcxproj.filters deleted file mode 100644 index aee99f2..0000000 --- a/WeChatFerry/wcf/wcf.vcxproj.filters +++ /dev/null @@ -1,51 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - - - 源文件 - - - 源文件 - - - 源文件 - - - 源文件 - - - 源文件 - - - \ No newline at end of file diff --git a/WeChatFerry/wcf/wcf.vcxproj.user b/WeChatFerry/wcf/wcf.vcxproj.user deleted file mode 100644 index 88a5509..0000000 --- a/WeChatFerry/wcf/wcf.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file From 5bf45402a8081f180b40ab80314dc70656ad8ccf Mon Sep 17 00:00:00 2001 From: Changhua Date: Wed, 17 Apr 2024 00:35:43 +0800 Subject: [PATCH 03/25] Fix injector --- WeChatFerry/com/util.h | 10 +-- WeChatFerry/sdk/injector.cpp | 116 +++++++++++++++++++++++++++-------- WeChatFerry/sdk/injector.h | 2 +- WeChatFerry/sdk/sdk.cpp | 66 ++++---------------- WeChatFerry/spy/spy.cpp | 8 +-- 5 files changed, 112 insertions(+), 90 deletions(-) diff --git a/WeChatFerry/com/util.h b/WeChatFerry/com/util.h index 5d79b4a..68808a6 100644 --- a/WeChatFerry/com/util.h +++ b/WeChatFerry/com/util.h @@ -2,11 +2,11 @@ #include -#define WECHAREXE L"WeChat.exe" -#define WECHATWINDLL L"WeChatWin.dll" -#define WECHATSDKDLL L"sdk.dll" -#define WECHATINJECTDLL L"spy.dll" -#define WECHATINJECTDLL_DEBUG L"spy_debug.dll" +#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" #define GET_DWORD(addr) ((DWORD) * (DWORD *)(addr)) #define GET_QWORD(addr) ((uint64_t) * (uint64_t *)(addr)) diff --git a/WeChatFerry/sdk/injector.cpp b/WeChatFerry/sdk/injector.cpp index fa67e55..ca84e7d 100644 --- a/WeChatFerry/sdk/injector.cpp +++ b/WeChatFerry/sdk/injector.cpp @@ -1,9 +1,43 @@ -#include "injector.h" +#include "framework.h" +#include "psapi.h" +#include +#include +#include + +#include "injector.h" +#include "util.h" + +HMODULE GetTargetModuleBase(HANDLE process, std::string dll) +{ + DWORD cbNeeded; + HMODULE moduleHandleList[512]; + BOOL ret = EnumProcessModulesEx(process, moduleHandleList, sizeof(moduleHandleList), &cbNeeded, LIST_MODULES_64BIT); + if (!ret) { + MessageBox(NULL, L"获取模块失败", L"GetTargetModuleBase", 0); + return NULL; + } + + if (cbNeeded > sizeof(moduleHandleList)) { + MessageBox(NULL, L"模块数量过多", L"GetTargetModuleBase", 0); + return NULL; + } + DWORD processCount = cbNeeded / sizeof(HMODULE); + + char moduleName[32]; + for (DWORD i = 0; i < processCount; i++) { + GetModuleBaseNameA(process, moduleHandleList[i], moduleName, 32); + if (!strncmp(dll.c_str(), moduleName, dll.size())) { + return moduleHandleList[i]; + } + } + return NULL; +} HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase) { HANDLE hThread; SIZE_T cszDLL = (wcslen(dllPath) + 1) * sizeof(WCHAR); + // 1. 打开目标进程 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); if (hProcess == NULL) { @@ -38,13 +72,17 @@ HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase) if (hThread == NULL) { VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE); CloseHandle(hProcess); - + MessageBox(NULL, L"CreateRemoteThread 失败", L"InjectDll", 0); return NULL; } WaitForSingleObject(hThread, -1); - // GetExitCodeThread(hThread, (LPDWORD)injectedBase); CloseHandle(hThread); + + *injectedBase = GetTargetModuleBase(hProcess, std::filesystem::path(Wstring2String(dllPath)).filename().string()); + + printf("hProcess: %p, pRemoteAddress: %p, injectedBase: %p\n", hProcess, pRemoteAddress, *injectedBase); + VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE); // CloseHandle(hProcess); // Close when exit @@ -55,6 +93,8 @@ bool EjectDll(HANDLE process, HMODULE dllBase) { HANDLE hThread = NULL; + printf("process: %p, dllBase: %p\n", process, dllBase); + // 使目标进程调用 FreeLibrary,卸载 DLL HMODULE k32 = GetModuleHandle(L"kernel32.dll"); if (k32 == NULL) { @@ -62,7 +102,8 @@ bool EjectDll(HANDLE process, HMODULE dllBase) return NULL; } - FARPROC libAddr = GetProcAddress(k32, "FreeLibrary"); + // FARPROC libAddr = GetProcAddress(k32, "FreeLibrary"); + FARPROC libAddr = GetProcAddress(k32, "FreeLibraryAndExitThread"); if (!libAddr) { MessageBox(NULL, L"获取 FreeLibrary 失败", L"InjectDll", 0); return NULL; @@ -79,35 +120,50 @@ bool EjectDll(HANDLE process, HMODULE dllBase) return true; } -static void *GetFuncAddr(LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName) +static LPVOID GetFuncAddr(HMODULE dllBase, LPCSTR funcName) { - HMODULE hLoaded = LoadLibrary(dllPath); - if (hLoaded == NULL) { - return NULL; - } + printf("dllBase: %p, funcName: %s\n", dllBase, funcName); + LPVOID absAddr = GetProcAddress(dllBase, funcName); + UINT64 offset = (UINT64)absAddr - (UINT64)dllBase; - void *absAddr = GetProcAddress(hLoaded, funcName); - DWORD offset = (DWORD)absAddr - (DWORD)hLoaded; - - FreeLibrary(hLoaded); - - return (void *)((DWORD)dllBase + offset); + printf("absAddr: %p, offset: %lld\n", absAddr, offset); + return (LPVOID)((UINT64)dllBase + offset); } -bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPVOID parameter, DWORD *ret) +static UINT64 GetFuncOffset(LPCWSTR dllPath, LPCSTR funcName) { - void *pFunc = GetFuncAddr(dllPath, dllBase, funcName); - if (pFunc == NULL) { - return false; + HMODULE dll = LoadLibrary(dllPath); + if (dll == NULL) { + MessageBox(NULL, L"获取 DLL 失败", L"GetFuncOffset", 0); + return 0; } - HANDLE hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, parameter, 0, NULL); + LPVOID absAddr = GetProcAddress(dll, funcName); + UINT64 offset = (UINT64)absAddr - (UINT64)dll; + FreeLibrary(dll); + + return offset; +} + +bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPDWORD ret) +{ + // LPVOID pFunc = GetFuncAddr(dllBase, funcName); + UINT64 offset = GetFuncOffset(dllPath, funcName); + if (offset == 0) { + return false; + } + UINT64 pFunc = (UINT64)dllBase + GetFuncOffset(dllPath, funcName); + if (pFunc <= (UINT64)dllBase) { + return false; + } + printf("pFunc: %p\n", pFunc); + HANDLE hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, NULL, 0, NULL); if (hThread == NULL) { return false; } WaitForSingleObject(hThread, INFINITE); if (ret != NULL) { - GetExitCodeThread(hThread, (LPDWORD)ret); + GetExitCodeThread(hThread, ret); } CloseHandle(hThread); @@ -115,13 +171,23 @@ bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcNa } bool CallDllFuncEx(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPVOID parameter, size_t sz, - DWORD *ret) + LPDWORD ret) { - void *pFunc = GetFuncAddr(dllPath, dllBase, funcName); - if (pFunc == NULL) { + // LPVOID pFunc = GetFuncAddr(dllBase, funcName); + // if (pFunc == NULL) { + // return false; + // } + + UINT64 offset = GetFuncOffset(dllPath, funcName); + if (offset == 0) { + return false; + } + UINT64 pFunc = (UINT64)dllBase + GetFuncOffset(dllPath, funcName); + if (pFunc <= (UINT64)dllBase) { return false; } + printf("pFunc: %p\n", pFunc); LPVOID pRemoteAddress = VirtualAllocEx(process, NULL, sz, MEM_COMMIT, PAGE_READWRITE); if (pRemoteAddress == NULL) { MessageBox(NULL, L"申请内存失败", L"CallDllFuncEx", 0); @@ -139,7 +205,7 @@ bool CallDllFuncEx(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR func WaitForSingleObject(hThread, INFINITE); VirtualFree(pRemoteAddress, 0, MEM_RELEASE); if (ret != NULL) { - GetExitCodeThread(hThread, (LPDWORD)ret); + GetExitCodeThread(hThread, ret); } CloseHandle(hThread); diff --git a/WeChatFerry/sdk/injector.h b/WeChatFerry/sdk/injector.h index e212a0e..07b4a28 100644 --- a/WeChatFerry/sdk/injector.h +++ b/WeChatFerry/sdk/injector.h @@ -4,6 +4,6 @@ HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase); bool EjectDll(HANDLE process, HMODULE dllBase); -bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPVOID parameter, DWORD *ret); +bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, DWORD *ret); bool CallDllFuncEx(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPVOID parameter, size_t sz, DWORD *ret); diff --git a/WeChatFerry/sdk/sdk.cpp b/WeChatFerry/sdk/sdk.cpp index b657403..50270ef 100644 --- a/WeChatFerry/sdk/sdk.cpp +++ b/WeChatFerry/sdk/sdk.cpp @@ -10,19 +10,19 @@ #define WCF_LOCK ".wcf.lock" -static bool debugMode = false; +static bool dbg = false; static HANDLE wcProcess = NULL; static HMODULE spyBase = NULL; static WCHAR spyDllPath[MAX_PATH] = { 0 }; static int GetDllPath(bool debug, wchar_t *dllPath) { - GetModuleFileName(GetModuleHandle(WECHATSDKDLL), dllPath, MAX_PATH); + GetModuleFileName(GetModuleHandle(WCFSDKDLL), dllPath, MAX_PATH); PathRemoveFileSpec(dllPath); if (debug) { - PathAppend(dllPath, WECHATINJECTDLL_DEBUG); + PathAppend(dllPath, WCFSPYDLL_DEBUG); } else { - PathAppend(dllPath, WECHATINJECTDLL); + PathAppend(dllPath, WCFSPYDLL); } if (!PathFileExists(dllPath)) { @@ -35,6 +35,7 @@ static int GetDllPath(bool debug, wchar_t *dllPath) int WxInitSDK(bool debug, int port) { + dbg = debug; int status = 0; DWORD wcPid = 0; @@ -56,67 +57,22 @@ int WxInitSDK(bool debug, int port) return -1; } - return 0; - PortPath_t pp = { 0 }; pp.port = port; sprintf_s(pp.path, MAX_PATH, "%s", std::filesystem::current_path().string().c_str()); - MessageBoxA(NULL, pp.path, "WxInitSDK", 0); - // if (!CallDllFuncEx(wcProcess, spyDllPath, spyBase, "InitSpy", (LPVOID)&pp, sizeof(PortPath_t), NULL)) { - // MessageBox(NULL, L"初始化失败", L"WxInitSDK", 0); - // return -1; - // } - -#ifdef WCF - FILE *fd = fopen(WCF_LOCK, "wb"); - if (fd == NULL) { - MessageBox(NULL, L"无法打开lock文件", L"WxInitSDK", 0); - return -2; + printf("process: %p, base: %p, path: %s\n", wcProcess, spyBase, pp.path); + if (!CallDllFuncEx(wcProcess, spyDllPath, spyBase, "InitSpy", (LPVOID)&pp, sizeof(PortPath_t), NULL)) { + MessageBox(NULL, L"初始化失败", L"WxInitSDK", 0); + return -1; } - fwrite((uint8_t *)&debug, sizeof(debug), 1, fd); - fwrite((uint8_t *)&spyBase, sizeof(spyBase), 1, fd); - fclose(fd); -#endif - debugMode = debug; + return 0; } int WxDestroySDK() { - int status = 0; -#ifdef WCF - bool debug; - DWORD pid = GetWeChatPid(); - if (pid == 0) { - MessageBox(NULL, L"微信未运行", L"WxDestroySDK", 0); - return status; - } - - wcProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); - if (wcProcess == NULL) { - MessageBox(NULL, L"微信未运行", L"WxDestroySDK", 0); - return -1; - } - - FILE *fd = fopen(WCF_LOCK, "rb"); - if (fd == NULL) { - MessageBox(NULL, L"无法打开lock文件", L"WxDestroySDK", 0); - return -2; - } - fread((uint8_t *)&debug, sizeof(debug), 1, fd); - fread((uint8_t *)&spyBase, sizeof(spyBase), 1, fd); - fclose(fd); - status = GetDllPath(debug, spyDllPath); -#else - status = GetDllPath(debugMode, spyDllPath); -#endif - - if (status != 0) { - return status; - } - - if (!CallDllFunc(wcProcess, spyDllPath, spyBase, "CleanupSpy", NULL, NULL)) { + if (!CallDllFunc(wcProcess, spyDllPath, spyBase, "CleanupSpy", NULL)) { return -1; } diff --git a/WeChatFerry/spy/spy.cpp b/WeChatFerry/spy/spy.cpp index ffabb53..48e73ad 100644 --- a/WeChatFerry/spy/spy.cpp +++ b/WeChatFerry/spy/spy.cpp @@ -12,7 +12,7 @@ DWORD g_WeChatWinDllAddr = 0; void InitSpy(LPVOID args) { MessageBox(NULL, L"InitSpy", L"InitSpy", 0); -#if 0 +#if 1 wchar_t version[16] = { 0 }; PortPath_t *pp = (PortPath_t *)args; int port = pp->port; @@ -21,7 +21,7 @@ void InitSpy(LPVOID args) InitLogger(path); g_WeChatWinDllAddr = (DWORD)GetModuleHandle(L"WeChatWin.dll"); // 获取wechatWin模块地址 if (g_WeChatWinDllAddr == 0) { - LOG_ERROR("获取wechatWin.dll模块地址失败"); + LOG_ERROR("获取 wechatWin.dll 模块地址失败"); return; } @@ -36,10 +36,10 @@ void InitSpy(LPVOID args) return; } - RpcStartServer(port); + // RpcStartServer(port); #endif } -void CleanupSpy() { /*RpcStopServer();*/ } +void CleanupSpy() { /*RpcStopServer();*/ MessageBox(NULL, L"CleanupSpy", L"CleanupSpy", 0);} int IsLogin(void) { return (int)GET_DWORD(g_WeChatWinDllAddr + g_WxCalls.login); } From bd612d22a529fbbb2e3b5fd4363c42adb7fdc520 Mon Sep 17 00:00:00 2001 From: Changhua Date: Wed, 17 Apr 2024 00:45:06 +0800 Subject: [PATCH 04/25] Refatoring --- WeChatFerry/sdk/injector.cpp | 31 +++++-------------------------- WeChatFerry/sdk/sdk.cpp | 1 - WeChatFerry/spy/spy.cpp | 16 ++++++++-------- 3 files changed, 13 insertions(+), 35 deletions(-) diff --git a/WeChatFerry/sdk/injector.cpp b/WeChatFerry/sdk/injector.cpp index ca84e7d..cc06298 100644 --- a/WeChatFerry/sdk/injector.cpp +++ b/WeChatFerry/sdk/injector.cpp @@ -1,13 +1,14 @@ #include "framework.h" #include "psapi.h" #include -#include #include #include "injector.h" #include "util.h" -HMODULE GetTargetModuleBase(HANDLE process, std::string dll) +using namespace std; + +HMODULE GetTargetModuleBase(HANDLE process, string dll) { DWORD cbNeeded; HMODULE moduleHandleList[512]; @@ -79,9 +80,7 @@ HANDLE InjectDll(DWORD pid, LPCWSTR dllPath, HMODULE *injectedBase) WaitForSingleObject(hThread, -1); CloseHandle(hThread); - *injectedBase = GetTargetModuleBase(hProcess, std::filesystem::path(Wstring2String(dllPath)).filename().string()); - - printf("hProcess: %p, pRemoteAddress: %p, injectedBase: %p\n", hProcess, pRemoteAddress, *injectedBase); + *injectedBase = GetTargetModuleBase(hProcess, filesystem::path(Wstring2String(dllPath)).filename().string()); VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE); // CloseHandle(hProcess); // Close when exit @@ -93,8 +92,6 @@ bool EjectDll(HANDLE process, HMODULE dllBase) { HANDLE hThread = NULL; - printf("process: %p, dllBase: %p\n", process, dllBase); - // 使目标进程调用 FreeLibrary,卸载 DLL HMODULE k32 = GetModuleHandle(L"kernel32.dll"); if (k32 == NULL) { @@ -102,7 +99,6 @@ bool EjectDll(HANDLE process, HMODULE dllBase) return NULL; } - // FARPROC libAddr = GetProcAddress(k32, "FreeLibrary"); FARPROC libAddr = GetProcAddress(k32, "FreeLibraryAndExitThread"); if (!libAddr) { MessageBox(NULL, L"获取 FreeLibrary 失败", L"InjectDll", 0); @@ -120,16 +116,6 @@ bool EjectDll(HANDLE process, HMODULE dllBase) return true; } -static LPVOID GetFuncAddr(HMODULE dllBase, LPCSTR funcName) -{ - printf("dllBase: %p, funcName: %s\n", dllBase, funcName); - LPVOID absAddr = GetProcAddress(dllBase, funcName); - UINT64 offset = (UINT64)absAddr - (UINT64)dllBase; - - printf("absAddr: %p, offset: %lld\n", absAddr, offset); - return (LPVOID)((UINT64)dllBase + offset); -} - static UINT64 GetFuncOffset(LPCWSTR dllPath, LPCSTR funcName) { HMODULE dll = LoadLibrary(dllPath); @@ -147,7 +133,6 @@ static UINT64 GetFuncOffset(LPCWSTR dllPath, LPCSTR funcName) bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPDWORD ret) { - // LPVOID pFunc = GetFuncAddr(dllBase, funcName); UINT64 offset = GetFuncOffset(dllPath, funcName); if (offset == 0) { return false; @@ -156,7 +141,7 @@ bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcNa if (pFunc <= (UINT64)dllBase) { return false; } - printf("pFunc: %p\n", pFunc); + HANDLE hThread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, NULL, 0, NULL); if (hThread == NULL) { return false; @@ -173,11 +158,6 @@ bool CallDllFunc(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcNa bool CallDllFuncEx(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR funcName, LPVOID parameter, size_t sz, LPDWORD ret) { - // LPVOID pFunc = GetFuncAddr(dllBase, funcName); - // if (pFunc == NULL) { - // return false; - // } - UINT64 offset = GetFuncOffset(dllPath, funcName); if (offset == 0) { return false; @@ -187,7 +167,6 @@ bool CallDllFuncEx(HANDLE process, LPCWSTR dllPath, HMODULE dllBase, LPCSTR func return false; } - printf("pFunc: %p\n", pFunc); LPVOID pRemoteAddress = VirtualAllocEx(process, NULL, sz, MEM_COMMIT, PAGE_READWRITE); if (pRemoteAddress == NULL) { MessageBox(NULL, L"申请内存失败", L"CallDllFuncEx", 0); diff --git a/WeChatFerry/sdk/sdk.cpp b/WeChatFerry/sdk/sdk.cpp index 50270ef..063be85 100644 --- a/WeChatFerry/sdk/sdk.cpp +++ b/WeChatFerry/sdk/sdk.cpp @@ -61,7 +61,6 @@ int WxInitSDK(bool debug, int port) pp.port = port; sprintf_s(pp.path, MAX_PATH, "%s", std::filesystem::current_path().string().c_str()); - printf("process: %p, base: %p, path: %s\n", wcProcess, spyBase, pp.path); if (!CallDllFuncEx(wcProcess, spyDllPath, spyBase, "InitSpy", (LPVOID)&pp, sizeof(PortPath_t), NULL)) { MessageBox(NULL, L"初始化失败", L"WxInitSDK", 0); return -1; diff --git a/WeChatFerry/spy/spy.cpp b/WeChatFerry/spy/spy.cpp index 48e73ad..2d6382c 100644 --- a/WeChatFerry/spy/spy.cpp +++ b/WeChatFerry/spy/spy.cpp @@ -11,14 +11,11 @@ DWORD g_WeChatWinDllAddr = 0; void InitSpy(LPVOID args) { - MessageBox(NULL, L"InitSpy", L"InitSpy", 0); -#if 1 + wchar_t version[16] = { 0 }; PortPath_t *pp = (PortPath_t *)args; - int port = pp->port; - std::string path(pp->path); - InitLogger(path); + InitLogger(pp->path); g_WeChatWinDllAddr = (DWORD)GetModuleHandle(L"WeChatWin.dll"); // 获取wechatWin模块地址 if (g_WeChatWinDllAddr == 0) { LOG_ERROR("获取 wechatWin.dll 模块地址失败"); @@ -36,10 +33,13 @@ void InitSpy(LPVOID args) return; } - // RpcStartServer(port); -#endif + // RpcStartServer(pp->port); } -void CleanupSpy() { /*RpcStopServer();*/ MessageBox(NULL, L"CleanupSpy", L"CleanupSpy", 0);} +void CleanupSpy() +{ + LOG_DEBUG("CleanupSpy"); + // RpcStopServer(); +} int IsLogin(void) { return (int)GET_DWORD(g_WeChatWinDllAddr + g_WxCalls.login); } From b20e0840c7383120c38efa03e65d67926423638e Mon Sep 17 00:00:00 2001 From: Changhua Date: Thu, 18 Apr 2024 06:49:38 +0800 Subject: [PATCH 05/25] Update version --- WeChatFerry/spy/load_calls.cpp | 3 ++- WeChatFerry/spy/rpc_server.cpp | 6 ++++-- WeChatFerry/spy/spy.cpp | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/WeChatFerry/spy/load_calls.cpp b/WeChatFerry/spy/load_calls.cpp index 4c0cbfe..8d51a77 100644 --- a/WeChatFerry/spy/load_calls.cpp +++ b/WeChatFerry/spy/load_calls.cpp @@ -3,7 +3,8 @@ #include "load_calls.h" -#define SUPPORT_VERSION L"3.9.2.23" +#define SUPPORT_VERSION L"3.9.10.19" + WxCalls_t wxCalls = { 0x2FFD638, // Login Status { 0x2FFD484, 0x2FFD590, 0x2FFD500, 0x30238CC }, // User Info: wxid, nickname, mobile, home diff --git a/WeChatFerry/spy/rpc_server.cpp b/WeChatFerry/spy/rpc_server.cpp index f1816a6..57fec0d 100644 --- a/WeChatFerry/spy/rpc_server.cpp +++ b/WeChatFerry/spy/rpc_server.cpp @@ -850,8 +850,9 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len } LOG_DEBUG("{:#04x}[{}] length: {}", (uint8_t)req.func, magic_enum::enum_name(req.func), in_len); -#if 0 + switch (req.func) { +#if 0 case Functions_FUNC_IS_LOGIN: { ret = func_is_login(out, out_len); break; @@ -978,12 +979,13 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len ret = func_invite_room_members(req.msg.m.roomid, req.msg.m.wxids, out, out_len); break; } +#endif default: { LOG_ERROR("[UNKNOW FUNCTION]"); break; } } -#endif + pb_release(Request_fields, &req); return ret; } diff --git a/WeChatFerry/spy/spy.cpp b/WeChatFerry/spy/spy.cpp index 2d6382c..fd116f4 100644 --- a/WeChatFerry/spy/spy.cpp +++ b/WeChatFerry/spy/spy.cpp @@ -26,20 +26,20 @@ void InitSpy(LPVOID args) LOG_ERROR("获取微信版本失败"); return; } - LOG_DEBUG("WeChat version: {}", Wstring2String(version).c_str()); + LOG_INFO("WeChat version: {}", Wstring2String(version).c_str()); if (LoadCalls(version, &g_WxCalls) != 0) { // 加载微信版本对应的Call地址 LOG_ERROR("不支持当前版本"); MessageBox(NULL, L"不支持当前版本", L"错误", 0); return; } - // RpcStartServer(pp->port); + RpcStartServer(pp->port); } void CleanupSpy() { LOG_DEBUG("CleanupSpy"); - // RpcStopServer(); + RpcStopServer(); } int IsLogin(void) { return (int)GET_DWORD(g_WeChatWinDllAddr + g_WxCalls.login); } From 7228fb35ea6b5e4f72e734eac8e1d9a6daffd392 Mon Sep 17 00:00:00 2001 From: Changhua Date: Fri, 19 Apr 2024 19:06:30 +0800 Subject: [PATCH 06/25] Update --- README.MD | 220 +++++++++++++++++++++--------------------------------- 1 file changed, 85 insertions(+), 135 deletions(-) diff --git a/README.MD b/README.MD index d92c9e8..145d848 100644 --- a/README.MD +++ b/README.MD @@ -1,7 +1,8 @@ # WeChatFerry + 一个玩微信的工具。更多介绍见:[WeChatFerry: 一个玩微信的工具](https://mp.weixin.qq.com/s/CGLfSaNDy8MyuyPWGjGJ7w)。 -
免责声明【必读】 +
免责声明【必读】 本工具仅供学习和技术研究使用,不得用于任何商业或非法行为,否则后果自负。 @@ -15,101 +16,22 @@
-|[📖 Python 文档](https://wechatferry.readthedocs.io/)|[📺 Python 视频教程](https://mp.weixin.qq.com/s/APdjGyZ2hllXxyG_sNCfXQ)|[🙋 FAQ](https://mp.weixin.qq.com/s/WOw26mKJG8Nq55cT6iG-yA)| -|:-:|:-:|:-:| - -👉 [WeChatRobot🤖](https://github.com/lich0821/WeChatRobot),一个基于 WeChatFerry 的 Python 机器人框架。 - -
点击查看功能清单 - -* 检查登录状态 -* 获取登录账号的 wxid -* 获取消息类型 -* 获取所有联系人 -* 获取所有好友 -* 获取数据库 -* 获取某数据库下的表 -* 获取用户信息 -* 发送文本消息(可 @) -* 发送图片 -* 发送文件 -* 允许接收消息 -* 停止接收消息 -* 执行 SQL 查询 -* 接受好友申请 -* 添加群成员 -* 删除群成员 -* 解密图片 -* 获取朋友圈消息 -* 保存图片 -* 保存语音 -* 发送卡片消息 -* 拍一拍群友 -* 邀请群成员 -* 图片 OCR -* 转发消息 -* 撤回消息 -* 获取登录二维码 - -
- -
点击查看支持的客户端 - -* Go -* HTTP (Go, Rust) -* Java -* Node.js -* Python -* Rust -
- |![碲矿](assets/TEQuant.jpg)|![赞赏](assets/QR.jpeg)| |:-:|:-:| |后台回复 `WCF` 加群交流|如果你觉得有用| -## 快速开始 -### Python -[![PyPi](https://img.shields.io/pypi/v/wcferry.svg)](https://pypi.python.org/pypi/wcferry) [![Downloads](https://static.pepy.tech/badge/wcferry)](https://pypi.python.org/pypi/wcferry) [![Documentation Status](https://readthedocs.org/projects/wechatferry/badge/?version=latest)](https://wechatferry.readthedocs.io/zh/latest/?badge=latest) - -* 安装 -```sh -pip install --upgrade wcferry -``` - -* 参考框架:[🤖WeChatRobot](https://github.com/lich0821/WeChatRobot) - -### HTTP -#### [wcfrust](https://github.com/lich0821/wcf-client-rust)(基于 Rust) -开箱即用:[快速开始](https://github.com/lich0821/wcf-client-rust?tab=readme-ov-file#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B)。 - -#### GoHttp(基于 Go) -参考 [GoHttp README.MD](clients/gohttp/README.md) - -#### ~~wcfhttp(基于 Python)~~ -❗ **wcfhttp 不再维护,有需要可以使用 [WcfRust](https://github.com/lich0821/wcf-client-rust) 或者 [GoHttp](clients/gohttp/README.md)。** - -其余客户端,可下载 [最新发布的版本](https://github.com/lich0821/WeChatFerry/releases/latest),根据技术栈,选择客户端,将相应 `dll` 和 `exe` 文件放到对应位置。 - -### Go -参考 [Go README.MD](clients/go/README.md) - -### Java -参考 [Java README.MD](clients/java/README.MD) - -### Node.js -参考 [Node.js README.MD](https://github.com/stkevintan/node-wcferry/blob/main/README.md) - -### Rust -参考 [Rust README.MD](clients/rust/README.MD) - ## 一起开发 + > 🚫 非开发用户不需要往下看。 ### 安装开发环境 +
点击查看 #### 安装 vcpkg + * 安装,参考[Vcpkg: 总览](https://github.com/microsoft/vcpkg/blob/master/README_zh_CN.md)。 + ```sh cd C:\Tools git clone https://github.com/microsoft/vcpkg @@ -117,14 +39,15 @@ git clone https://github.com/microsoft/vcpkg ``` * 添加全局配置: -环境变量增加 `vcpkg` 所在路径(本文为:`C:\Tools\vcpkg`)。 +环境变量增加 `vcpkg` 所在路径(本项目为:`C:\Tools\vcpkg`)。 #### 安装相关组件 + ```sh -vcpkg install protobuf[zlib]:x86-windows-static -vcpkg install spdlog:x86-windows-static -vcpkg install nng:x86-windows-static -vcpkg install magic-enum:x86-windows-static +vcpkg install protobuf[zlib]:x64-windows-static +vcpkg install spdlog:x64-windows-static +vcpkg install nng:x64-windows-static +vcpkg install magic-enum:x64-windows-static vcpkg integrate install ``` @@ -139,27 +62,39 @@ vcpkg integrate install
### 编译 -使用 VS2019 打开工程,编译即可。 + +使用 VS2019 打开工程,编译即可。编译成功后,在 `WeChatFerry\WeChatFerry\Out` 目录中会看到相应的 DLL 文件。 **注**:如果遇到执行 `protoc` 时的 9009 错误,检查是否是 python3 环境有问题,或者 protoc 命令的环境变量配置不正确。 ### 运行 -运行 `wcf.exe` 启动 -```sh -wcf.exe --help +```py +import ctypes +# 加载 sdk.dll (需要绝对路径) +sdk = ctypes.cdll.LoadLibrary("C:/Projs/WeChatFerry/WeChatFerry/Out/sdk.dll") + +# 初始化 +sdk.WxInitSDK(False, 10086) + +# 退出 SDK +sdk.WxDestroySDK() + +# 注意关闭 Python 进程 ``` ## 项目结构 + ```sh WeChatFerry ├── LICENSE # LICENSE ├── README.MD # 说明 ├── WeChatFerry │   ├── WeChatFerry.sln # VS2019 工程文件 +│   ├── com # 公共模块 │   ├── rpc # RPC 模块 │   ├── sdk # 注入及启动模块 -│   ├── spy # 核心功能实现模块 -│   └── wcf # 命令行版启动器 +│   ├── smc # Silk-Mp3 转换模块 +│   └── spy # 核心功能实现模块 ├── assets │   ├── QR.jpeg # 二维码,测试用图 │   ├── TEQuant.jpg # 二维码,测试用图 @@ -169,7 +104,7 @@ WeChatFerry │   ├── gohttp # HTTP 客户端 │   ├── http # HTTP 客户端 │   ├── java # Java 客户端 -│   ├── node # Node.js 客户端 +│   ├── node # Node.js 客户端 │   ├── pyauto # 群友封装的客户端 │   ├── python # Python 客户端 │   └── rust # Rust 客户端 @@ -177,47 +112,13 @@ WeChatFerry ``` -
点击查看 - -### go -Go 客户端。 - -### gohttp -HTTP 客户端,二进制发布无依赖 - -### http -HTTP 客户端。 - -### node -Node.js 客户端. - -### java -Java 客户端。 - -### python -Python 客户端。 - -### rpc -RPC 的通信部分和序列化 / 反序列化部分。 - -### rust -Rust 客户端。 - -### sdk -负责将 `spy` 注入微信进程,并启动 RPC 服务。 - -### spy -间谍模块,注入到微信中,通过 RPC 做消息转发工作。 - -### wcf -命令行版启动器,调用 `sdk` 将 `spy` 注入微信。其他客户端可通过 RPC 连接到 `spy` 进行消息传递。默认监听的地址为 `tcp://0.0.0.0:10086` 和 `tcp://0.0.0.0:10087`。一般情况不需要显式运行,各客户端自动调用。 - -
- ## 版本更新 -### v39.0.14 (2024.02.18) -* 修复获取登录二维码问题 +### v39.1.0 (2024.04.19) + +* 适配 x64 环境 +* 重构项目 +* 开始适配 `3.9.10.19`
点击查看更多 @@ -229,21 +130,29 @@ Rust 客户端。 * `y` 是 `WeChatFerry` 的版本,从 0 开始 * `z` 是各客户端的版本,从 0 开始 +### v39.0.14 (2024.02.18) + +* 修复获取登录二维码问题 + ### v39.0.13 (2024.02.14) + * 修复若干问题 * 撤回消息 * 获取登录二维码 ### v39.0.12 (2023.12.20) + * 修复一个问题 * 消息转发 ### v39.0.11 (2023.12.16) + * 修复 PB 消息类型(可能会导致非 Python 客户端崩溃) * 修复日志错误 * 移除非必要依赖 ### v39.0.10 (2023.12.08) + * 代码优化 * 发送卡片消息 * 拍一拍群友 @@ -251,30 +160,39 @@ Rust 客户端。 * 图片 OCR ### v39.0.7 (2023.12.03) + * 保存语音 ### v39.0.6 (2023.11.26) + * 修复下载图片退出问题 ### v39.0.5 (2023.11.22) + * 修复收到某些文件崩溃问题 ### v39.0.4 (2023.11.21) + * 下载图片、文件和视频 ### v39.0.3 (2023.09.28) + * 修复登录账号昵称超长报错问题 ### v39.0.2 (2023.07.16) + * 修复朋友圈消息 `is_group` 为 `True` 问题 ### v39.0.1 (2023.07.16) + * 获取朋友圈消息 ### v39.0.0 (2023.07.14) + 升级到 `3.9.2.23`。 ### v37.1.25 (2023.05.07) + 更新版本编码。 根据新版本编码规则: @@ -283,6 +201,7 @@ Rust 客户端。 * HTTP 客户端 `wcfhttp` 的 `v3.7.0.30.25` 应该调整为 `v37.1.25.0` ### v3.7.0.30.25 (2023.05.05) + * 修复群消息判断错误 * 修复名片添加好友问题 * 修复获取数据库多余字符问题 @@ -290,105 +209,136 @@ Rust 客户端。 * Python 客户端发送图片支持网络路径 ### v3.7.0.30.24 (2023.04.19) + 实现了一个功能。 ### v3.7.0.30.23 (2023.04.13) + * 解密图片 * 获取登录账号信息 * 获取联系人备注 ### v3.7.0.30.22(2023.04.09) + 将监听端口调整为可配置。 ### v3.7.0.30.21(2023.03.15) + * 发送表情 ### v3.7.0.30.20(2023.03.12) + 修复 wxid 获取问题。 ### v3.7.0.30.19(2023.03.06) + 修复重复消息问题。 ### v3.7.0.30.18(2023.03.05) + 修复添加好友问题。 ### v3.7.0.30.17(2023.03.05) + 修复获取登录账号 wxid 问题。 ### v3.7.0.30.16(2023.03.04) + 将错误码改成错误消息,方便调试。 ### v3.7.0.30.15(2023.03.01) + * 发送 xml ### v3.7.0.30.14(2023.02.28) + * 添加群成员 ### v3.7.0.30.13(2023.02.27) + 去除 gRPC 框架,自定义更轻量的 RPC 轮子 `nnprc`。 ### v3.7.0.30.12(2023.01.20) + * 更新 Python 客户端 * 修改监听地址为 `0.0.0.0:10086` * 增加 `Launcher`,直接注入 `spy` ### v3.7.0.30.11(2022.10.19) + 更新 Python 客户端。 ### v3.7.0.30-gRPC-2(2022.10.18) + 增加 Java 客户端。 ### v3.7.0.30-gRPC-1(2022.10.16) + 将 RPC 框架切换为 gRPC! ### v3.7.0.30-8(2022.09.25) + * 获取登录账号微信 ID ### v3.7.0.30-7(2022.09.24) + 修复群聊有系统消息时会崩溃 bug。后续考虑把消息来源交还给客户端自己区别。 ### v3.7.0.30-6(2022.08.21) + * 通过好友验证 ### v3.7.0.30-5(2022.08.20) + * 执行 SQL 语句 ### v3.7.0.30-4(2022.08.20) + 修复群消息 @人 功能。有几点注意事项: 1. `vAtWxids` 是要 `@` 的 `wxid` 清单,以 `,` 分隔。 2. 只有群主才能 `@所有人`,非群主硬发 `@所有人` 会导致消息发不出去;`@所有人` 对应 `vAtWxids` 为 `"notify@all"`。 3. 消息体里 `@` 的数量必须与 `vAtWxids` 里的数量一致,否则消息能发出但 `@` 功能失效。 ### v3.7.0.30-3(2022.08.20) + 修复可重入 bug。 ### v3.7.0.30-2(2022.08.14) + 优化 Hook 和 Inject 代码,实现可重入。 ### v3.7.0.30-1(2022.08.12) + 适配微信 `3.7.0.30`。 ### v3.7.0.29-3(2022.08.7) + * 查询数据库,获取库、表。 ### v3.7.0.29-2(2022.08.7) + 优化 RPC。 ### v3.7.0.29-1(2022.08.7) + 适配微信 `3.7.0.29`。 ### v3.3.0.115-3(2021.08.28) + 适配微信 `3.3.0.115`,新增功能: * 获取所有联系人 ### v3.3.0.115-2(2021.08.22) + 适配微信 `3.3.0.115`,新增功能: * 发送图片消息 ### v3.3.0.115-1(2021.08.22) + 适配微信 `3.3.0.115`。 ### v3.0.0.57-1(2021.02.12) + 适配微信 `3.0.0.57`,支持功能: * 登录状态判断 * 接收文本消息 From 7c1f4123f0a58ddd94140bfef25fc70cbba08a85 Mon Sep 17 00:00:00 2001 From: Changhua Date: Sat, 20 Apr 2024 07:11:15 +0800 Subject: [PATCH 07/25] Enhance robustness --- WeChatFerry/sdk/sdk.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/WeChatFerry/sdk/sdk.cpp b/WeChatFerry/sdk/sdk.cpp index 063be85..ff754d5 100644 --- a/WeChatFerry/sdk/sdk.cpp +++ b/WeChatFerry/sdk/sdk.cpp @@ -8,9 +8,7 @@ #include "sdk.h" #include "util.h" -#define WCF_LOCK ".wcf.lock" - -static bool dbg = false; +static BOOL injected = false; static HANDLE wcProcess = NULL; static HMODULE spyBase = NULL; static WCHAR spyDllPath[MAX_PATH] = { 0 }; @@ -35,7 +33,6 @@ static int GetDllPath(bool debug, wchar_t *dllPath) int WxInitSDK(bool debug, int port) { - dbg = debug; int status = 0; DWORD wcPid = 0; @@ -66,17 +63,22 @@ int WxInitSDK(bool debug, int port) return -1; } + injected = true; return 0; } int WxDestroySDK() { - if (!CallDllFunc(wcProcess, spyDllPath, spyBase, "CleanupSpy", NULL)) { + if (!injected) { return -1; } + if (!CallDllFunc(wcProcess, spyDllPath, spyBase, "CleanupSpy", NULL)) { + return -2; + } + if (!EjectDll(wcProcess, spyBase)) { - return -1; // TODO: Unify error codes + return -3; // TODO: Unify error codes } return 0; From b55741e7a819e231ddd0d9211feb936bd6178d9c Mon Sep 17 00:00:00 2001 From: Changhua Date: Sun, 21 Apr 2024 21:14:13 +0800 Subject: [PATCH 08/25] Copy dlls to python client --- WeChatFerry/sdk/SDK.vcxproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WeChatFerry/sdk/SDK.vcxproj b/WeChatFerry/sdk/SDK.vcxproj index be6bfb4..5c17179 100644 --- a/WeChatFerry/sdk/SDK.vcxproj +++ b/WeChatFerry/sdk/SDK.vcxproj @@ -178,7 +178,8 @@ sdk.def - xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)Out + xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)Out +xcopy /y $(OutDir)$(TargetFileName) $(SolutionDir)..\clients\python\wcferry Copy files From a9e31cf65a45f615d8880d8c601e34771fdb58b5 Mon Sep 17 00:00:00 2001 From: Changhua Date: Wed, 24 Apr 2024 19:18:13 +0800 Subject: [PATCH 09/25] Adapt python client --- clients/python/wcferry/client.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/clients/python/wcferry/client.py b/clients/python/wcferry/client.py index 7452d67..ef1d9b9 100644 --- a/clients/python/wcferry/client.py +++ b/clients/python/wcferry/client.py @@ -1,10 +1,11 @@ #! /usr/bin/env python3 # -*- coding: utf-8 -*- -__version__ = "39.0.14.1" +__version__ = "39.1.0.0" import atexit import base64 +import ctypes import logging import mimetypes import os @@ -72,11 +73,12 @@ class Wcf(): self.LOG.info(f"wcferry version: {__version__}") self.port = port self.host = host + self.sdk = None if host is None: self._local_mode = True self.host = "127.0.0.1" - cmd = fr'"{self._wcf_root}\wcf.exe" start {self.port} {"debug" if debug else ""}' - if os.system(cmd) != 0: + self.sdk = ctypes.cdll.LoadLibrary(f"{self._wcf_root}/sdk.dll") + if self.sdk.WxInitSDK(debug, port) != 0: self.LOG.error("初始化失败!") os._exit(-1) @@ -121,11 +123,9 @@ class Wcf(): self.disable_recv_msg() self.cmd_socket.close() - if self._local_mode: - cmd = fr'"{self._wcf_root}\wcf.exe" stop' - if os.system(cmd) != 0: - self.LOG.error("退出失败!") - return + if self._local_mode and self.sdk and self.sdk.WxDestroySDK() != 0: + self.LOG.error("退出失败!") + self._is_running = False def keep_running(self): @@ -658,7 +658,7 @@ class Wcf(): if (cnt["wxid"].endswith("@chatroom") or # 群聊 cnt["wxid"].startswith("gh_") or # 公众号 cnt["wxid"] in not_friends.keys() # 其他杂号 - ): + ): continue friends.append(cnt) From ebb45d3cb1fcc075d6bd22bea9f5f80f7fb7375b Mon Sep 17 00:00:00 2001 From: Changhua Date: Fri, 26 Apr 2024 23:23:00 +0800 Subject: [PATCH 10/25] Refactoring --- WeChatFerry/spy/funcs.cpp | 3 +++ WeChatFerry/spy/funcs.h | 1 + WeChatFerry/spy/rpc_server.cpp | 2 -- WeChatFerry/spy/spy.cpp | 2 -- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/WeChatFerry/spy/funcs.cpp b/WeChatFerry/spy/funcs.cpp index eeb63f0..eeea91c 100644 --- a/WeChatFerry/spy/funcs.cpp +++ b/WeChatFerry/spy/funcs.cpp @@ -24,6 +24,9 @@ namespace fs = std::filesystem; extern bool gIsListeningPyq; extern WxCalls_t g_WxCalls; extern DWORD g_WeChatWinDllAddr; + +int IsLogin(void) { return (int)GET_DWORD(g_WeChatWinDllAddr + g_WxCalls.login); } + #if 0 static string get_key(uint8_t header1, uint8_t header2, uint8_t *key) { diff --git a/WeChatFerry/spy/funcs.h b/WeChatFerry/spy/funcs.h index ec4e0f8..2b33509 100644 --- a/WeChatFerry/spy/funcs.h +++ b/WeChatFerry/spy/funcs.h @@ -3,6 +3,7 @@ #include "stdint.h" #include +int IsLogin(void); std::string GetAudio(uint64_t id, std::string dir); std::string DecryptImage(std::string src, std::string dst); int RefreshPyq(uint64_t id); diff --git a/WeChatFerry/spy/rpc_server.cpp b/WeChatFerry/spy/rpc_server.cpp index 57fec0d..5357ffb 100644 --- a/WeChatFerry/spy/rpc_server.cpp +++ b/WeChatFerry/spy/rpc_server.cpp @@ -40,8 +40,6 @@ namespace fs = std::filesystem; -extern int IsLogin(void); // Defined in spy.cpp - bool gIsListening = false; bool gIsListeningPyq = false; mutex gMutex; diff --git a/WeChatFerry/spy/spy.cpp b/WeChatFerry/spy/spy.cpp index fd116f4..61bcd67 100644 --- a/WeChatFerry/spy/spy.cpp +++ b/WeChatFerry/spy/spy.cpp @@ -41,5 +41,3 @@ void CleanupSpy() LOG_DEBUG("CleanupSpy"); RpcStopServer(); } - -int IsLogin(void) { return (int)GET_DWORD(g_WeChatWinDllAddr + g_WxCalls.login); } From d8770487ed16d994228f2556b2f0173e9d511b4b Mon Sep 17 00:00:00 2001 From: Changhua Date: Sun, 28 Apr 2024 09:16:09 +0800 Subject: [PATCH 11/25] Fix data type --- WeChatFerry/com/util.cpp | 44 ++++++++++++++-------------- WeChatFerry/com/util.h | 24 +++++++-------- WeChatFerry/spy/chatroom_mgmt.cpp | 2 +- WeChatFerry/spy/contact_mgmt.cpp | 2 +- WeChatFerry/spy/exec_sql.cpp | 2 +- WeChatFerry/spy/funcs.cpp | 4 +-- WeChatFerry/spy/receive_msg.cpp | 2 +- WeChatFerry/spy/receive_transfer.cpp | 2 +- WeChatFerry/spy/send_msg.cpp | 2 +- WeChatFerry/spy/spy.cpp | 4 +-- WeChatFerry/spy/user_info.cpp | 10 +++---- 11 files changed, 49 insertions(+), 49 deletions(-) diff --git a/WeChatFerry/com/util.cpp b/WeChatFerry/com/util.cpp index ff324ac..aefcfe4 100644 --- a/WeChatFerry/com/util.cpp +++ b/WeChatFerry/com/util.cpp @@ -133,12 +133,12 @@ static bool GetFileVersion(const wchar_t *filePath, wchar_t *version) return false; } - DWORD verMS = pVerInfo->dwFileVersionMS; - DWORD verLS = pVerInfo->dwFileVersionLS; - DWORD major = HIWORD(verMS); - DWORD minor = LOWORD(verMS); - DWORD build = HIWORD(verLS); - DWORD revision = LOWORD(verLS); + 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); @@ -163,9 +163,9 @@ int GetWeChatVersion(wchar_t *version) return ret; } -DWORD GetWeChatPid() +UINT64 GetWeChatPid() { - DWORD pid = 0; + UINT64 pid = 0; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) }; while (Process32Next(hSnapshot, &pe32)) { @@ -179,7 +179,7 @@ DWORD GetWeChatPid() return pid; } -int OpenWeChat(DWORD *pid) +int OpenWeChat(UINT64 *pid) { *pid = GetWeChatPid(); if (*pid) { @@ -208,9 +208,9 @@ int OpenWeChat(DWORD *pid) return ERROR_SUCCESS; } -int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size) +size_t GetWstringByAddress(UINT64 address, wchar_t *buffer, UINT64 buffer_size) { - DWORD strLength = GET_DWORD(address + 4); + size_t strLength = GET_UINT64(address + 4); if (strLength == 0) { return 0; } else if (strLength > buffer_size) { @@ -222,27 +222,27 @@ int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size) return strLength; } -string GetStringByAddress(DWORD address) +string GetStringByAddress(UINT64 address) { - DWORD strLength = GET_DWORD(address + 4); + UINT64 strLength = GET_UINT64(address + 4); return Wstring2String(wstring(GET_WSTRING(address), strLength)); } -string GetStringByStrAddr(DWORD addr) +string GetStringByStrAddr(UINT64 addr) { - DWORD strLength = GET_DWORD(addr + 4); + UINT64 strLength = GET_UINT64(addr + 4); return strLength ? string(GET_STRING(addr), strLength) : string(); } -string GetStringByWstrAddr(DWORD addr) +string GetStringByWstrAddr(UINT64 addr) { - DWORD strLength = GET_DWORD(addr + 4); + UINT64 strLength = GET_UINT64(addr + 4); return strLength ? Wstring2String(wstring(GET_WSTRING(addr), strLength)) : string(); } -DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address) +UINT32 GetMemoryIntByAddress(HANDLE hProcess, UINT64 address) { - DWORD value = 0; + UINT32 value = 0; unsigned char data[4] = { 0 }; if (ReadProcessMemory(hProcess, (LPVOID)address, data, 4, 0)) { @@ -255,12 +255,12 @@ DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address) return value; } -wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address) +wstring GetUnicodeInfoByAddress(HANDLE hProcess, UINT64 address) { wstring value = L""; - DWORD strAddress = GetMemoryIntByAddress(hProcess, address); - DWORD strLen = GetMemoryIntByAddress(hProcess, address + 0x4); + UINT64 strAddress = GetMemoryIntByAddress(hProcess, address); + UINT64 strLen = GetMemoryIntByAddress(hProcess, address + 0x4); if (strLen > 500) return value; diff --git a/WeChatFerry/com/util.h b/WeChatFerry/com/util.h index 68808a6..5d369f8 100644 --- a/WeChatFerry/com/util.h +++ b/WeChatFerry/com/util.h @@ -8,10 +8,10 @@ #define WCFSPYDLL L"spy.dll" #define WCFSPYDLL_DEBUG L"spy_debug.dll" -#define GET_DWORD(addr) ((DWORD) * (DWORD *)(addr)) -#define GET_QWORD(addr) ((uint64_t) * (uint64_t *)(addr)) -#define GET_STRING(addr) ((CHAR *)(*(DWORD *)(addr))) -#define GET_WSTRING(addr) ((WCHAR *)(*(DWORD *)(addr))) +#define GET_UINT64(addr) ((UINT64) * (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)) @@ -20,16 +20,16 @@ typedef struct PortPath { char path[MAX_PATH]; } PortPath_t; -DWORD GetWeChatPid(); -int OpenWeChat(DWORD *pid); +UINT64 GetWeChatPid(); +int OpenWeChat(UINT64 *pid); int GetWeChatVersion(wchar_t *version); -int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size); -DWORD GetMemoryIntByAddress(HANDLE hProcess, DWORD address); -std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address); +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(DWORD address); -std::string GetStringByStrAddr(DWORD addr); -std::string GetStringByWstrAddr(DWORD addr); +std::string GetStringByAddress(UINT64 address); +std::string GetStringByStrAddr(UINT64 addr); +std::string GetStringByWstrAddr(UINT64 addr); void DbgMsg(const char *zcFormat, ...); diff --git a/WeChatFerry/spy/chatroom_mgmt.cpp b/WeChatFerry/spy/chatroom_mgmt.cpp index 25bafcd..7a6e4b9 100644 --- a/WeChatFerry/spy/chatroom_mgmt.cpp +++ b/WeChatFerry/spy/chatroom_mgmt.cpp @@ -10,7 +10,7 @@ using namespace std; extern WxCalls_t g_WxCalls; -extern DWORD g_WeChatWinDllAddr; +extern UINT64 g_WeChatWinDllAddr; #if 0 int AddChatroomMember(string roomid, string wxids) { diff --git a/WeChatFerry/spy/contact_mgmt.cpp b/WeChatFerry/spy/contact_mgmt.cpp index 28bbaa4..2039a40 100644 --- a/WeChatFerry/spy/contact_mgmt.cpp +++ b/WeChatFerry/spy/contact_mgmt.cpp @@ -7,7 +7,7 @@ using namespace std; extern WxCalls_t g_WxCalls; -extern DWORD g_WeChatWinDllAddr; +extern UINT64 g_WeChatWinDllAddr; #if 0 #define FEAT_LEN 5 static const uint8_t FEAT_COUNTRY[FEAT_LEN] = { 0xA4, 0xD9, 0x02, 0x4A, 0x18 }; diff --git a/WeChatFerry/spy/exec_sql.cpp b/WeChatFerry/spy/exec_sql.cpp index 04b4521..9065a35 100644 --- a/WeChatFerry/spy/exec_sql.cpp +++ b/WeChatFerry/spy/exec_sql.cpp @@ -16,7 +16,7 @@ #define OFFSET_DB_NAME 0x14 #define OFFSET_DB_MSG_MGR 0x30403B8 -extern DWORD g_WeChatWinDllAddr; +extern UINT64 g_WeChatWinDllAddr; typedef map dbMap_t; static dbMap_t dbMap; diff --git a/WeChatFerry/spy/funcs.cpp b/WeChatFerry/spy/funcs.cpp index eeea91c..b03bb51 100644 --- a/WeChatFerry/spy/funcs.cpp +++ b/WeChatFerry/spy/funcs.cpp @@ -23,9 +23,9 @@ namespace fs = std::filesystem; extern bool gIsListeningPyq; extern WxCalls_t g_WxCalls; -extern DWORD g_WeChatWinDllAddr; +extern UINT64 g_WeChatWinDllAddr; -int IsLogin(void) { return (int)GET_DWORD(g_WeChatWinDllAddr + g_WxCalls.login); } +int IsLogin(void) { return (int)GET_UINT64(g_WeChatWinDllAddr + g_WxCalls.login); } #if 0 static string get_key(uint8_t header1, uint8_t header2, uint8_t *key) diff --git a/WeChatFerry/spy/receive_msg.cpp b/WeChatFerry/spy/receive_msg.cpp index b9aba4e..b8adf11 100644 --- a/WeChatFerry/spy/receive_msg.cpp +++ b/WeChatFerry/spy/receive_msg.cpp @@ -19,7 +19,7 @@ extern queue gMsgQueue; // Defined in spy.cpp extern WxCalls_t g_WxCalls; -extern DWORD g_WeChatWinDllAddr; +extern UINT64 g_WeChatWinDllAddr; static DWORD reg_buffer = 0; static DWORD recvMsgHookAddr = 0; diff --git a/WeChatFerry/spy/receive_transfer.cpp b/WeChatFerry/spy/receive_transfer.cpp index 5b66bb9..019d220 100644 --- a/WeChatFerry/spy/receive_transfer.cpp +++ b/WeChatFerry/spy/receive_transfer.cpp @@ -6,7 +6,7 @@ using namespace std; extern WxCalls_t g_WxCalls; -extern DWORD g_WeChatWinDllAddr; +extern UINT64 g_WeChatWinDllAddr; #if 0 int ReceiveTransfer(string wxid, string transferid, string transactionid) { diff --git a/WeChatFerry/spy/send_msg.cpp b/WeChatFerry/spy/send_msg.cpp index 2e2f57c..362150c 100644 --- a/WeChatFerry/spy/send_msg.cpp +++ b/WeChatFerry/spy/send_msg.cpp @@ -10,7 +10,7 @@ extern HANDLE g_hEvent; extern WxCalls_t g_WxCalls; -extern DWORD g_WeChatWinDllAddr; +extern UINT64 g_WeChatWinDllAddr; extern string GetSelfWxid(); // Defined in spy.cpp #if 0 void SendTextMessage(string wxid, string msg, string atWxids) diff --git a/WeChatFerry/spy/spy.cpp b/WeChatFerry/spy/spy.cpp index 61bcd67..ef711fe 100644 --- a/WeChatFerry/spy/spy.cpp +++ b/WeChatFerry/spy/spy.cpp @@ -7,7 +7,7 @@ #include "util.h" WxCalls_t g_WxCalls = { 0 }; -DWORD g_WeChatWinDllAddr = 0; +UINT64 g_WeChatWinDllAddr = 0; void InitSpy(LPVOID args) { @@ -16,7 +16,7 @@ void InitSpy(LPVOID args) PortPath_t *pp = (PortPath_t *)args; InitLogger(pp->path); - g_WeChatWinDllAddr = (DWORD)GetModuleHandle(L"WeChatWin.dll"); // 获取wechatWin模块地址 + g_WeChatWinDllAddr = (UINT64)GetModuleHandle(L"WeChatWin.dll"); // 获取wechatWin模块地址 if (g_WeChatWinDllAddr == 0) { LOG_ERROR("获取 wechatWin.dll 模块地址失败"); return; diff --git a/WeChatFerry/spy/user_info.cpp b/WeChatFerry/spy/user_info.cpp index dddc108..75f7691 100644 --- a/WeChatFerry/spy/user_info.cpp +++ b/WeChatFerry/spy/user_info.cpp @@ -1,10 +1,10 @@ -#include "user_info.h" +#include "user_info.h" #include "load_calls.h" #include "log.h" #include "util.h" extern WxCalls_t g_WxCalls; -extern DWORD g_WeChatWinDllAddr; +extern UINT64 g_WeChatWinDllAddr; static char home[MAX_PATH] = { 0 }; @@ -20,9 +20,9 @@ string GetHomePath() string GetSelfWxid() { - DWORD wxidType = 0; + UINT64 wxidType = 0; try { - wxidType = GET_DWORD(g_WeChatWinDllAddr + g_WxCalls.ui.wxid + 0x14); + wxidType = GET_UINT64(g_WeChatWinDllAddr + g_WxCalls.ui.wxid + 0x14); if (wxidType == 0xF) { return GET_STRING_FROM_P(g_WeChatWinDllAddr + g_WxCalls.ui.wxid); } else { @@ -41,7 +41,7 @@ UserInfo_t GetUserInfo() ui.wxid = GetSelfWxid(); - DWORD nameType = GET_DWORD(g_WeChatWinDllAddr + g_WxCalls.ui.nickName + 0x14); + UINT64 nameType = GET_UINT64(g_WeChatWinDllAddr + g_WxCalls.ui.nickName + 0x14); if (nameType == 0xF) { ui.name = GET_STRING_FROM_P(g_WeChatWinDllAddr + g_WxCalls.ui.nickName); } else { // 0x1F From 4bf65bb4e37d83d0b3ed2f3d48950412cd245f8d Mon Sep 17 00:00:00 2001 From: Changhua Date: Mon, 29 Apr 2024 21:19:10 +0800 Subject: [PATCH 12/25] Impl IsLogin --- WeChatFerry/spy/load_calls.cpp | 2 +- WeChatFerry/spy/rpc_server.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/WeChatFerry/spy/load_calls.cpp b/WeChatFerry/spy/load_calls.cpp index 8d51a77..f3a7dd2 100644 --- a/WeChatFerry/spy/load_calls.cpp +++ b/WeChatFerry/spy/load_calls.cpp @@ -6,7 +6,7 @@ #define SUPPORT_VERSION L"3.9.10.19" WxCalls_t wxCalls = { - 0x2FFD638, // Login Status + 0x5AB9184, // Login Status { 0x2FFD484, 0x2FFD590, 0x2FFD500, 0x30238CC }, // User Info: wxid, nickname, mobile, home { 0x768140, 0xCE6C80, 0x756960 }, // Send Message /* Receive Message: diff --git a/WeChatFerry/spy/rpc_server.cpp b/WeChatFerry/spy/rpc_server.cpp index 5357ffb..dd1b1e6 100644 --- a/WeChatFerry/spy/rpc_server.cpp +++ b/WeChatFerry/spy/rpc_server.cpp @@ -51,7 +51,7 @@ static DWORD lThreadId = 0; static bool lIsRunning = false; static nng_socket cmdSock, msgSock; // TODO: 断开检测 static uint8_t gBuffer[G_BUF_SIZE] = { 0 }; -#if 0 + bool func_is_login(uint8_t *out, size_t *len) { Response rsp = Response_init_default; @@ -68,7 +68,7 @@ bool func_is_login(uint8_t *out, size_t *len) return true; } - +#if 0 bool func_get_self_wxid(uint8_t *out, size_t *len) { Response rsp = Response_init_default; @@ -850,11 +850,11 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len LOG_DEBUG("{:#04x}[{}] length: {}", (uint8_t)req.func, magic_enum::enum_name(req.func), in_len); switch (req.func) { -#if 0 case Functions_FUNC_IS_LOGIN: { ret = func_is_login(out, out_len); break; } +#if 0 case Functions_FUNC_GET_SELF_WXID: { ret = func_get_self_wxid(out, out_len); break; From a3087309d6c4bce52b1a76ffb4b5bef3d99af64d Mon Sep 17 00:00:00 2001 From: Changhua Date: Thu, 2 May 2024 16:01:13 +0800 Subject: [PATCH 13/25] Update instructions --- README.MD | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.MD b/README.MD index 145d848..a6f6048 100644 --- a/README.MD +++ b/README.MD @@ -57,7 +57,12 @@ vcpkg integrate install #### 安装 Python3 -通过微软商店或者 python.org 自行下载均可,注意配置好环境变量,确保 `python3` 在命令行下可用 +通过微软商店或者 python.org 自行下载均可,注意配置好环境变量,确保 `python3` 在命令行下可用。 + +安装依赖: +```sh +pip install grpcio-tools==1.48.2 +```
From d849b79975a595b7c59b02b1c81bd477aa9fc3d2 Mon Sep 17 00:00:00 2001 From: Changhua Date: Thu, 2 May 2024 16:05:58 +0800 Subject: [PATCH 14/25] Fix data type --- WeChatFerry/com/util.cpp | 6 +++--- WeChatFerry/com/util.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/WeChatFerry/com/util.cpp b/WeChatFerry/com/util.cpp index aefcfe4..a03c265 100644 --- a/WeChatFerry/com/util.cpp +++ b/WeChatFerry/com/util.cpp @@ -163,9 +163,9 @@ int GetWeChatVersion(wchar_t *version) return ret; } -UINT64 GetWeChatPid() +DWORD GetWeChatPid() { - UINT64 pid = 0; + DWORD pid = 0; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) }; while (Process32Next(hSnapshot, &pe32)) { @@ -179,7 +179,7 @@ UINT64 GetWeChatPid() return pid; } -int OpenWeChat(UINT64 *pid) +int OpenWeChat(DWORD *pid) { *pid = GetWeChatPid(); if (*pid) { diff --git a/WeChatFerry/com/util.h b/WeChatFerry/com/util.h index 5d369f8..f870ed6 100644 --- a/WeChatFerry/com/util.h +++ b/WeChatFerry/com/util.h @@ -20,8 +20,8 @@ typedef struct PortPath { char path[MAX_PATH]; } PortPath_t; -UINT64 GetWeChatPid(); -int OpenWeChat(UINT64 *pid); +DWORD GetWeChatPid(); +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); From 54ead79f4db53dd7afe1f860616a1971840fe2ea Mon Sep 17 00:00:00 2001 From: Changhua Date: Fri, 3 May 2024 18:14:31 +0800 Subject: [PATCH 15/25] Impl GetSelfWxid --- WeChatFerry/spy/load_calls.cpp | 2 +- WeChatFerry/spy/rpc_server.cpp | 6 +++--- WeChatFerry/spy/user_info.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/WeChatFerry/spy/load_calls.cpp b/WeChatFerry/spy/load_calls.cpp index f3a7dd2..4b75cf8 100644 --- a/WeChatFerry/spy/load_calls.cpp +++ b/WeChatFerry/spy/load_calls.cpp @@ -7,7 +7,7 @@ WxCalls_t wxCalls = { 0x5AB9184, // Login Status - { 0x2FFD484, 0x2FFD590, 0x2FFD500, 0x30238CC }, // User Info: wxid, nickname, mobile, home + { 0x5AB8FC8, 0x5AB90A8, 0x5AB8FE8, 0x5A7F170 }, // User Info: wxid, nickname, mobile, home { 0x768140, 0xCE6C80, 0x756960 }, // Send Message /* Receive Message: Hook, call, msgId, type, isSelf, ts, roomId, content, wxid, sign, thumb, extra, msgXml */ diff --git a/WeChatFerry/spy/rpc_server.cpp b/WeChatFerry/spy/rpc_server.cpp index dd1b1e6..0ffe04f 100644 --- a/WeChatFerry/spy/rpc_server.cpp +++ b/WeChatFerry/spy/rpc_server.cpp @@ -68,7 +68,7 @@ bool func_is_login(uint8_t *out, size_t *len) return true; } -#if 0 + bool func_get_self_wxid(uint8_t *out, size_t *len) { Response rsp = Response_init_default; @@ -87,7 +87,7 @@ bool func_get_self_wxid(uint8_t *out, size_t *len) return true; } - +#if 0 bool func_get_msg_types(uint8_t *out, size_t *len) { Response rsp = Response_init_default; @@ -854,11 +854,11 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len ret = func_is_login(out, out_len); break; } -#if 0 case Functions_FUNC_GET_SELF_WXID: { ret = func_get_self_wxid(out, out_len); break; } +#if 0 case Functions_FUNC_GET_MSG_TYPES: { ret = func_get_msg_types(out, out_len); break; diff --git a/WeChatFerry/spy/user_info.cpp b/WeChatFerry/spy/user_info.cpp index 75f7691..f2e370d 100644 --- a/WeChatFerry/spy/user_info.cpp +++ b/WeChatFerry/spy/user_info.cpp @@ -22,7 +22,7 @@ string GetSelfWxid() { UINT64 wxidType = 0; try { - wxidType = GET_UINT64(g_WeChatWinDllAddr + g_WxCalls.ui.wxid + 0x14); + wxidType = GET_UINT64(g_WeChatWinDllAddr + g_WxCalls.ui.wxid + 0x18); if (wxidType == 0xF) { return GET_STRING_FROM_P(g_WeChatWinDllAddr + g_WxCalls.ui.wxid); } else { @@ -41,7 +41,7 @@ UserInfo_t GetUserInfo() ui.wxid = GetSelfWxid(); - UINT64 nameType = GET_UINT64(g_WeChatWinDllAddr + g_WxCalls.ui.nickName + 0x14); + UINT64 nameType = GET_UINT64(g_WeChatWinDllAddr + g_WxCalls.ui.nickName + 0x18); if (nameType == 0xF) { ui.name = GET_STRING_FROM_P(g_WeChatWinDllAddr + g_WxCalls.ui.nickName); } else { // 0x1F From b19f41b8cf65011420b61b74ab77b39eb265fb3c Mon Sep 17 00:00:00 2001 From: Changhua Date: Sat, 4 May 2024 18:18:11 +0800 Subject: [PATCH 16/25] Impl GetUserInfo --- WeChatFerry/spy/rpc_server.cpp | 52 +++++++++++++++++----------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/WeChatFerry/spy/rpc_server.cpp b/WeChatFerry/spy/rpc_server.cpp index 0ffe04f..f108465 100644 --- a/WeChatFerry/spy/rpc_server.cpp +++ b/WeChatFerry/spy/rpc_server.cpp @@ -87,6 +87,28 @@ bool func_get_self_wxid(uint8_t *out, size_t *len) return true; } + +bool func_get_user_info(uint8_t *out, size_t *len) +{ + Response rsp = Response_init_default; + rsp.func = Functions_FUNC_GET_USER_INFO; + rsp.which_msg = Response_ui_tag; + + UserInfo_t ui = GetUserInfo(); + rsp.msg.ui.wxid = (char *)ui.wxid.c_str(); + rsp.msg.ui.name = (char *)ui.name.c_str(); + rsp.msg.ui.mobile = (char *)ui.mobile.c_str(); + rsp.msg.ui.home = (char *)ui.home.c_str(); + + pb_ostream_t stream = pb_ostream_from_buffer(out, *len); + if (!pb_encode(&stream, Response_fields, &rsp)) { + LOG_ERROR("Encoding failed: {}", PB_GET_ERROR(&stream)); + return false; + } + *len = stream.bytes_written; + + return true; +} #if 0 bool func_get_msg_types(uint8_t *out, size_t *len) { @@ -168,28 +190,6 @@ bool func_get_db_tables(char *db, uint8_t *out, size_t *len) return true; } -bool func_get_user_info(uint8_t *out, size_t *len) -{ - Response rsp = Response_init_default; - rsp.func = Functions_FUNC_GET_USER_INFO; - rsp.which_msg = Response_ui_tag; - - UserInfo_t ui = GetUserInfo(); - rsp.msg.ui.wxid = (char *)ui.wxid.c_str(); - rsp.msg.ui.name = (char *)ui.name.c_str(); - rsp.msg.ui.mobile = (char *)ui.mobile.c_str(); - rsp.msg.ui.home = (char *)ui.home.c_str(); - - pb_ostream_t stream = pb_ostream_from_buffer(out, *len); - if (!pb_encode(&stream, Response_fields, &rsp)) { - LOG_ERROR("Encoding failed: {}", PB_GET_ERROR(&stream)); - return false; - } - *len = stream.bytes_written; - - return true; -} - bool func_get_audio_msg(uint64_t id, char *dir, uint8_t *out, size_t *len) { Response rsp = Response_init_default; @@ -858,6 +858,10 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len ret = func_get_self_wxid(out, out_len); break; } + case Functions_FUNC_GET_USER_INFO: { + ret = func_get_user_info(out, out_len); + break; + } #if 0 case Functions_FUNC_GET_MSG_TYPES: { ret = func_get_msg_types(out, out_len); @@ -875,10 +879,6 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len ret = func_get_db_tables(req.msg.str, out, out_len); break; } - case Functions_FUNC_GET_USER_INFO: { - ret = func_get_user_info(out, out_len); - break; - } case Functions_FUNC_GET_AUDIO_MSG: { ret = func_get_audio_msg(req.msg.am.id, req.msg.am.dir, out, out_len); break; From a3ff4378158cdf6e2834fa0da848342a67fbfcb1 Mon Sep 17 00:00:00 2001 From: Changhua Date: Sat, 4 May 2024 18:30:52 +0800 Subject: [PATCH 17/25] Impl GetMsgTypes --- WeChatFerry/spy/receive_msg.cpp | 4 ++-- WeChatFerry/spy/rpc_server.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/WeChatFerry/spy/receive_msg.cpp b/WeChatFerry/spy/receive_msg.cpp index b8adf11..0ca30a6 100644 --- a/WeChatFerry/spy/receive_msg.cpp +++ b/WeChatFerry/spy/receive_msg.cpp @@ -31,7 +31,7 @@ static DWORD recvPyqHookAddr = 0; static DWORD recvPyqCallAddr = 0; static DWORD recvPyqJumpBackAddr = 0; static CHAR recvPyqBackupCode[5] = { 0 }; -#if 0 + MsgTypes_t GetMsgTypes() { const MsgTypes_t m = { @@ -72,7 +72,7 @@ MsgTypes_t GetMsgTypes() return m; } - +#if 0 void HookAddress(DWORD hookAddr, LPVOID funcAddr, CHAR recvMsgBackupCode[5]) { // 组装跳转数据 diff --git a/WeChatFerry/spy/rpc_server.cpp b/WeChatFerry/spy/rpc_server.cpp index f108465..2745b61 100644 --- a/WeChatFerry/spy/rpc_server.cpp +++ b/WeChatFerry/spy/rpc_server.cpp @@ -109,7 +109,7 @@ bool func_get_user_info(uint8_t *out, size_t *len) return true; } -#if 0 + bool func_get_msg_types(uint8_t *out, size_t *len) { Response rsp = Response_init_default; @@ -129,7 +129,7 @@ bool func_get_msg_types(uint8_t *out, size_t *len) return true; } - +#if 0 bool func_get_contacts(uint8_t *out, size_t *len) { Response rsp = Response_init_default; @@ -862,11 +862,11 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len ret = func_get_user_info(out, out_len); break; } -#if 0 case Functions_FUNC_GET_MSG_TYPES: { ret = func_get_msg_types(out, out_len); break; } +#if 0 case Functions_FUNC_GET_CONTACTS: { ret = func_get_contacts(out, out_len); break; From 9acdf2922506e59a287de3dc57252bf1ac1c5824 Mon Sep 17 00:00:00 2001 From: Changhua Date: Sat, 27 Apr 2024 11:02:34 +0800 Subject: [PATCH 18/25] Introduce MinHook --- README.MD | 1 + 1 file changed, 1 insertion(+) diff --git a/README.MD b/README.MD index a6f6048..ef7d1ff 100644 --- a/README.MD +++ b/README.MD @@ -48,6 +48,7 @@ vcpkg install protobuf[zlib]:x64-windows-static vcpkg install spdlog:x64-windows-static vcpkg install nng:x64-windows-static vcpkg install magic-enum:x64-windows-static +vcpkg install minhook:x64-windows-static vcpkg integrate install ``` From 1ab32146b85eaa222583afb33e6a95435422ee1e Mon Sep 17 00:00:00 2001 From: Changhua Date: Fri, 31 May 2024 21:03:58 +0800 Subject: [PATCH 19/25] Introduce debug log --- README.MD | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.MD b/README.MD index ef7d1ff..720aca6 100644 --- a/README.MD +++ b/README.MD @@ -88,6 +88,13 @@ sdk.WxDestroySDK() # 注意关闭 Python 进程 ``` +### 调试日志 +```c + DbgMsg("ListenMessage"); // 封装的 OutputDebugString + OutputDebugString(L"ListenMessage\n"); + MessageBox(NULL, L"ListenMessage", L"ListenMessage", 0); +``` + ## 项目结构 ```sh From 3af8924756a98e247101958d085646fa9f21cfa9 Mon Sep 17 00:00:00 2001 From: Changhua Date: Sat, 1 Jun 2024 11:05:20 +0800 Subject: [PATCH 20/25] Hook with MinHook --- WeChatFerry/spy/receive_msg.cpp | 84 +++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/WeChatFerry/spy/receive_msg.cpp b/WeChatFerry/spy/receive_msg.cpp index 0ca30a6..8a225a4 100644 --- a/WeChatFerry/spy/receive_msg.cpp +++ b/WeChatFerry/spy/receive_msg.cpp @@ -1,5 +1,6 @@ #pragma execution_character_set("utf-8") +#include "MinHook.h" #include "framework.h" #include #include @@ -21,16 +22,9 @@ extern queue gMsgQueue; extern WxCalls_t g_WxCalls; extern UINT64 g_WeChatWinDllAddr; -static DWORD reg_buffer = 0; -static DWORD recvMsgHookAddr = 0; -static DWORD recvMsgCallAddr = 0; -static DWORD recvMsgJumpBackAddr = 0; -static CHAR recvMsgBackupCode[5] = { 0 }; - -static DWORD recvPyqHookAddr = 0; -static DWORD recvPyqCallAddr = 0; -static DWORD recvPyqJumpBackAddr = 0; -static CHAR recvPyqBackupCode[5] = { 0 }; +typedef UINT64 (*funcRecvMsg_t)(UINT64, UINT64); +static funcRecvMsg_t funcRecvMsg = nullptr; +static funcRecvMsg_t realRecvMsg = nullptr; MsgTypes_t GetMsgTypes() { @@ -72,7 +66,77 @@ MsgTypes_t GetMsgTypes() return m; } + +static UINT64 DispatchMsg(UINT64 arg1, UINT64 arg2) +{ + LOG_INFO("DispatchMsg"); + return realRecvMsg(arg1, arg2); +} + +void ListenMessage() +{ + MH_STATUS status = MH_UNKNOWN; + if (gIsListening || (g_WeChatWinDllAddr == 0)) { + LOG_WARN("gIsListening || (g_WeChatWinDllAddr == 0)"); + return; + } + funcRecvMsg = (funcRecvMsg_t)(g_WeChatWinDllAddr + g_WxCalls.recvMsg.call); + + status = MH_Initialize(); + if (status != MH_OK) { + LOG_ERROR("MH_Initialize failed: {}", to_string(status)); + return; + } + + status = MH_CreateHook(&funcRecvMsg, &DispatchMsg, reinterpret_cast(&realRecvMsg)); + if (status != MH_OK) { + LOG_ERROR("MH_CreateHook failed: {}", to_string(status)); + return; + } + + status = MH_EnableHook(&funcRecvMsg); + if (status != MH_OK) { + LOG_ERROR("MH_EnableHook failed: {}", to_string(status)); + return; + } + + gIsListening = true; +} + +void UnListenMessage() +{ + MH_STATUS status = MH_UNKNOWN; + if (!gIsListening) { + return; + } + + status = MH_DisableHook(&recvMsgCallAddr); + if (status != MH_OK) { + LOG_ERROR("MH_DisableHook failed: {}", to_string(status)); + return; + } + + status = MH_Uninitialize(); + if (status != MH_OK) { + LOG_ERROR("MH_Uninitialize failed: {}", to_string(status)); + return; + } + + gIsListening = false; +} + #if 0 +// static DWORD reg_buffer = 0; +// static DWORD recvMsgHookAddr = 0; +// static DWORD recvMsgCallAddr = 0; +// static DWORD recvMsgJumpBackAddr = 0; +// static CHAR recvMsgBackupCode[5] = { 0 }; + +// static DWORD recvPyqHookAddr = 0; +// static DWORD recvPyqCallAddr = 0; +// static DWORD recvPyqJumpBackAddr = 0; +// static CHAR recvPyqBackupCode[5] = { 0 }; + void HookAddress(DWORD hookAddr, LPVOID funcAddr, CHAR recvMsgBackupCode[5]) { // 组装跳转数据 From c679be366f5344f6c639e8aacd50838b449bca6b Mon Sep 17 00:00:00 2001 From: Changhua Date: Sat, 1 Jun 2024 11:17:34 +0800 Subject: [PATCH 21/25] Fix typo --- WeChatFerry/spy/receive_msg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WeChatFerry/spy/receive_msg.cpp b/WeChatFerry/spy/receive_msg.cpp index 8a225a4..53cb55d 100644 --- a/WeChatFerry/spy/receive_msg.cpp +++ b/WeChatFerry/spy/receive_msg.cpp @@ -110,7 +110,7 @@ void UnListenMessage() return; } - status = MH_DisableHook(&recvMsgCallAddr); + status = MH_DisableHook(&funcRecvMsg); if (status != MH_OK) { LOG_ERROR("MH_DisableHook failed: {}", to_string(status)); return; From e217f35bdf09df346b500ee95b963d617f1f87e5 Mon Sep 17 00:00:00 2001 From: Changhua Date: Sun, 2 Jun 2024 16:23:13 +0800 Subject: [PATCH 22/25] Test receive message --- WeChatFerry/spy/receive_msg.cpp | 12 ++++++++---- WeChatFerry/spy/rpc_server.cpp | 5 +++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/WeChatFerry/spy/receive_msg.cpp b/WeChatFerry/spy/receive_msg.cpp index 53cb55d..f99793e 100644 --- a/WeChatFerry/spy/receive_msg.cpp +++ b/WeChatFerry/spy/receive_msg.cpp @@ -80,7 +80,7 @@ void ListenMessage() LOG_WARN("gIsListening || (g_WeChatWinDllAddr == 0)"); return; } - funcRecvMsg = (funcRecvMsg_t)(g_WeChatWinDllAddr + g_WxCalls.recvMsg.call); + funcRecvMsg = (funcRecvMsg_t)(g_WeChatWinDllAddr + 0x2206570); // TODO: Fix me status = MH_Initialize(); if (status != MH_OK) { @@ -88,13 +88,13 @@ void ListenMessage() return; } - status = MH_CreateHook(&funcRecvMsg, &DispatchMsg, reinterpret_cast(&realRecvMsg)); + status = MH_CreateHook(funcRecvMsg, &DispatchMsg, reinterpret_cast(&realRecvMsg)); if (status != MH_OK) { LOG_ERROR("MH_CreateHook failed: {}", to_string(status)); return; } - status = MH_EnableHook(&funcRecvMsg); + status = MH_EnableHook(funcRecvMsg); if (status != MH_OK) { LOG_ERROR("MH_EnableHook failed: {}", to_string(status)); return; @@ -110,7 +110,7 @@ void UnListenMessage() return; } - status = MH_DisableHook(&funcRecvMsg); + status = MH_DisableHook(funcRecvMsg); if (status != MH_OK) { LOG_ERROR("MH_DisableHook failed: {}", to_string(status)); return; @@ -125,6 +125,10 @@ void UnListenMessage() gIsListening = false; } +void ListenPyq() { } + +void UnListenPyq() { } + #if 0 // static DWORD reg_buffer = 0; // static DWORD recvMsgHookAddr = 0; diff --git a/WeChatFerry/spy/rpc_server.cpp b/WeChatFerry/spy/rpc_server.cpp index 2745b61..c450fac 100644 --- a/WeChatFerry/spy/rpc_server.cpp +++ b/WeChatFerry/spy/rpc_server.cpp @@ -426,7 +426,7 @@ bool func_forward_msg(uint64_t id, char *receiver, uint8_t *out, size_t *len) return true; } - +#endif static void PushMessage() { static uint8_t buffer[G_BUF_SIZE] = { 0 }; @@ -543,6 +543,7 @@ bool func_disable_recv_txt(uint8_t *out, size_t *len) return true; } +#if 0 bool func_exec_db_query(char *db, char *sql, uint8_t *out, size_t *len) { Response rsp = Response_init_default; @@ -907,7 +908,6 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len ret = func_forward_msg(req.msg.fm.id, req.msg.fm.receiver, out, out_len); break; } -#if 0 case Functions_FUNC_SEND_XML: { ret = func_send_xml(req.msg.xml, out, out_len); break; @@ -925,6 +925,7 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len ret = func_disable_recv_txt(out, out_len); break; } +#if 0 case Functions_FUNC_EXEC_DB_QUERY: { ret = func_exec_db_query(req.msg.query.db, req.msg.query.sql, out, out_len); break; From ebc268a29034f4a08df3783405f76e9063f4688a Mon Sep 17 00:00:00 2001 From: Changhua Date: Mon, 3 Jun 2024 23:06:02 +0800 Subject: [PATCH 23/25] Migrate to x64 --- WeChatFerry/com/util.cpp | 22 +++++++++++----------- WeChatFerry/com/util.h | 1 + 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/WeChatFerry/com/util.cpp b/WeChatFerry/com/util.cpp index a03c265..e52790c 100644 --- a/WeChatFerry/com/util.cpp +++ b/WeChatFerry/com/util.cpp @@ -165,7 +165,7 @@ int GetWeChatVersion(wchar_t *version) DWORD GetWeChatPid() { - DWORD pid = 0; + DWORD pid = 0; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) }; while (Process32Next(hSnapshot, &pe32)) { @@ -208,44 +208,44 @@ int OpenWeChat(DWORD *pid) return ERROR_SUCCESS; } -size_t GetWstringByAddress(UINT64 address, wchar_t *buffer, UINT64 buffer_size) +size_t GetWstringByAddress(UINT64 addr, wchar_t *buffer, UINT64 buffer_size) { - size_t strLength = GET_UINT64(address + 4); + size_t strLength = GET_DWORD(addr + 8); if (strLength == 0) { return 0; } else if (strLength > buffer_size) { strLength = buffer_size - 1; } - wmemcpy_s(buffer, strLength + 1, GET_WSTRING(address), strLength + 1); + wmemcpy_s(buffer, strLength + 1, GET_WSTRING(addr), strLength + 1); return strLength; } -string GetStringByAddress(UINT64 address) +string GetStringByAddress(UINT64 addr) { - UINT64 strLength = GET_UINT64(address + 4); - return Wstring2String(wstring(GET_WSTRING(address), strLength)); + size_t strLength = GET_DWORD(addr + 8); + return Wstring2String(wstring(GET_WSTRING(addr), strLength)); } string GetStringByStrAddr(UINT64 addr) { - UINT64 strLength = GET_UINT64(addr + 4); + size_t strLength = GET_DWORD(addr + 8); return strLength ? string(GET_STRING(addr), strLength) : string(); } string GetStringByWstrAddr(UINT64 addr) { - UINT64 strLength = GET_UINT64(addr + 4); + size_t strLength = GET_DWORD(addr + 8); return strLength ? Wstring2String(wstring(GET_WSTRING(addr), strLength)) : string(); } -UINT32 GetMemoryIntByAddress(HANDLE hProcess, UINT64 address) +UINT32 GetMemoryIntByAddress(HANDLE hProcess, UINT64 addr) { UINT32 value = 0; unsigned char data[4] = { 0 }; - if (ReadProcessMemory(hProcess, (LPVOID)address, 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); diff --git a/WeChatFerry/com/util.h b/WeChatFerry/com/util.h index f870ed6..8339464 100644 --- a/WeChatFerry/com/util.h +++ b/WeChatFerry/com/util.h @@ -9,6 +9,7 @@ #define WCFSPYDLL_DEBUG L"spy_debug.dll" #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))) From 0c46fb975c49ea8a91c3a26963b540e2aa7e47d5 Mon Sep 17 00:00:00 2001 From: Changhua Date: Tue, 4 Jun 2024 23:09:35 +0800 Subject: [PATCH 24/25] Update receive message --- WeChatFerry/spy/load_calls.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WeChatFerry/spy/load_calls.cpp b/WeChatFerry/spy/load_calls.cpp index 4b75cf8..0bffe4f 100644 --- a/WeChatFerry/spy/load_calls.cpp +++ b/WeChatFerry/spy/load_calls.cpp @@ -10,8 +10,8 @@ WxCalls_t wxCalls = { { 0x5AB8FC8, 0x5AB90A8, 0x5AB8FE8, 0x5A7F170 }, // User Info: wxid, nickname, mobile, home { 0x768140, 0xCE6C80, 0x756960 }, // Send Message /* Receive Message: - Hook, call, msgId, type, isSelf, ts, roomId, content, wxid, sign, thumb, extra, msgXml */ - { 0xD19A0B, 0x756960, 0x30, 0x38, 0x3C, 0x44, 0x48, 0x70, 0x180, 0x194, 0x1A8, 0x1BC, 0x1FC }, + Hook, call, msgId, type, isSelf, ts, roomId, content, wxid, sign, thumb, extra, msgXml */ + { 0x00, 0x2206570, 0x30, 0x38, 0x3C, 0x44, 0x48, 0x88, 0x240, 0x260, 0x280, 0x2A0, 0x308 }, { 0x768140, 0XF59E40, 0XCE6640, 0x756960 }, // Send Image Message { 0x76AE20, 0xF59E40, 0xB6D1F0, 0x756960 }, // Send File Message { 0xB8A70, 0x3ED5E0, 0x107F00, 0x3ED7B0, 0x2386FE4 }, // Send xml Message From 7f61793a1502b5198700fc66c672c22dde2e4007 Mon Sep 17 00:00:00 2001 From: Changhua Date: Wed, 5 Jun 2024 23:15:51 +0800 Subject: [PATCH 25/25] Impl receive message --- WeChatFerry/spy/receive_msg.cpp | 54 +++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/WeChatFerry/spy/receive_msg.cpp b/WeChatFerry/spy/receive_msg.cpp index f99793e..8a518e9 100644 --- a/WeChatFerry/spy/receive_msg.cpp +++ b/WeChatFerry/spy/receive_msg.cpp @@ -69,7 +69,57 @@ MsgTypes_t GetMsgTypes() static UINT64 DispatchMsg(UINT64 arg1, UINT64 arg2) { - LOG_INFO("DispatchMsg"); + WxMsg_t wxMsg = { 0 }; + try { + wxMsg.id = GET_QWORD(arg2 + g_WxCalls.recvMsg.msgId); + wxMsg.type = GET_DWORD(arg2 + g_WxCalls.recvMsg.type); + wxMsg.is_self = GET_DWORD(arg2 + g_WxCalls.recvMsg.isSelf); + wxMsg.ts = GET_DWORD(arg2 + g_WxCalls.recvMsg.ts); + wxMsg.content = GetStringByWstrAddr(arg2 + g_WxCalls.recvMsg.content); + wxMsg.sign = GetStringByWstrAddr(arg2 + g_WxCalls.recvMsg.sign); + wxMsg.xml = GetStringByWstrAddr(arg2 + g_WxCalls.recvMsg.msgXml); + + string roomid = GetStringByWstrAddr(arg2 + g_WxCalls.recvMsg.roomId); + if (roomid.find("@chatroom") != string::npos) { // 群 ID 的格式为 xxxxxxxxxxx@chatroom + wxMsg.is_group = true; + wxMsg.roomid = roomid; + if (wxMsg.is_self) { + wxMsg.sender = GetSelfWxid(); + } else { + wxMsg.sender = GetStringByWstrAddr(arg2 + g_WxCalls.recvMsg.wxid); + } + } else { + wxMsg.is_group = false; + if (wxMsg.is_self) { + wxMsg.sender = GetSelfWxid(); + } else { + wxMsg.sender = roomid; + } + } + + wxMsg.thumb = GetStringByWstrAddr(arg2 + g_WxCalls.recvMsg.thumb); + if (!wxMsg.thumb.empty()) { + wxMsg.thumb = GetHomePath() + wxMsg.thumb; + replace(wxMsg.thumb.begin(), wxMsg.thumb.end(), '\\', '/'); + } + + wxMsg.extra = GetStringByWstrAddr(arg2 + g_WxCalls.recvMsg.extra); + if (!wxMsg.extra.empty()) { + wxMsg.extra = GetHomePath() + wxMsg.extra; + replace(wxMsg.extra.begin(), wxMsg.extra.end(), '\\', '/'); + } + } catch (const std::exception &e) { + LOG_ERROR(GB2312ToUtf8(e.what())); + } catch (...) { + LOG_ERROR("Unknow exception."); + } + + { + unique_lock lock(gMutex); + gMsgQueue.push(wxMsg); // 推送到队列 + } + + gCV.notify_all(); // 通知各方消息就绪 return realRecvMsg(arg1, arg2); } @@ -80,7 +130,7 @@ void ListenMessage() LOG_WARN("gIsListening || (g_WeChatWinDllAddr == 0)"); return; } - funcRecvMsg = (funcRecvMsg_t)(g_WeChatWinDllAddr + 0x2206570); // TODO: Fix me + funcRecvMsg = (funcRecvMsg_t)(g_WeChatWinDllAddr + g_WxCalls.recvMsg.call); status = MH_Initialize(); if (status != MH_OK) {