From 84665f25758812822acf849384647fc0bf406627 Mon Sep 17 00:00:00 2001 From: ljc545w Date: Sat, 18 Jun 2022 20:47:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E7=90=86=E6=A0=87=E5=A4=B4=E5=92=8C?= =?UTF-8?q?=E6=BA=90=E4=BB=A3=E7=A0=81=EF=BC=8C=E6=B7=BB=E5=8A=A0=E9=80=9A?= =?UTF-8?q?=E7=94=A8driver?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 +- ComWeChatRobot.sln | 76 +++++++++ DWeChatRobot/AddBrandContact.cpp | 4 +- DWeChatRobot/AddFriend.h | 4 +- DWeChatRobot/AddFriendByV3.cpp | 4 + DWeChatRobot/AddFriendByWxid.cpp | 4 + DWeChatRobot/CheckFriendStatus.cpp | 2 + DWeChatRobot/CheckFriendStatus.h | 2 + DWeChatRobot/DWeChatRobot.vcxproj | 150 ++++++++++++++++- DWeChatRobot/DWeChatRobot.vcxproj.filters | 12 +- DWeChatRobot/DWeChatRobot.vcxproj.user | 5 + DWeChatRobot/DbBackup.cpp | 16 +- DWeChatRobot/DbBackup.h | 14 +- DWeChatRobot/DbExecuteSql.cpp | 30 ++-- DWeChatRobot/DbExecuteSql.h | 6 +- DWeChatRobot/DeleteUser.cpp | 4 +- DWeChatRobot/DeleteUser.h | 4 +- DWeChatRobot/FriendList.cpp | 37 ++--- DWeChatRobot/FriendList.h | 6 +- DWeChatRobot/GetChatRoomMembers.h | 4 +- DWeChatRobot/GetChatRoomMemebers.cpp | 2 + DWeChatRobot/GetDbHandles.cpp | 5 +- DWeChatRobot/GetDbHandles.h | 39 +---- DWeChatRobot/HookImageMessage.cpp | 4 +- DWeChatRobot/HookVoiceMessage.cpp | 4 +- DWeChatRobot/ReceiveMessage.cpp | 35 +--- DWeChatRobot/ReceiveMessage.h | 17 +- DWeChatRobot/SearchContact.h | 12 +- DWeChatRobot/SearchContactByCache.cpp | 45 +++--- DWeChatRobot/SearchContactByNet.cpp | 33 +--- DWeChatRobot/SelfInfo.cpp | 40 +++-- DWeChatRobot/SelfInfo.h | 5 +- DWeChatRobot/SendAppMsg.cpp | 15 +- DWeChatRobot/SendAppMsg.h | 4 +- DWeChatRobot/SendArticle.cpp | 4 + DWeChatRobot/SendArticle.h | 2 + DWeChatRobot/SendAtText.cpp | 4 + DWeChatRobot/SendAtText.h | 4 +- DWeChatRobot/SendCard.cpp | 4 + DWeChatRobot/SendCard.h | 2 + DWeChatRobot/SendFile.cpp | 4 + DWeChatRobot/SendFile.h | 4 +- DWeChatRobot/SendImage.cpp | 4 + DWeChatRobot/SendImage.h | 4 +- DWeChatRobot/SendText.cpp | 4 + DWeChatRobot/SendText.h | 4 +- DWeChatRobot/VerifyFriendApply.cpp | 4 + DWeChatRobot/VerifyFriendApply.h | 4 +- DWeChatRobot/comclient.cpp | 5 +- DWeChatRobot/comclient.h | 4 +- DWeChatRobot/dllmain.cpp | 6 +- DWeChatRobot/pch.cpp | 5 +- DWeChatRobot/pch.h | 97 +---------- DWeChatRobot/wechatver.cpp | 8 +- DWeChatRobot/wechatver.h | 5 +- DWeChatRobot/wxapi.h | 42 +++++ DWeChatRobot/wxdata.h | 155 ++++++++++++++++++ DWeChatRobot/wxsocket.cpp | 33 ++-- DWeChatRobot/wxsocket.h | 4 - DWeChatRobot/wxsocketapi.h | 10 +- Release/CWeChatRobot.exe | Bin 119808 -> 119808 bytes Release/DWeChatRobot.dll | Bin 82432 -> 81920 bytes Release/socket/SWeChatRobot.dll | Bin 0 -> 45056 bytes Release/socket/wxDriver.dll | Bin 0 -> 15360 bytes Release/socket/wxDriver64.dll | Bin 0 -> 20992 bytes wxDriver/dllmain.cpp | 19 +++ wxDriver/driver.cpp | 177 ++++++++++++++++++++ wxDriver/driver.h | 23 +++ wxDriver/driverdata.h | 2 + wxDriver/framework.h | 6 + wxDriver/inject.cpp | 112 +++++++++++++ wxDriver/ntapi.cpp | 90 +++++++++++ wxDriver/ntapi.h | 187 ++++++++++++++++++++++ wxDriver/pch.cpp | 5 + wxDriver/pch.h | 13 ++ wxDriver/wxDriver.vcxproj | 183 +++++++++++++++++++++ wxDriver/wxDriver.vcxproj.filters | 51 ++++++ wxDriver/wxDriver.vcxproj.user | 4 + 78 files changed, 1603 insertions(+), 344 deletions(-) create mode 100644 DWeChatRobot/wxapi.h create mode 100644 DWeChatRobot/wxdata.h delete mode 100644 DWeChatRobot/wxsocket.h create mode 100644 Release/socket/SWeChatRobot.dll create mode 100644 Release/socket/wxDriver.dll create mode 100644 Release/socket/wxDriver64.dll create mode 100644 wxDriver/dllmain.cpp create mode 100644 wxDriver/driver.cpp create mode 100644 wxDriver/driver.h create mode 100644 wxDriver/driverdata.h create mode 100644 wxDriver/framework.h create mode 100644 wxDriver/inject.cpp create mode 100644 wxDriver/ntapi.cpp create mode 100644 wxDriver/ntapi.h create mode 100644 wxDriver/pch.cpp create mode 100644 wxDriver/pch.h create mode 100644 wxDriver/wxDriver.vcxproj create mode 100644 wxDriver/wxDriver.vcxproj.filters create mode 100644 wxDriver/wxDriver.vcxproj.user diff --git a/.gitignore b/.gitignore index 31d5c74..0b491aa 100644 --- a/.gitignore +++ b/.gitignore @@ -4,10 +4,13 @@ *.lib */Debug/ */Release/ +*/SOCKET_Debug/ +*/SOCKET_Release/ +*/Win32/ +*/x64/ *.rar /.vs/ /x64 -*/x64/ */obj/ /wxRobot/bin/Debug/ /wxRobot/bin/Release/*.pdb diff --git a/ComWeChatRobot.sln b/ComWeChatRobot.sln index ecb0fd1..0cfc740 100644 --- a/ComWeChatRobot.sln +++ b/ComWeChatRobot.sln @@ -20,6 +20,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CSharp", "CSharp", "{4DE1F6 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wxRobot", "wxRobot\wxRobot.csproj", "{10504CFA-6D19-4A97-8728-11BCE6C2499F}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxDriver", "wxDriver\wxDriver.vcxproj", "{B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -28,6 +30,12 @@ Global Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 + SOCKET_DEBUG|Any CPU = SOCKET_DEBUG|Any CPU + SOCKET_DEBUG|x64 = SOCKET_DEBUG|x64 + SOCKET_DEBUG|x86 = SOCKET_DEBUG|x86 + SOCKET_Release|Any CPU = SOCKET_Release|Any CPU + SOCKET_Release|x64 = SOCKET_Release|x64 + SOCKET_Release|x86 = SOCKET_Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.Debug|Any CPU.ActiveCfg = Debug|Win32 @@ -40,6 +48,18 @@ Global {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.Release|x64.Build.0 = Release|x64 {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.Release|x86.ActiveCfg = Release|Win32 {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.Release|x86.Build.0 = Release|Win32 + {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.SOCKET_DEBUG|Any CPU.ActiveCfg = Release|x64 + {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.SOCKET_DEBUG|Any CPU.Build.0 = Release|x64 + {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.SOCKET_DEBUG|x64.ActiveCfg = Release|x64 + {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.SOCKET_DEBUG|x64.Build.0 = Release|x64 + {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.SOCKET_DEBUG|x86.ActiveCfg = Release|Win32 + {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.SOCKET_DEBUG|x86.Build.0 = Release|Win32 + {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.SOCKET_Release|Any CPU.ActiveCfg = Release|x64 + {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.SOCKET_Release|Any CPU.Build.0 = Release|x64 + {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.SOCKET_Release|x64.ActiveCfg = Release|x64 + {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.SOCKET_Release|x64.Build.0 = Release|x64 + {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.SOCKET_Release|x86.ActiveCfg = Release|Win32 + {F54A8A7E-C2C0-4FD8-B625-59C77FF613BA}.SOCKET_Release|x86.Build.0 = Release|Win32 {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.Debug|Any CPU.ActiveCfg = Debug|Win32 {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.Debug|x64.ActiveCfg = Debug|x64 {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.Debug|x64.Build.0 = Debug|x64 @@ -50,6 +70,18 @@ Global {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.Release|x64.Build.0 = Release|x64 {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.Release|x86.ActiveCfg = Release|Win32 {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.Release|x86.Build.0 = Release|Win32 + {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.SOCKET_DEBUG|Any CPU.ActiveCfg = Release|x64 + {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.SOCKET_DEBUG|Any CPU.Build.0 = Release|x64 + {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.SOCKET_DEBUG|x64.ActiveCfg = Release|x64 + {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.SOCKET_DEBUG|x64.Build.0 = Release|x64 + {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.SOCKET_DEBUG|x86.ActiveCfg = Release|Win32 + {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.SOCKET_DEBUG|x86.Build.0 = Release|Win32 + {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.SOCKET_Release|Any CPU.ActiveCfg = Release|x64 + {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.SOCKET_Release|Any CPU.Build.0 = Release|x64 + {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.SOCKET_Release|x64.ActiveCfg = Release|x64 + {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.SOCKET_Release|x64.Build.0 = Release|x64 + {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.SOCKET_Release|x86.ActiveCfg = Release|Win32 + {3F7198C7-68D1-4BBA-9BF2-B7FC67A9426E}.SOCKET_Release|x86.Build.0 = Release|Win32 {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.Debug|Any CPU.ActiveCfg = Debug|Win32 {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.Debug|x64.ActiveCfg = Debug|x64 {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.Debug|x64.Build.0 = Debug|x64 @@ -60,6 +92,16 @@ Global {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.Release|x64.Build.0 = Release|x64 {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.Release|x86.ActiveCfg = Release|Win32 {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.Release|x86.Build.0 = Release|Win32 + {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.SOCKET_DEBUG|Any CPU.ActiveCfg = SOCKET_Debug|Win32 + {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.SOCKET_DEBUG|x64.ActiveCfg = SOCKET_Debug|x64 + {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.SOCKET_DEBUG|x64.Build.0 = SOCKET_Debug|x64 + {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.SOCKET_DEBUG|x86.ActiveCfg = SOCKET_Debug|Win32 + {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.SOCKET_DEBUG|x86.Build.0 = SOCKET_Debug|Win32 + {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.SOCKET_Release|Any CPU.ActiveCfg = SOCKET_Release|Win32 + {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.SOCKET_Release|x64.ActiveCfg = SOCKET_Release|x64 + {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.SOCKET_Release|x64.Build.0 = SOCKET_Release|x64 + {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.SOCKET_Release|x86.ActiveCfg = SOCKET_Release|Win32 + {C0FC8DAB-0590-46AC-9270-6FEA45D52390}.SOCKET_Release|x86.Build.0 = SOCKET_Release|Win32 {10504CFA-6D19-4A97-8728-11BCE6C2499F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {10504CFA-6D19-4A97-8728-11BCE6C2499F}.Debug|Any CPU.Build.0 = Debug|Any CPU {10504CFA-6D19-4A97-8728-11BCE6C2499F}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -72,6 +114,40 @@ Global {10504CFA-6D19-4A97-8728-11BCE6C2499F}.Release|x64.Build.0 = Release|Any CPU {10504CFA-6D19-4A97-8728-11BCE6C2499F}.Release|x86.ActiveCfg = Release|Any CPU {10504CFA-6D19-4A97-8728-11BCE6C2499F}.Release|x86.Build.0 = Release|Any CPU + {10504CFA-6D19-4A97-8728-11BCE6C2499F}.SOCKET_DEBUG|Any CPU.ActiveCfg = Release|Any CPU + {10504CFA-6D19-4A97-8728-11BCE6C2499F}.SOCKET_DEBUG|Any CPU.Build.0 = Release|Any CPU + {10504CFA-6D19-4A97-8728-11BCE6C2499F}.SOCKET_DEBUG|x64.ActiveCfg = Release|Any CPU + {10504CFA-6D19-4A97-8728-11BCE6C2499F}.SOCKET_DEBUG|x64.Build.0 = Release|Any CPU + {10504CFA-6D19-4A97-8728-11BCE6C2499F}.SOCKET_DEBUG|x86.ActiveCfg = Release|Any CPU + {10504CFA-6D19-4A97-8728-11BCE6C2499F}.SOCKET_DEBUG|x86.Build.0 = Release|Any CPU + {10504CFA-6D19-4A97-8728-11BCE6C2499F}.SOCKET_Release|Any CPU.ActiveCfg = Release|Any CPU + {10504CFA-6D19-4A97-8728-11BCE6C2499F}.SOCKET_Release|Any CPU.Build.0 = Release|Any CPU + {10504CFA-6D19-4A97-8728-11BCE6C2499F}.SOCKET_Release|x64.ActiveCfg = Release|Any CPU + {10504CFA-6D19-4A97-8728-11BCE6C2499F}.SOCKET_Release|x64.Build.0 = Release|Any CPU + {10504CFA-6D19-4A97-8728-11BCE6C2499F}.SOCKET_Release|x86.ActiveCfg = Release|Any CPU + {10504CFA-6D19-4A97-8728-11BCE6C2499F}.SOCKET_Release|x86.Build.0 = Release|Any CPU + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.Debug|x64.ActiveCfg = Debug|x64 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.Debug|x64.Build.0 = Debug|x64 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.Debug|x86.ActiveCfg = Debug|Win32 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.Debug|x86.Build.0 = Debug|Win32 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.Release|Any CPU.ActiveCfg = Release|Win32 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.Release|x64.ActiveCfg = Release|x64 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.Release|x64.Build.0 = Release|x64 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.Release|x86.ActiveCfg = Release|Win32 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.Release|x86.Build.0 = Release|Win32 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.SOCKET_DEBUG|Any CPU.ActiveCfg = Debug|Win32 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.SOCKET_DEBUG|Any CPU.Build.0 = Debug|Win32 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.SOCKET_DEBUG|x64.ActiveCfg = Debug|x64 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.SOCKET_DEBUG|x64.Build.0 = Debug|x64 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.SOCKET_DEBUG|x86.ActiveCfg = Debug|Win32 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.SOCKET_DEBUG|x86.Build.0 = Debug|Win32 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.SOCKET_Release|Any CPU.ActiveCfg = Debug|Win32 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.SOCKET_Release|Any CPU.Build.0 = Debug|Win32 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.SOCKET_Release|x64.ActiveCfg = Release|x64 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.SOCKET_Release|x64.Build.0 = Release|x64 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.SOCKET_Release|x86.ActiveCfg = Release|Win32 + {B8740C2A-CBE7-4873-9669-E0DFEC4A3B8D}.SOCKET_Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/DWeChatRobot/AddBrandContact.cpp b/DWeChatRobot/AddBrandContact.cpp index 26dbd58..e97c08b 100644 --- a/DWeChatRobot/AddBrandContact.cpp +++ b/DWeChatRobot/AddBrandContact.cpp @@ -53,7 +53,9 @@ BOOL __stdcall AddBrandContact(wchar_t* PublicId) { return isSuccess; } +#ifndef USE_SOCKET BOOL AddBrandContactRemote(LPVOID lpParameter) { int isSuccess = AddBrandContact((wchar_t*)lpParameter); return isSuccess; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/DWeChatRobot/AddFriend.h b/DWeChatRobot/AddFriend.h index 5b5c474..a5301c7 100644 --- a/DWeChatRobot/AddFriend.h +++ b/DWeChatRobot/AddFriend.h @@ -4,6 +4,8 @@ BOOL __stdcall AddFriendByV3(wchar_t* v3, wchar_t* message,int AddType); BOOL __stdcall AddFriendByWxid(wchar_t* wxid, wchar_t* message); BOOL __stdcall AddBrandContact(wchar_t* PublicId); +#ifndef USE_SOCKET extern "C" __declspec(dllexport) BOOL AddFriendByV3Remote(LPVOID lpParameter); extern "C" __declspec(dllexport) BOOL AddFriendByWxidRemote(LPVOID lpParameter); -extern "C" __declspec(dllexport) BOOL AddBrandContactRemote(LPVOID lpParameter); \ No newline at end of file +extern "C" __declspec(dllexport) BOOL AddBrandContactRemote(LPVOID lpParameter); +#endif \ No newline at end of file diff --git a/DWeChatRobot/AddFriendByV3.cpp b/DWeChatRobot/AddFriendByV3.cpp index e6b76e3..b59e814 100644 --- a/DWeChatRobot/AddFriendByV3.cpp +++ b/DWeChatRobot/AddFriendByV3.cpp @@ -21,17 +21,21 @@ struct AddFriendByV3ParamStruct { char nullbuffer[0xC] = { 0 }; }; +#ifndef USE_SOCKET struct AddFriendByV3Struct { wchar_t* wxid; wchar_t* message; int AddType; }; +#endif +#ifndef USE_SOCKET BOOL AddFriendByV3Remote(LPVOID lpParameter) { AddFriendByV3Struct* afbvs = (AddFriendByV3Struct*)lpParameter; BOOL isSuccess = AddFriendByV3(afbvs->wxid, afbvs->message,afbvs->AddType); return isSuccess; } +#endif BOOL __stdcall AddFriendByV3(wchar_t* v3, wchar_t* message,int AddType) { DWORD WeChatWinBase = GetWeChatWinBase(); diff --git a/DWeChatRobot/AddFriendByWxid.cpp b/DWeChatRobot/AddFriendByWxid.cpp index 90b2b00..466bb7d 100644 --- a/DWeChatRobot/AddFriendByWxid.cpp +++ b/DWeChatRobot/AddFriendByWxid.cpp @@ -21,16 +21,20 @@ struct AddFriendByWxidParamStruct { char nullbuffer[0xC] = { 0 }; }; +#ifndef USE_SOCKET struct AddFriendByWxidStruct { wchar_t* wxid; wchar_t* message; }; +#endif +#ifndef USE_SOCKET BOOL AddFriendByWxidRemote(LPVOID lpParameter) { AddFriendByWxidStruct* afbws = (AddFriendByWxidStruct*)lpParameter; BOOL isSuccess = AddFriendByWxid(afbws->wxid, afbws->message); return isSuccess; } +#endif BOOL __stdcall AddFriendByWxid(wchar_t* wxid,wchar_t* message) { DWORD WeChatWinBase = GetWeChatWinBase(); diff --git a/DWeChatRobot/CheckFriendStatus.cpp b/DWeChatRobot/CheckFriendStatus.cpp index 61fca45..60e2ee4 100644 --- a/DWeChatRobot/CheckFriendStatus.cpp +++ b/DWeChatRobot/CheckFriendStatus.cpp @@ -98,6 +98,7 @@ VOID UnHookFriendStatusCode() { CheckFriendStatusHooked = false; } +#ifndef USE_SOCKET /* * 供外部调用的检查好友状态接口,检查并返回状态码 * lparameter:要检查的联系人wxid保存地址 @@ -107,6 +108,7 @@ DWORD CheckFriendStatusRemote(LPVOID lparameter) { CheckFriendStatus((wchar_t*)lparameter); return LocalFriendStatus; } +#endif /* * 检查好友状态的具体实现 diff --git a/DWeChatRobot/CheckFriendStatus.h b/DWeChatRobot/CheckFriendStatus.h index 23b5a99..8ea565d 100644 --- a/DWeChatRobot/CheckFriendStatus.h +++ b/DWeChatRobot/CheckFriendStatus.h @@ -1,7 +1,9 @@ #pragma once #include +#ifndef USE_SOCKET extern "C" __declspec(dllexport) DWORD CheckFriendStatusRemote(LPVOID lparameter); +#endif VOID __stdcall CheckFriendStatus(wchar_t* wxid); VOID UnHookFriendStatusCode(); VOID HookFriendStatusCode(); \ No newline at end of file diff --git a/DWeChatRobot/DWeChatRobot.vcxproj b/DWeChatRobot/DWeChatRobot.vcxproj index c1f3b90..be143e7 100644 --- a/DWeChatRobot/DWeChatRobot.vcxproj +++ b/DWeChatRobot/DWeChatRobot.vcxproj @@ -17,6 +17,22 @@ Release x64 + + SOCKET_Debug + Win32 + + + SOCKET_Debug + x64 + + + SOCKET_Release + Win32 + + + SOCKET_Release + x64 + 16.0 @@ -33,6 +49,12 @@ v142 Unicode + + DynamicLibrary + true + v142 + Unicode + DynamicLibrary false @@ -40,12 +62,25 @@ true Unicode + + DynamicLibrary + false + v142 + true + Unicode + DynamicLibrary true v143 Unicode + + DynamicLibrary + true + v143 + Unicode + DynamicLibrary false @@ -53,6 +88,13 @@ true Unicode + + DynamicLibrary + false + v143 + true + Unicode + @@ -61,31 +103,62 @@ + + + + + + + + + + + + true $(ProjectName) $(IncludePath) + + true + SWeChatRobot + $(IncludePath) + $(Configuration)\ + $(SolutionDir)Debug\socket\ + false $(ProjectName) + + false + SWeChatRobot + $(Configuration)\ + $(SolutionDir)Release\socket\ + true + + true + false + + false + Level3 @@ -101,6 +174,22 @@ false + + + Level3 + true + WIN32;_DEBUG;MYWECHATROBOT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + /D "USE_SOCKET" /D "_CRT_SECURE_NO_WARNINGS" %(AdditionalOptions) + + + Windows + true + false + + Level3 @@ -120,6 +209,26 @@ false + + + Level3 + true + true + true + WIN32;NDEBUG;MYWECHATROBOT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + /D "USE_SOCKET" /D "_CRT_SECURE_NO_WARNINGS" %(AdditionalOptions) + + + Windows + true + true + true + false + + Level3 @@ -135,6 +244,21 @@ false + + + Level3 + true + _DEBUG;MYWECHATROBOT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + Level3 @@ -154,6 +278,25 @@ false + + + Level3 + true + true + true + NDEBUG;MYWECHATROBOT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + + @@ -180,7 +323,8 @@ - + + @@ -200,9 +344,13 @@ Create + Create Create + Create Create + Create Create + Create diff --git a/DWeChatRobot/DWeChatRobot.vcxproj.filters b/DWeChatRobot/DWeChatRobot.vcxproj.filters index faeb435..60a83f7 100644 --- a/DWeChatRobot/DWeChatRobot.vcxproj.filters +++ b/DWeChatRobot/DWeChatRobot.vcxproj.filters @@ -25,9 +25,6 @@ {069b8c09-e473-4bba-a49e-571f35f2efef} - - {25f77de8-b12c-4f2b-a3ac-0260b6a16897} - {8ad1ff87-550b-4942-8ebd-afbe1cfaddc9} @@ -171,15 +168,18 @@ 鍙戦佹秷鎭痋鍙戦佸皬绋嬪簭 - - wxsocket - comclient wxsocket + + 閫氱敤鏍囧ご + + + 閫氱敤鏍囧ご + diff --git a/DWeChatRobot/DWeChatRobot.vcxproj.user b/DWeChatRobot/DWeChatRobot.vcxproj.user index 77449a7..ea733e2 100644 --- a/DWeChatRobot/DWeChatRobot.vcxproj.user +++ b/DWeChatRobot/DWeChatRobot.vcxproj.user @@ -6,4 +6,9 @@ WindowsLocalDebugger D:\Tencent\WeChat\WeChat.exe + + + WindowsLocalDebugger + D:\Tencent\WeChat\WeChat.exe + \ No newline at end of file diff --git a/DWeChatRobot/DbBackup.cpp b/DWeChatRobot/DbBackup.cpp index c46dd5c..2835a6a 100644 --- a/DWeChatRobot/DbBackup.cpp +++ b/DWeChatRobot/DbBackup.cpp @@ -2,6 +2,18 @@ BOOL SQLite3_Backup_Init_Patched = FALSE; +/* +* 外部调用时传递的参数类型 +* DbHandle:要备份的数据库句柄 +* BackupFile:备份的保存位置 +*/ +#ifndef USE_SOCKET +struct BackupStruct { + DWORD DbHandle; + char* BackupFile; +}; +#endif + /* * 数据库备份函数 * return:int,无异常返回`0`,有异常返回非0值 @@ -136,8 +148,10 @@ int BackupSQLiteDB(DWORD DbHandle,const char* BackupFile) * lpParameter:`BackupStruct`类型结构体指针 * return:int,无异常返回`0`,有异常返回非0值 */ +#ifndef USE_SOCKET int BackupSQLiteDBRemote(LPVOID lpParameter) { BackupStruct* param = (BackupStruct*)lpParameter; int rc = BackupSQLiteDB(param->DbHandle,(const char*)param->BackupFile); return rc; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/DWeChatRobot/DbBackup.h b/DWeChatRobot/DbBackup.h index 75296bb..b4205c9 100644 --- a/DWeChatRobot/DbBackup.h +++ b/DWeChatRobot/DbBackup.h @@ -1,13 +1,7 @@ #pragma once #include -/* -* 外部调用时传递的参数类型 -* DbHandle:要备份的数据库句柄 -* BackupFile:备份的保存位置 -*/ -struct BackupStruct { - DWORD DbHandle; - char* BackupFile; -}; + int BackupSQLiteDB(DWORD DbHandle, const char* BackupFile); -extern "C" __declspec(dllexport) int BackupSQLiteDBRemote(LPVOID lpParameter); \ No newline at end of file +#ifndef USE_SOCKET +extern "C" __declspec(dllexport) int BackupSQLiteDBRemote(LPVOID lpParameter); +#endif \ No newline at end of file diff --git a/DWeChatRobot/DbExecuteSql.cpp b/DWeChatRobot/DbExecuteSql.cpp index 430e92c..5b4d062 100644 --- a/DWeChatRobot/DbExecuteSql.cpp +++ b/DWeChatRobot/DbExecuteSql.cpp @@ -26,10 +26,12 @@ DWORD sqlite3_execAddr = WeChatWinBase + OffsetFromIdaAddr(IDA_SQLITE3_EXEC_ADDR * ptrDb:数据库句柄 * ptrSql:保存sql的地址 */ +#ifndef USE_SOCKET struct executeParams { DWORD ptrDb; DWORD ptrSql; }; +#endif /* * 保存查询结果的结构 @@ -179,12 +181,14 @@ void ClearResultArray() { * sql:要执行的SQL * callback:回调函数地址 * data:传递给回调函数的参数 -* return:BOOL,执行成功返回`1`,执行失败返回`0` +* return:void*,执行成功返回数组指针,执行失败返回`0` */ -BOOL ExecuteSQL(DWORD ptrDb,const char* sql,DWORD callback,void* data) { +void* ExecuteSQL(DWORD ptrDb,const char* sql,DWORD callback,void* data) { Sqlite3_exec p_Sqlite3_exec = (Sqlite3_exec)sqlite3_execAddr; int status = p_Sqlite3_exec(ptrDb,sql, (sqlite3_callback)callback,data,0); - return status == 0; + if (status != SQLITE_OK) + return NULL; + return SQLResult.data(); } /* @@ -192,12 +196,13 @@ BOOL ExecuteSQL(DWORD ptrDb,const char* sql,DWORD callback,void* data) { * lpParameter:`executeParams`类型结构体指针 * return:DWORD,如果SQL执行成功,返回`SQLResult`首成员地址,否则返回0 */ +#ifndef USE_SOCKET DWORD ExecuteSQLRemote(LPVOID lpParameter){ ClearResultArray(); executeParams* sqlparam = (executeParams*)lpParameter; - BOOL status = ExecuteSQL(sqlparam->ptrDb, (const char*)sqlparam->ptrSql, (DWORD)selectdbinfo, &result); + void* status = ExecuteSQL(sqlparam->ptrDb, (const char*)sqlparam->ptrSql, (DWORD)selectdbinfo, &result); - if (status) { + if (status != NULL) { result.SQLResultAddr = (DWORD)SQLResult.data(); return (DWORD)&result; } @@ -206,8 +211,9 @@ DWORD ExecuteSQLRemote(LPVOID lpParameter){ } return 0; } +#endif -static BOOL SelectData(DWORD db,const char* sql,void* data) +void* SelectData(DWORD db,const char* sql,void* data) { executeResult* pdata = (executeResult*)data; DWORD wxBaseAddress = GetWeChatWinBase(); @@ -222,7 +228,7 @@ static BOOL SelectData(DWORD db,const char* sql,void* data) DWORD* stmt; int rc = p_Sqlite3_prepare(db, sql, -1, &stmt, 0); if (rc != SQLITE_OK) - return rc; + return NULL; while (p_Sqlite3_step(stmt) == SQLITE_ROW) { int col_count = p_Sqlite3_column_count(stmt); @@ -264,15 +270,16 @@ static BOOL SelectData(DWORD db,const char* sql,void* data) pdata->length++; } p_Sqlite3_finalize(stmt); - return rc == 0; + return SQLResult.data(); } +#ifndef USE_SOCKET int SelectDataRemote(LPVOID lpParameter) { ClearResultArray(); executeParams* sqlparam = (executeParams*)lpParameter; - BOOL status = SelectData(sqlparam->ptrDb, (const char*)sqlparam->ptrSql, &result); + void* status = SelectData(sqlparam->ptrDb, (const char*)sqlparam->ptrSql, &result); - if (status) { + if (status != NULL) { result.SQLResultAddr = (DWORD)SQLResult.data(); return (DWORD)&result; } @@ -280,4 +287,5 @@ int SelectDataRemote(LPVOID lpParameter) { result.length = 0; } return 0; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/DWeChatRobot/DbExecuteSql.h b/DWeChatRobot/DbExecuteSql.h index f8274c6..be96319 100644 --- a/DWeChatRobot/DbExecuteSql.h +++ b/DWeChatRobot/DbExecuteSql.h @@ -4,7 +4,9 @@ int GetDbInfo(void* data, int argc, char** argv, char** azColName); int selectdbinfo(void* data, int argc, char** argv, char** azColName); int query(void* data, int argc, char** argv, char** azColName); - +#ifndef USE_SOCKET extern "C" __declspec(dllexport) DWORD ExecuteSQLRemote(LPVOID lpParameter); extern "C" __declspec(dllexport) int SelectDataRemote(LPVOID lpParameter); -BOOL ExecuteSQL(DWORD ptrDb, const char* sql, DWORD callback, void* data); \ No newline at end of file +#endif +void* ExecuteSQL(DWORD ptrDb, const char* sql, DWORD callback, void* data); +void* SelectData(DWORD db, const char* sql, void* data); \ No newline at end of file diff --git a/DWeChatRobot/DeleteUser.cpp b/DWeChatRobot/DeleteUser.cpp index 7bcff42..49c28bc 100644 --- a/DWeChatRobot/DeleteUser.cpp +++ b/DWeChatRobot/DeleteUser.cpp @@ -31,7 +31,9 @@ BOOL __stdcall DeleteUser(wchar_t* wxid) { return isSuccess; } +#ifndef USE_SOCKET BOOL DeleteUserRemote(LPVOID lpParameter) { BOOL isSuccess = DeleteUser((wchar_t*)lpParameter); return isSuccess; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/DWeChatRobot/DeleteUser.h b/DWeChatRobot/DeleteUser.h index 3b6d826..d86a011 100644 --- a/DWeChatRobot/DeleteUser.h +++ b/DWeChatRobot/DeleteUser.h @@ -1,4 +1,6 @@ #pragma once #include BOOL __stdcall DeleteUser(wchar_t* wxid); -extern "C" __declspec(dllexport) BOOL DeleteUserRemote(LPVOID lpParameter); \ No newline at end of file +#ifndef USE_SOCKET +extern "C" __declspec(dllexport) BOOL DeleteUserRemote(LPVOID lpParameter); +#endif \ No newline at end of file diff --git a/DWeChatRobot/FriendList.cpp b/DWeChatRobot/FriendList.cpp index 14efc03..021f22e 100644 --- a/DWeChatRobot/FriendList.cpp +++ b/DWeChatRobot/FriendList.cpp @@ -4,29 +4,8 @@ // 通讯录左树偏移 #define LeftTreeOffset 0x23638F4 -/* -* 保存单个好友信息的结构体 -* wxIdAddr:wxid保存地址 -* wxNumberAddr:微信号保存地址 -* wxNickNameAddr:昵称保存地址 -* wxRemarkAddr:备注保存地址 -* WxFriendStructW:默认构造函数 -*/ -struct WxFriendStructW { - DWORD wxIdAddr; - DWORD wxNumberAddr; - DWORD wxNickNameAddr; - DWORD wxRemarkAddr; - WxFriendStructW(DWORD wxIdAddr, DWORD wxNumberAddr, DWORD wxNickNameAddr, DWORD wxRemarkAddr) { - this->wxIdAddr = wxIdAddr; - this->wxNumberAddr = wxNumberAddr; - this->wxNickNameAddr = wxNickNameAddr; - this->wxRemarkAddr = wxRemarkAddr; - } -}; - // 保存所有好友信息的动态数组 -vector WxFriendList; +vector WxFriendList; /* * 供外部调用的获取好友列表接口1 @@ -37,15 +16,16 @@ int GetFriendListInit() { #ifdef _DEBUG cout << WxFriendList.size() << endl; #endif - return WxFriendList.size(); + return WxFriendList.size() == 0 ? 0 : WxFriendList.size() - 1; } +#ifndef USE_SOCKET /* * 供外部调用的获取好友列表接口2 * return:DWORD,WxFriendList第一个成员地址 */ DWORD GetFriendListRemote() { - if (WxFriendList.size() == 0) + if (WxFriendList.size() == 0 || WxFriendList.size() - 1 == 0) return 0; #ifdef _DEBUG printf("0x%08X\n", (DWORD)&WxFriendList[0]); @@ -62,12 +42,12 @@ void GetFriendListFinish() { WxFriendList.clear(); cout << WxFriendList.size() << endl; } - +#endif /* * 获取好友列表的具体实现 * return:void */ -void __stdcall GetFriendList() { +WxFriendStruct* __stdcall GetFriendList() { #ifdef _DEBUG wcout.imbue(locale("chs")); #endif @@ -114,7 +94,7 @@ void __stdcall GetFriendList() { mov LeftTreeAddr, ecx; popad; } - WxFriendStructW p(wxIdAddr, wxNumberAddr, wxNickNameAddr, wxRemarkAddr); + WxFriendStruct p(wxIdAddr, wxNumberAddr, wxNickNameAddr, wxRemarkAddr); WxFriendList.push_back(p); #ifdef _DEBUG wcout << (wchar_t*)(*(DWORD*)p.wxIdAddr) << endl; @@ -123,4 +103,7 @@ void __stdcall GetFriendList() { break; } } + WxFriendStruct nullp(NULL, NULL, NULL, NULL); + WxFriendList.push_back(nullp); + return WxFriendList.data(); } \ No newline at end of file diff --git a/DWeChatRobot/FriendList.h b/DWeChatRobot/FriendList.h index 51593ee..c068bdf 100644 --- a/DWeChatRobot/FriendList.h +++ b/DWeChatRobot/FriendList.h @@ -1,6 +1,8 @@ #pragma once -void __stdcall GetFriendList(); +WxFriendStruct* __stdcall GetFriendList(); +#ifndef USE_SOCKET extern "C" __declspec(dllexport) DWORD GetFriendListRemote(); extern "C" __declspec(dllexport) int GetFriendListInit(); -extern "C" __declspec(dllexport) void GetFriendListFinish(); \ No newline at end of file +extern "C" __declspec(dllexport) void GetFriendListFinish(); +#endif \ No newline at end of file diff --git a/DWeChatRobot/GetChatRoomMembers.h b/DWeChatRobot/GetChatRoomMembers.h index 341ac29..81a4027 100644 --- a/DWeChatRobot/GetChatRoomMembers.h +++ b/DWeChatRobot/GetChatRoomMembers.h @@ -2,4 +2,6 @@ #include BOOL __stdcall GetChatRoomMembers(wchar_t* chatroomid); -extern "C" __declspec(dllexport) DWORD GetChatRoomMembersRemote(LPVOID lparameter); \ No newline at end of file +#ifndef USE_SOCKET +extern "C" __declspec(dllexport) DWORD GetChatRoomMembersRemote(LPVOID lparameter); +#endif \ No newline at end of file diff --git a/DWeChatRobot/GetChatRoomMemebers.cpp b/DWeChatRobot/GetChatRoomMemebers.cpp index 9f88f4a..7c21fac 100644 --- a/DWeChatRobot/GetChatRoomMemebers.cpp +++ b/DWeChatRobot/GetChatRoomMemebers.cpp @@ -29,6 +29,7 @@ ChatRoomInfoStruct chatroominfo = { 0 }; * lparameter:保存群聊ID的地址 * return:DWORD,调用成功且群成员数量不为0,返回`chatroominfo`首地址,否则返回0 */ +#ifndef USE_SOCKET DWORD GetChatRoomMembersRemote(LPVOID lparameter) { wchar_t* chatroomid = (WCHAR*)lparameter; if (chatroominfo.members != NULL) { @@ -47,6 +48,7 @@ DWORD GetChatRoomMembersRemote(LPVOID lparameter) { } return 0; } +#endif /* * 获取群成员列表的具体实现 diff --git a/DWeChatRobot/GetDbHandles.cpp b/DWeChatRobot/GetDbHandles.cpp index a13121e..6c28227 100644 --- a/DWeChatRobot/GetDbHandles.cpp +++ b/DWeChatRobot/GetDbHandles.cpp @@ -29,17 +29,19 @@ DWORD GetDbHandleByDbName(wchar_t* dbname) { * 供外部调用的获取数据库信息接口 * return:DWORD,`dbs`首个成员地址 */ +#ifndef USE_SOCKET DWORD GetDbHandlesRemote() { if (dbs.size() == 0) GetDbHandles(); return (DWORD)dbs.data() ; } +#endif /* * 获取数据库信息的具体实现 * return:void */ -void GetDbHandles() { +void* GetDbHandles() { dbs.clear(); DWORD WeChatWinBase = GetWeChatWinBase(); DWORD SqlHandleBaseAddr = WeChatWinBase + SqlHandleMicroMsgOffset; @@ -121,4 +123,5 @@ void GetDbHandles() { cout << endl; } #endif + return dbs.data(); } \ No newline at end of file diff --git a/DWeChatRobot/GetDbHandles.h b/DWeChatRobot/GetDbHandles.h index 6698747..577a3b3 100644 --- a/DWeChatRobot/GetDbHandles.h +++ b/DWeChatRobot/GetDbHandles.h @@ -1,41 +1,8 @@ #pragma once #include -#include -/* -* 保存数据库单个表信息的结构体 -* name:表名;l_name:`name`字符数 -* tbl_name:表名;l_tbl_name:`tbl_name`字符数 -* sql:建表语句;l_sql:`sql`字符数 -* rootpage:表编号;l_rootpage:`rootpage`字符数 -*/ -struct TableInfoStruct { - char* name; - DWORD l_name; - char* tbl_name; - DWORD l_tbl_name; - char* sql; - DWORD l_sql; - char* rootpage; - DWORD l_rootpage; -}; - -/* -* 保存数据库信息的结构体 -* handle:数据库句柄 -* dbname:数据库名 -* l_dbname:`dbname`字符数 -* tables:保存库中所有表信息的容器 -* count:库中表的数量 -*/ -struct DbInfoStruct { - DWORD handle; - wchar_t* dbname; - DWORD l_dbname; - vector tables; - DWORD count; -}; - -void GetDbHandles(); +void* GetDbHandles(); +#ifndef USE_SOCKET extern "C" __declspec(dllexport) DWORD GetDbHandlesRemote(); +#endif DWORD GetDbHandleByDbName(wchar_t* dbname); \ No newline at end of file diff --git a/DWeChatRobot/HookImageMessage.cpp b/DWeChatRobot/HookImageMessage.cpp index 71ce3e5..f3709a3 100644 --- a/DWeChatRobot/HookImageMessage.cpp +++ b/DWeChatRobot/HookImageMessage.cpp @@ -84,6 +84,7 @@ void UnHookImageMsg() { ImageMsgHooked = false; } +#ifndef USE_SOCKET BOOL HookImageMsgRemote(LPVOID lpParameter) { savepath = (wstring)(wchar_t*)lpParameter; if (savepath.back() != '\\') { @@ -95,4 +96,5 @@ BOOL HookImageMsgRemote(LPVOID lpParameter) { } HookImageMsg(); return true; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/DWeChatRobot/HookVoiceMessage.cpp b/DWeChatRobot/HookVoiceMessage.cpp index 0f78a95..8c43eb5 100644 --- a/DWeChatRobot/HookVoiceMessage.cpp +++ b/DWeChatRobot/HookVoiceMessage.cpp @@ -70,6 +70,7 @@ void UnHookVoiceMsg() { VoiceMsgHooked = false; } +#ifndef USE_SOCKET BOOL HookVoiceMsgRemote(LPVOID lpParameter) { savepath = (wstring)(wchar_t*)lpParameter; if (savepath.back() != '\\') { @@ -81,4 +82,5 @@ BOOL HookVoiceMsgRemote(LPVOID lpParameter) { } HookVoiceMsg(); return true; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/DWeChatRobot/ReceiveMessage.cpp b/DWeChatRobot/ReceiveMessage.cpp index bc72a02..f6c9e35 100644 --- a/DWeChatRobot/ReceiveMessage.cpp +++ b/DWeChatRobot/ReceiveMessage.cpp @@ -12,31 +12,8 @@ // 发送消息HOOK的CALL偏移 #define SendMessageNextCallOffset 0x101E8170 - 0x0FDE0000 -/* -* 保存单条信息的结构 -* messagetype:消息类型 -* sender:发送者wxid;l_sender:`sender`字符数 -* wxid:如果sender是群聊id,则此成员保存具体发送人wxid,否则与`sender`一致;l_wxid:`wxid`字符数 -* message:消息内容,非文本消息是xml格式;l_message:`message`字符数 -* filepath:图片、文件及其他资源的保存路径;l_filepath:`filepath`字符数 -*/ -struct messageStruct { - DWORD messagetype; - BOOL isSendMessage; - wchar_t* sender; - DWORD l_sender; - wchar_t* wxid; - DWORD l_wxid; - wchar_t* message; - DWORD l_message; - wchar_t* filepath; - DWORD l_filepath; - wchar_t* time; - DWORD l_time; -}; - // 保存多条信息的动态数组 -vector messageVector; +vector messageVector; // 是否开启接收消息HOOK标志 BOOL ReceiveMessageHooked = false; @@ -57,7 +34,8 @@ DWORD SendMessageNextCall = GetWeChatWinBase() + SendMessageNextCallOffset; DWORD SendMessageJmpBackAddress = SendMessageHookAddress + 0x5; // 创建广播消息数组 -static SAFEARRAY* CreateMessageArray(messageStruct* ms) { +#ifndef USE_SOCKET +static SAFEARRAY* CreateMessageArray(ReceiveMsgStruct* ms) { HRESULT hr = S_OK; SAFEARRAY* psaValue; vector MessageInfoKey = { @@ -89,6 +67,7 @@ static SAFEARRAY* CreateMessageArray(messageStruct* ms) { } return psaValue; } +#endif /* * 消息处理函数,根据消息缓冲区组装结构并存入容器 @@ -99,7 +78,7 @@ VOID ReceiveMessage(DWORD messageAddr) { // 此处用于区别是发送的还是接收的消息 BOOL isSendMessage = *(BOOL*)(messageAddr + 0x3C); - messageStruct message = { 0 }; + ReceiveMsgStruct message = { 0 }; message.isSendMessage = isSendMessage; message.time = GetTimeW(); message.l_time = wcslen(message.time); @@ -136,7 +115,7 @@ VOID ReceiveMessage(DWORD messageAddr) { ZeroMemory(message.filepath, (length + 1) * 2); memcpy(message.filepath, (wchar_t*)(*(DWORD*)(messageAddr + 0x1AC)), length * 2); message.l_filepath = length; -#ifdef USE_COM_EVENT +#ifdef USE_COM // 通过连接点,将消息广播给客户端 SAFEARRAY* psaValue = CreateMessageArray(&message); VARIANT vsaValue; @@ -174,7 +153,7 @@ VOID PopHeadMessage() { messageVector[0].filepath = NULL; delete[] messageVector[0].time; messageVector[0].time = NULL; - vector::iterator k = messageVector.begin(); + vector::iterator k = messageVector.begin(); messageVector.erase(k); } diff --git a/DWeChatRobot/ReceiveMessage.h b/DWeChatRobot/ReceiveMessage.h index f9a3aaa..d6a151e 100644 --- a/DWeChatRobot/ReceiveMessage.h +++ b/DWeChatRobot/ReceiveMessage.h @@ -1,15 +1,20 @@ #pragma once #include +#ifndef USE_SOCKET extern "C" __declspec(dllexport) DWORD GetHeadMessage(); extern "C" __declspec(dllexport) VOID PopHeadMessage(); - extern "C" __declspec(dllexport) VOID HookReceiveMessage(); extern "C" __declspec(dllexport) VOID UnHookReceiveMessage(); - -void __stdcall HookVoiceMsg(); extern "C" __declspec(dllexport) void UnHookVoiceMsg(); extern "C" __declspec(dllexport) BOOL HookVoiceMsgRemote(LPVOID lpParameter); - -void __stdcall HookImageMsg(); extern "C" __declspec(dllexport) void UnHookImageMsg(); -extern "C" __declspec(dllexport) BOOL HookImageMsgRemote(LPVOID lpParameter); \ No newline at end of file +extern "C" __declspec(dllexport) BOOL HookImageMsgRemote(LPVOID lpParameter); +#else +VOID HookReceiveMessage(); +VOID UnHookReceiveMessage(); +void UnHookImageMsg(); +void UnHookVoiceMsg(); +#endif + +void __stdcall HookVoiceMsg(); +void __stdcall HookImageMsg(); \ No newline at end of file diff --git a/DWeChatRobot/SearchContact.h b/DWeChatRobot/SearchContact.h index e0f8844..55d57fc 100644 --- a/DWeChatRobot/SearchContact.h +++ b/DWeChatRobot/SearchContact.h @@ -1,10 +1,12 @@ #pragma once #include -BOOL __stdcall GetUserInfoByWxId(wchar_t* wxid); -extern "C" __declspec(dllexport) DWORD GetWxUserInfoRemote(LPVOID lparamter); -extern "C" __declspec(dllexport) VOID DeleteUserInfoCacheRemote(); +wstring __stdcall GetUserInfoByWxId(wchar_t* wxid); wchar_t* __stdcall GetUserNickNameByWxId(wchar_t* wxid); +void* __stdcall SearchContactByNet(wchar_t* keyword); +void UnHookSearchContact(); -void __stdcall SearchContactByNet(wchar_t* keyword); +#ifndef USE_SOCKET +extern "C" __declspec(dllexport) DWORD GetWxUserInfoRemote(LPVOID lparamter); +extern "C" __declspec(dllexport) VOID DeleteUserInfoCacheRemote(); extern "C" __declspec(dllexport) DWORD SearchContactByNetRemote(LPVOID keyword); -void UnHookSearchContact(); \ No newline at end of file +#endif \ No newline at end of file diff --git a/DWeChatRobot/SearchContactByCache.cpp b/DWeChatRobot/SearchContactByCache.cpp index 93d1f80..bf4d257 100644 --- a/DWeChatRobot/SearchContactByCache.cpp +++ b/DWeChatRobot/SearchContactByCache.cpp @@ -19,22 +19,20 @@ * message:wUserInfo.c_str() * length:wUserInfo字符串长度 */ +#ifndef USE_SOCKET struct GetUserInfoStruct { DWORD message; DWORD length; -}; - -// 保存好友信息的字符串 -wstring wUserInfo = L""; -// 外部调用时的具体返回对象 -GetUserInfoStruct ret = { 0 }; +} ret; +#endif /* * 根据缓冲区内容拼接好友信息 * address:缓冲区地址 * return:void */ -VOID WxUserInfo(DWORD address) { +static wstring WxUserInfo(DWORD address) { + wstring wUserInfo = L""; vector InfoType{ address + 0x10, address + 0x24, @@ -77,6 +75,7 @@ VOID WxUserInfo(DWORD address) { wcout.imbue(locale("chs")); wcout << wUserInfo.c_str() << endl; #endif + return wUserInfo; } /* @@ -84,35 +83,40 @@ VOID WxUserInfo(DWORD address) { * lparamter:保存好友wxid的地址 * return:DWORD,`ret`的首地址 */ +#ifndef USE_SOCKET DWORD GetWxUserInfoRemote(LPVOID lparamter) { wchar_t* userwxid = (wchar_t*)lparamter; - if (!GetUserInfoByWxId(userwxid)) { - return 0; - } - ret.message = (DWORD)wUserInfo.c_str(); - ret.length = (DWORD)wUserInfo.length(); + wstring wUserInfo = GetUserInfoByWxId(userwxid); + + ZeroMemory(&ret, sizeof(GetUserInfoStruct)); + wchar_t* message = new wchar_t[wUserInfo.length() + 1]; + memcpy(message, wUserInfo.c_str(), (wUserInfo.length() + 1) * 2); + ret.message = (DWORD)message; + ret.length = wUserInfo.length(); return (DWORD)&ret; } - +#endif /* * 供外部调用的清空好友信息缓存的接口 * return:void */ +#ifndef USE_SOCKET VOID DeleteUserInfoCacheRemote() { if (ret.length) { - ZeroMemory((wchar_t*)ret.message, ret.length * 2 + 2); - ret.length = 0; - wUserInfo = L""; + delete[](wchar_t*)ret.message; + ZeroMemory(&ret, sizeof(GetUserInfoStruct)); } } +#endif /* * 根据wxid获取好友信息的具体实现 * wxid:好友wxid -* return:BOOL,成功返回`1`,失败返回`0` +* return:wstring,成功返回好友信息,失败返回空字符串 */ -BOOL __stdcall GetUserInfoByWxId(wchar_t* wxid) { +wstring __stdcall GetUserInfoByWxId(wchar_t* wxid) { + wstring wUserInfo = L""; DWORD WeChatWinBase = GetWeChatWinBase(); DWORD WxGetUserInfoCall1 = WeChatWinBase + GetUserInfoCall1Offset; DWORD WxGetUserInfoCall2 = WeChatWinBase + GetUserInfoCall2Offset; @@ -142,7 +146,8 @@ BOOL __stdcall GetUserInfoByWxId(wchar_t* wxid) { popad; } if(isSuccess) - WxUserInfo(address); + wUserInfo = WxUserInfo(address); + char deletebuffer[0x410] = { 0 }; __asm { pushad; @@ -154,7 +159,7 @@ BOOL __stdcall GetUserInfoByWxId(wchar_t* wxid) { call DeleteUserInfoCacheCall2; popad; } - return isSuccess; + return wUserInfo; } /* diff --git a/DWeChatRobot/SearchContactByNet.cpp b/DWeChatRobot/SearchContactByNet.cpp index 5f4f18d..88d8e3a 100644 --- a/DWeChatRobot/SearchContactByNet.cpp +++ b/DWeChatRobot/SearchContactByNet.cpp @@ -14,31 +14,7 @@ static char HookSearchContactErrcodeOldAsm[5] = { 0 }; static char HookUserInfoOldAsm[5] = { 0 }; static DWORD WeChatWinBase = GetWeChatWinBase(); -static struct UserInfo { - int errcode; - wchar_t* keyword; - int l_keyword; - wchar_t* v3; - int l_v3; - wchar_t* NickName; - int l_NickName; - wchar_t* Signature; - int l_Signature; - wchar_t* v2; - int l_v2; - wchar_t* Nation; - int l_Nation; - wchar_t* Province; - int l_Province; - wchar_t* City; - int l_City; - wchar_t* BigAvatar; - int l_BigAvatar; - wchar_t* SmallAvatar; - int l_SmallAvatar; - DWORD sex; - BOOL over; -} userinfo; +static UserInfo userinfo; DWORD HookSearchContactErrcodeNextCall = WeChatWinBase + HookSearchContactErrcodeNextCallOffset; DWORD HookSearchContactErrcodeAddr = WeChatWinBase + HookSearchContactErrcodeAddrOffset; @@ -217,7 +193,7 @@ static void DeleteUserInfoCache() { } -void __stdcall SearchContactByNet(wchar_t* keyword) { +void* __stdcall SearchContactByNet(wchar_t* keyword) { HookSearchContact(); DeleteUserInfoCache(); DWORD SearchContactByNetCall1 = GetWeChatWinBase() + SearchContactByNetCall1Offset; @@ -248,9 +224,12 @@ void __stdcall SearchContactByNet(wchar_t* keyword) { wcout << userinfo.v3 << endl; #endif } + return &userinfo; } +#ifndef USE_SOCKET DWORD SearchContactByNetRemote(LPVOID keyword) { SearchContactByNet((wchar_t*)keyword); return (DWORD)&userinfo; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/DWeChatRobot/SelfInfo.cpp b/DWeChatRobot/SelfInfo.cpp index 9ae2a5e..5a07866 100644 --- a/DWeChatRobot/SelfInfo.cpp +++ b/DWeChatRobot/SelfInfo.cpp @@ -1,24 +1,40 @@ #include "pch.h" #include -// 保存个人信息的字符串 -wstring selfinfo = L""; - /* * 外部调用时的返回类型 * message:selfinfo.c_str() * length:selfinfo字符串长度 */ +#ifndef USE_SOCKET struct SelfInfoStruct { DWORD message; DWORD length; } ret; +#endif // !USE_SOCKET + /* * 供外部调用的获取个人信息接口 * return:DWORD,ret的首地址 */ +#ifndef USE_SOCKET DWORD GetSelfInfoRemote() { + ZeroMemory(&ret, sizeof(SelfInfoStruct)); + wstring selfinfo = GetSelfInfo(); + wchar_t* message = new wchar_t[selfinfo.length() + 1]; + memcpy(message,selfinfo.c_str(),(selfinfo.length() + 1) * 2); + ret.message = (DWORD)message; + ret.length = selfinfo.length(); + return (DWORD)&ret; +} +#endif + +/* +* 获取个人信息 +*/ +wstring GetSelfInfo() { + wstring selfinfo = L""; DWORD WeChatWinBase = GetWeChatWinBase(); vector SelfInfoAddr = { WeChatWinBase + 0x236307C, @@ -45,9 +61,7 @@ DWORD GetSelfInfoRemote() { L"\"wxCity\"", L"\"PhoneNumber\"" }; -#ifdef _DEBUG - wcout.imbue(locale("chs")); -#endif + selfinfo = selfinfo + L"{"; for (unsigned int i = 0; i < SelfInfoAddr.size(); i++) { selfinfo = selfinfo + SelfInfoKey[i] + L":"; @@ -91,22 +105,22 @@ DWORD GetSelfInfoRemote() { wtemp = NULL; } selfinfo = selfinfo + L"}"; - ret.message = (DWORD)selfinfo.c_str(); - ret.length = selfinfo.length(); #ifdef _DEBUG + wcout.imbue(locale("chs")); wcout << selfinfo << endl; #endif - return (DWORD)&ret; + return selfinfo; } /* * 删除个人信息缓存 * return:void */ +#ifndef USE_SOCKET VOID DeleteSelfInfoCacheRemote() { if (ret.length) { - ZeroMemory((wchar_t*)ret.message, ret.length*2 + 2); - ret.length = 0; - selfinfo = L""; + delete[] (wchar_t*)ret.message; + ZeroMemory(&ret, sizeof(SelfInfoStruct)); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/DWeChatRobot/SelfInfo.h b/DWeChatRobot/SelfInfo.h index 910ba8e..ce16613 100644 --- a/DWeChatRobot/SelfInfo.h +++ b/DWeChatRobot/SelfInfo.h @@ -2,5 +2,8 @@ #include #include using namespace std; +wstring GetSelfInfo(); +#ifndef USE_SOCKET extern "C" __declspec(dllexport) DWORD GetSelfInfoRemote(); -extern "C" __declspec(dllexport) VOID DeleteSelfInfoCacheRemote(); \ No newline at end of file +extern "C" __declspec(dllexport) VOID DeleteSelfInfoCacheRemote(); +#endif \ No newline at end of file diff --git a/DWeChatRobot/SendAppMsg.cpp b/DWeChatRobot/SendAppMsg.cpp index ae6d587..0628332 100644 --- a/DWeChatRobot/SendAppMsg.cpp +++ b/DWeChatRobot/SendAppMsg.cpp @@ -4,19 +4,12 @@ #define SendAppMsgCall2Offset 0x04AD0980 - 0x04360000 #define SendAppMsgCall3Offset 0x04B1BB30 - 0x04360000 -struct VectorStruct { -#ifdef _DEBUG - DWORD v_head; -#endif - DWORD v_data; - DWORD v_end1; - DWORD v_end2; -}; - +#ifndef USE_SOCKET struct SendAppMsgStruct { wchar_t* wxid; wchar_t* appid; }; +#endif BOOL __stdcall SendAppMsg(wchar_t* wxid,wchar_t* appid) { DWORD WeChatWinBase = GetWeChatWinBase(); @@ -55,8 +48,10 @@ BOOL __stdcall SendAppMsg(wchar_t* wxid,wchar_t* appid) { return isSuccess; } +#ifndef USE_SOCKET BOOL SendAppMsgRemote(LPVOID lpParameter) { SendAppMsgStruct* sams = (SendAppMsgStruct*)lpParameter; BOOL isSuccess = SendAppMsg(sams->wxid, sams->appid); return isSuccess; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/DWeChatRobot/SendAppMsg.h b/DWeChatRobot/SendAppMsg.h index cbf8aea..ed5d9dd 100644 --- a/DWeChatRobot/SendAppMsg.h +++ b/DWeChatRobot/SendAppMsg.h @@ -1,4 +1,6 @@ #pragma once #include BOOL __stdcall SendAppMsg(wchar_t* wxid, wchar_t* appid); -extern "C" __declspec(dllexport) BOOL SendAppMsgRemote(LPVOID lpParameter); \ No newline at end of file +#ifndef USE_SOCKET +extern "C" __declspec(dllexport) BOOL SendAppMsgRemote(LPVOID lpParameter); +#endif \ No newline at end of file diff --git a/DWeChatRobot/SendArticle.cpp b/DWeChatRobot/SendArticle.cpp index db56ee5..7cbe7dd 100644 --- a/DWeChatRobot/SendArticle.cpp +++ b/DWeChatRobot/SendArticle.cpp @@ -23,6 +23,7 @@ * abstract:文章摘要的保存地址 * url:文章链接的保存地址 */ +#ifndef USE_SOCKET struct SendArticleStruct { DWORD wxid; DWORD title; @@ -30,12 +31,14 @@ struct SendArticleStruct { DWORD url; DWORD imgpath; }; +#endif /* * 供外部调用的发送文章消息接口 * lparameter:SendArticleStruct类型结构体指针 * return:void */ +#ifndef USE_SOCKET VOID SendArticleRemote(LPVOID lparameter) { SendArticleStruct* sas = (SendArticleStruct*)lparameter; wchar_t* wxid = (wchar_t*)sas->wxid; @@ -45,6 +48,7 @@ VOID SendArticleRemote(LPVOID lparameter) { wchar_t* imgpath = sas->imgpath ? (wchar_t*)sas->imgpath : NULL; SendArticle(wxid,title,abstract,url, imgpath); } +#endif /* * 获取自己的wxid保存地址 diff --git a/DWeChatRobot/SendArticle.h b/DWeChatRobot/SendArticle.h index 5df065b..3368401 100644 --- a/DWeChatRobot/SendArticle.h +++ b/DWeChatRobot/SendArticle.h @@ -1,4 +1,6 @@ #pragma once #include +#ifndef USE_SOCKET extern "C" __declspec(dllexport) VOID SendArticleRemote(LPVOID lparameter); +#endif BOOL __stdcall SendArticle(wchar_t* wxid, wchar_t* title, wchar_t* abstract, wchar_t* url,wchar_t* imgpath); \ No newline at end of file diff --git a/DWeChatRobot/SendAtText.cpp b/DWeChatRobot/SendAtText.cpp index 59ee477..ecdda62 100644 --- a/DWeChatRobot/SendAtText.cpp +++ b/DWeChatRobot/SendAtText.cpp @@ -12,6 +12,7 @@ * wxmsg:发送的内容保存地址 * length:艾特的人数量,用于指示wxidlist长度 */ +#ifndef USE_SOCKET struct SendAtTextStruct { DWORD chatroomid; @@ -20,6 +21,7 @@ struct SendAtTextStruct DWORD length; BOOL AutoNickName; }; +#endif /* * 内存中使用的参数结构 @@ -40,6 +42,7 @@ struct AtStruct { * lpParameter:SendAtTextStruct类型结构体指针 * return:void */ +#ifndef USE_SOCKET void SendAtTextRemote(LPVOID lpParameter) { SendAtTextStruct* rp = (SendAtTextStruct*)lpParameter; wchar_t* wsChatRoomId = (WCHAR*)rp->chatroomid; @@ -51,6 +54,7 @@ void SendAtTextRemote(LPVOID lpParameter) { else SendAtText(wsChatRoomId, (DWORD*)rp->wxidlist, wsTextMsg, rp->length, rp->AutoNickName); } +#endif /* * 发送艾特消息的具体实现 diff --git a/DWeChatRobot/SendAtText.h b/DWeChatRobot/SendAtText.h index fe544c8..62940c0 100644 --- a/DWeChatRobot/SendAtText.h +++ b/DWeChatRobot/SendAtText.h @@ -2,4 +2,6 @@ #include void __stdcall SendAtText(wchar_t* wsChatRoomId, DWORD wsWxId[], wchar_t* wsTextMsg, int length, BOOL AutoNickName); -extern "C" __declspec(dllexport) void SendAtTextRemote(LPVOID lpParameter); \ No newline at end of file +#ifndef USE_SOCKET +extern "C" __declspec(dllexport) void SendAtTextRemote(LPVOID lpParameter); +#endif \ No newline at end of file diff --git a/DWeChatRobot/SendCard.cpp b/DWeChatRobot/SendCard.cpp index 7c68ed9..784a685 100644 --- a/DWeChatRobot/SendCard.cpp +++ b/DWeChatRobot/SendCard.cpp @@ -11,17 +11,20 @@ * sharedwxid:被推荐人的wxid保存地址 * nickname:名片显示的昵称保存地址 */ +#ifndef USE_SOCKET struct SendCardStruct { DWORD receiver; DWORD sharedwxid; DWORD nickname; }; +#endif /* * 供外部调用的发送名片接口 * lparameter:SendCardStruct类型结构体指针 * return:void */ +#ifndef USE_SOCKET VOID SendCardRemote(LPVOID lparameter) { SendCardStruct* scs = (SendCardStruct*)lparameter; wchar_t* receiver = (WCHAR*)scs->receiver; @@ -29,6 +32,7 @@ VOID SendCardRemote(LPVOID lparameter) { wchar_t* nickname = (WCHAR*)scs->nickname; SendCard(receiver,sharedwxid,nickname); } +#endif /* * 发送名片消息的具体实现 diff --git a/DWeChatRobot/SendCard.h b/DWeChatRobot/SendCard.h index 892ab26..10720e6 100644 --- a/DWeChatRobot/SendCard.h +++ b/DWeChatRobot/SendCard.h @@ -1,4 +1,6 @@ #pragma once #include +#ifndef USE_SOCKET extern "C" __declspec(dllexport) VOID SendCardRemote(LPVOID lparameter); +#endif BOOL __stdcall SendCard(wchar_t* receiver, wchar_t* sharedwxid, wchar_t* nickname); \ No newline at end of file diff --git a/DWeChatRobot/SendFile.cpp b/DWeChatRobot/SendFile.cpp index a486bb6..c816414 100644 --- a/DWeChatRobot/SendFile.cpp +++ b/DWeChatRobot/SendFile.cpp @@ -18,10 +18,12 @@ * wxid:wxid的保存地址 * filepath:文件绝对路径的保存地址 */ +#ifndef USE_SOCKET struct FileParamStruct { DWORD wxid; DWORD filepath; }; +#endif /* * 内存中使用的参数结构 @@ -51,10 +53,12 @@ struct WxFileStruct { * lpParamStruct:FileParamStruct类型结构体指针 * return:void */ +#ifndef USE_SOCKET void SendFileRemote(LPVOID lpParamStruct) { FileParamStruct* params = (FileParamStruct*)lpParamStruct; SendFile((WCHAR*)params->wxid, (WCHAR*)params->filepath); } +#endif /* * 发送文件消息的具体实现 diff --git a/DWeChatRobot/SendFile.h b/DWeChatRobot/SendFile.h index 62ab150..b283e1c 100644 --- a/DWeChatRobot/SendFile.h +++ b/DWeChatRobot/SendFile.h @@ -2,4 +2,6 @@ #include void __stdcall SendFile(wchar_t* receiver, wchar_t* FilePath); -extern "C" __declspec(dllexport) void SendFileRemote(LPVOID lpParamStruct); \ No newline at end of file +#ifndef USE_SOCKET +extern "C" __declspec(dllexport) void SendFileRemote(LPVOID lpParamStruct); +#endif \ No newline at end of file diff --git a/DWeChatRobot/SendImage.cpp b/DWeChatRobot/SendImage.cpp index b7f8920..9ff8495 100644 --- a/DWeChatRobot/SendImage.cpp +++ b/DWeChatRobot/SendImage.cpp @@ -14,20 +14,24 @@ * wxid:保存wxid的地址 * imagepath:保存图片绝对路径的地址 */ +#ifndef USE_SOCKET struct ImageParamStruct { DWORD wxid; DWORD imagepath; }; +#endif /* * 供外部调用的发送图片消息接口 * lpParamStruct:ImageParamStruct类型结构体指针 * return:void */ +#ifndef USE_SOCKET void SendImageRemote(LPVOID lpParamStruct) { ImageParamStruct* params = (ImageParamStruct*)lpParamStruct; SendImage((WCHAR*)params->wxid, (WCHAR*)params->imagepath); } +#endif /* * 发送图片消息的具体实现 diff --git a/DWeChatRobot/SendImage.h b/DWeChatRobot/SendImage.h index 5c39f04..95ade93 100644 --- a/DWeChatRobot/SendImage.h +++ b/DWeChatRobot/SendImage.h @@ -2,4 +2,6 @@ #include void __stdcall SendImage(wchar_t* receiver, wchar_t* ImagePath); -extern "C" __declspec(dllexport) void SendImageRemote(LPVOID lpParamStruct); \ No newline at end of file +#ifndef USE_SOCKET +extern "C" __declspec(dllexport) void SendImageRemote(LPVOID lpParamStruct); +#endif \ No newline at end of file diff --git a/DWeChatRobot/SendText.cpp b/DWeChatRobot/SendText.cpp index 667a4b2..ecf414e 100644 --- a/DWeChatRobot/SendText.cpp +++ b/DWeChatRobot/SendText.cpp @@ -10,23 +10,27 @@ * wxid:wxid保存地址 * wxmsg:发送的内容保存地址 */ +#ifndef USE_SOCKET struct SendTextStruct { DWORD wxid; DWORD wxmsg; }; +#endif /* * 供外部调用的发送文本消息接口 * lpParameter:SendTextStruct类型结构体指针 * return:void */ +#ifndef USE_SOCKET void SendTextRemote(LPVOID lpParameter) { SendTextStruct* rp = (SendTextStruct*)lpParameter; wchar_t* wsWxId = (WCHAR*)rp->wxid; wchar_t* wsTextMsg = (WCHAR*)rp->wxmsg; SendText(wsWxId, wsTextMsg); } +#endif /* * 发送文本消息的具体实现 diff --git a/DWeChatRobot/SendText.h b/DWeChatRobot/SendText.h index 6c16f45..5f58dcc 100644 --- a/DWeChatRobot/SendText.h +++ b/DWeChatRobot/SendText.h @@ -2,4 +2,6 @@ #include void __stdcall SendText(wchar_t* wsWxId, wchar_t* wsTextMsg); -extern "C" __declspec(dllexport) void SendTextRemote(LPVOID lpParameter); \ No newline at end of file +#ifndef USE_SOCKET +extern "C" __declspec(dllexport) void SendTextRemote(LPVOID lpParameter); +#endif \ No newline at end of file diff --git a/DWeChatRobot/VerifyFriendApply.cpp b/DWeChatRobot/VerifyFriendApply.cpp index d4e621f..a40e981 100644 --- a/DWeChatRobot/VerifyFriendApply.cpp +++ b/DWeChatRobot/VerifyFriendApply.cpp @@ -4,10 +4,12 @@ #define VerifyFriendApplyCall2Offset 0x6B6FE8D0 - 0x6B450000 #define VerifyFriendApplyParamOffset 0x6D3320D8 - 0x6B450000 +#ifndef USE_SOCKET struct VerifyFriendApplyStruct { wchar_t* v3_data; wchar_t* v4_data; }; +#endif struct VerifyFriendApplyParamStruct { DWORD handle; @@ -17,11 +19,13 @@ struct VerifyFriendApplyParamStruct { char buffer[0x3C] = { 0 }; }; +#ifndef USE_SOCKET BOOL VerifyFriendApplyRemote(LPVOID lparameter) { VerifyFriendApplyStruct* vfas = (VerifyFriendApplyStruct*)lparameter; BOOL isSuccess = VerifyFriendApply(vfas->v3_data, vfas->v4_data); return isSuccess; } +#endif BOOL __stdcall VerifyFriendApply(wchar_t* v3_data, wchar_t* v4_data) { WxBaseStruct v3(v3_data); diff --git a/DWeChatRobot/VerifyFriendApply.h b/DWeChatRobot/VerifyFriendApply.h index 71881a1..ee3f014 100644 --- a/DWeChatRobot/VerifyFriendApply.h +++ b/DWeChatRobot/VerifyFriendApply.h @@ -2,4 +2,6 @@ #include BOOL __stdcall VerifyFriendApply(wchar_t* v3_data, wchar_t* v4_data); -extern "C" __declspec(dllexport) BOOL VerifyFriendApplyRemote(LPVOID lparameter); \ No newline at end of file +#ifndef USE_SOCKET +extern "C" __declspec(dllexport) BOOL VerifyFriendApplyRemote(LPVOID lparameter); +#endif \ No newline at end of file diff --git a/DWeChatRobot/comclient.cpp b/DWeChatRobot/comclient.cpp index ac10436..a7e599d 100644 --- a/DWeChatRobot/comclient.cpp +++ b/DWeChatRobot/comclient.cpp @@ -1,4 +1,5 @@ #include "pch.h" +#ifdef USE_COM #include #include #include "../CWeChatRobot/WeChatRobotCOM_i.h" @@ -7,7 +8,6 @@ #include #include -using namespace std; CComModule m_commodule; class CSink : @@ -62,4 +62,5 @@ BOOL PostComMessage(VARIANT* msg) { } CoUninitialize(); return true; -} \ No newline at end of file +} +#endif // !USE_COM \ No newline at end of file diff --git a/DWeChatRobot/comclient.h b/DWeChatRobot/comclient.h index a74ff39..0eb1205 100644 --- a/DWeChatRobot/comclient.h +++ b/DWeChatRobot/comclient.h @@ -1,4 +1,6 @@ #pragma once #include -#define USE_COM_EVENT +#define USE_COM +#include +#pragma comment(lib, "comsuppw.lib") BOOL PostComMessage(VARIANT* msg); \ No newline at end of file diff --git a/DWeChatRobot/dllmain.cpp b/DWeChatRobot/dllmain.cpp index faad9b4..4d3660d 100644 --- a/DWeChatRobot/dllmain.cpp +++ b/DWeChatRobot/dllmain.cpp @@ -10,12 +10,14 @@ BOOL APIENTRY DllMain( HMODULE hModule, { case DLL_PROCESS_ATTACH: { -#ifdef _DEBUG if (ProcessIsWeChat()) { +#ifndef USE_SOCKET +#ifdef _DEBUG PrintProcAddr(); HookLogMsgInfo(); - } #endif +#endif + } break; } case DLL_THREAD_ATTACH: diff --git a/DWeChatRobot/pch.cpp b/DWeChatRobot/pch.cpp index ee864e0..fbb6c2a 100644 --- a/DWeChatRobot/pch.cpp +++ b/DWeChatRobot/pch.cpp @@ -188,14 +188,13 @@ void PrintProcAddr() { printf("CheckFriendStatus 0x%08X\n", (DWORD)CheckFriendStatus); printf("GetChatRoomMembers 0x%08X\n", (DWORD)GetChatRoomMembers); printf("ExecuteSql 0x%08X\n", (DWORD)ExecuteSQL); - printf("BackupSQLiteDB 0x%08X\n", (DWORD)BackupSQLiteDBRemote); + printf("BackupSQLiteDB 0x%08X\n", (DWORD)BackupSQLiteDB); printf("VerifyFriendApply 0x%08X\n", (DWORD)VerifyFriendApply); printf("AddFriendByV3 0x%08X\n", (DWORD)AddFriendByV3); printf("AddFriendByWxid 0x%08X\n", (DWORD)AddFriendByWxid); printf("AddBrandContact 0x%08X\n", (DWORD)AddBrandContact); - printf("SelectDataRemote 0x%08X\n", (DWORD)SelectDataRemote); + printf("SelectData 0x%08X\n", (DWORD)SelectData); printf("SearchContactByNet 0x%08X\n", (DWORD)SearchContactByNet); - printf("SearchContactByNetRemote 0x%08X\n", (DWORD)SearchContactByNetRemote); } BOOL ProcessIsWeChat() diff --git a/DWeChatRobot/pch.h b/DWeChatRobot/pch.h index aca87a3..190b19c 100644 --- a/DWeChatRobot/pch.h +++ b/DWeChatRobot/pch.h @@ -9,96 +9,15 @@ // 娣诲姞瑕佸湪姝ゅ棰勭紪璇戠殑鏍囧ご #include "framework.h" -#include #include -#include -#include "SendImage.h" -#include "SendText.h" -#include "SendFile.h" -#include "SendArticle.h" -#include "FriendList.h" -#include "SearchContact.h" -#include "SelfInfo.h" -#include "SendCard.h" -#include "CheckFriendStatus.h" -#include "LogMsgInfo.h" -#include "ReceiveMessage.h" -#include "SendAtText.h" -#include "GetChatRoomMembers.h" -#include "GetDbHandles.h" -#include "DbExecuteSql.h" -#include "DbBackup.h" -#include "VerifyFriendApply.h" -#include "AddFriend.h" -#include "sqlite3.h" -#include "wechatver.h" -#include "DeleteUser.h" -#include "SendAppMsg.h" -#include -#include -#include "wxsocket.h" -#include "comclient.h" +#include +#include +#include "wxdata.h" +#include "wxapi.h" #endif //PCH_H - -#ifdef WX_SOCKET +#ifdef USE_SOCKET #include "wxsocketapi.h" -#endif - -using namespace std; -#pragma comment(lib,"version.lib") -#pragma comment(lib, "comsuppw.lib") -#pragma warning(disable:4731) -// 瀵逛簬瀵煎嚭鍑芥暟锛岄渶瑕佷娇鐢ㄦ瀹忎慨楗 -#define DLLEXPORT extern "C" __declspec(dllexport) - -/* -* 寰俊涓殑鍩虹鏁版嵁缁撴瀯 -* buffer锛歎NICODE瀛楃涓 -* length锛歚buffer`瀛楃鏁 -* maxLength锛歚buffer`鏈澶у瓧绗︽暟 -* fill1锛氬崰浣嶆垚鍛1锛岄粯璁や负0 -* fill2锛氬崰浣嶆垚鍛2锛岄粯璁や负0 -* WxBaseStruct锛氶粯璁ゆ瀯閫犲嚱鏁 -*/ -struct WxBaseStruct -{ - wchar_t* buffer; - DWORD length; - DWORD maxLength; - DWORD fill1; - DWORD fill2; - - WxBaseStruct(wchar_t* pStr) { - buffer = pStr; - length = wcslen(pStr); - maxLength = wcslen(pStr) * 2; - fill1 = 0x0; - fill2 = 0x0; - } -}; - -/* -* 涓嶄娇鐢ㄦ瀯閫犲嚱鏁扮殑寰俊鍩虹鏁版嵁缁撴瀯锛屼娇鐢ㄩ鐜囪緝浣 -*/ -struct WxString -{ - wchar_t* buffer = NULL; - DWORD length = 0; - DWORD maxLength = 0; - DWORD fill1 = 0; - DWORD fill2 = 0; -}; - -BOOL CreateConsole(void); -DWORD GetWeChatWinBase(); -void Wchar_tToString(std::string& szDst, wchar_t* wchar); -string UTF8ToGBK(const std::string& strUTF8); -void HookAnyAddress(DWORD dwHookAddr, LPVOID dwJmpAddress, char* originalRecieveCode); -void UnHookAnyAddress(DWORD dwHookAddr, char* originalRecieveCode); -DLLEXPORT void UnHookAll(); -wstring wreplace(wstring source, wchar_t replaced, wstring replaceto); -void PrintProcAddr(); -wchar_t* GetTimeW(); -BOOL ProcessIsWeChat(); -BOOL FindOrCreateDirectory(const wchar_t* pszPath); \ No newline at end of file +#else +#include "comclient.h" +#endif \ No newline at end of file diff --git a/DWeChatRobot/wechatver.cpp b/DWeChatRobot/wechatver.cpp index 80486e8..8cf659d 100644 --- a/DWeChatRobot/wechatver.cpp +++ b/DWeChatRobot/wechatver.cpp @@ -61,7 +61,13 @@ vector split(const wstring& str, const wstring& delim) { return res; } -BOOL ChangeWeChatVerRemote(wchar_t* verStr) { +#ifndef USE_SOCKET +BOOL ChangeWeChatVerRemote(LPVOID verStr) { + return ChangeWeChatVer((wchar_t*)verStr); +} +#endif + +BOOL ChangeWeChatVer(wchar_t* verStr) { wstring wverStr(verStr); vector v_split = split(wverStr, L"."); BYTE bVer[4] = { 0 }; diff --git a/DWeChatRobot/wechatver.h b/DWeChatRobot/wechatver.h index 5bf62c5..db756d5 100644 --- a/DWeChatRobot/wechatver.h +++ b/DWeChatRobot/wechatver.h @@ -4,4 +4,7 @@ using namespace std; DWORD GetWeChatVerInt(); string GetWeChatVerStr(); -extern "C" __declspec(dllexport) BOOL ChangeWeChatVerRemote(wchar_t* verStr); \ No newline at end of file +BOOL ChangeWeChatVer(wchar_t* verStr); +#ifndef USE_SOCKET +extern "C" __declspec(dllexport) BOOL ChangeWeChatVerRemote(wchar_t* verStr); +#endif // !USE_SOCKET \ No newline at end of file diff --git a/DWeChatRobot/wxapi.h b/DWeChatRobot/wxapi.h new file mode 100644 index 0000000..f7fd93c --- /dev/null +++ b/DWeChatRobot/wxapi.h @@ -0,0 +1,42 @@ +#pragma once +#include "SendImage.h" +#include "SendText.h" +#include "SendFile.h" +#include "SendArticle.h" +#include "FriendList.h" +#include "SearchContact.h" +#include "SelfInfo.h" +#include "SendCard.h" +#include "CheckFriendStatus.h" +#include "LogMsgInfo.h" +#include "ReceiveMessage.h" +#include "SendAtText.h" +#include "GetChatRoomMembers.h" +#include "GetDbHandles.h" +#include "DbExecuteSql.h" +#include "DbBackup.h" +#include "VerifyFriendApply.h" +#include "AddFriend.h" +#include "sqlite3.h" +#include "wechatver.h" +#include "DeleteUser.h" +#include "SendAppMsg.h" + +using namespace std; +#pragma comment(lib,"version.lib") +#pragma warning(disable:4731) +// 对于导出函数,需要使用此宏修饰 +#define DLLEXPORT extern "C" __declspec(dllexport) + +BOOL CreateConsole(void); +DWORD GetWeChatWinBase(); +void Wchar_tToString(std::string& szDst, wchar_t* wchar); +string UTF8ToGBK(const std::string& strUTF8); +void HookAnyAddress(DWORD dwHookAddr, LPVOID dwJmpAddress, char* originalRecieveCode); +void UnHookAnyAddress(DWORD dwHookAddr, char* originalRecieveCode); +DLLEXPORT void UnHookAll(); +wstring wreplace(wstring source, wchar_t replaced, wstring replaceto); +void PrintProcAddr(); +wchar_t* GetTimeW(); +BOOL ProcessIsWeChat(); +BOOL FindOrCreateDirectory(const wchar_t* pszPath); \ No newline at end of file diff --git a/DWeChatRobot/wxdata.h b/DWeChatRobot/wxdata.h new file mode 100644 index 0000000..0f7fb3f --- /dev/null +++ b/DWeChatRobot/wxdata.h @@ -0,0 +1,155 @@ +#pragma once +#include +using namespace std; + +/* +* 微信中的基础数据结构 +* buffer:UNICODE字符串 +* length:`buffer`字符数 +* maxLength:`buffer`最大字符数 +* fill1:占位成员1,默认为0 +* fill2:占位成员2,默认为0 +* WxBaseStruct:默认构造函数 +*/ +struct WxBaseStruct +{ + wchar_t* buffer; + DWORD length; + DWORD maxLength; + DWORD fill1; + DWORD fill2; + + WxBaseStruct(wchar_t* pStr) { + buffer = pStr; + length = wcslen(pStr); + maxLength = wcslen(pStr) * 2; + fill1 = 0x0; + fill2 = 0x0; + } +}; + +/* +* 不使用构造函数的微信基础数据结构,使用频率较低 +*/ +struct WxString +{ + wchar_t* buffer = NULL; + DWORD length = 0; + DWORD maxLength = 0; + DWORD fill1 = 0; + DWORD fill2 = 0; +}; + +/* +* 保存单条信息的结构 +* messagetype:消息类型 +* sender:发送者wxid;l_sender:`sender`字符数 +* wxid:如果sender是群聊id,则此成员保存具体发送人wxid,否则与`sender`一致;l_wxid:`wxid`字符数 +* message:消息内容,非文本消息是xml格式;l_message:`message`字符数 +* filepath:图片、文件及其他资源的保存路径;l_filepath:`filepath`字符数 +*/ +struct ReceiveMsgStruct { + DWORD messagetype; + BOOL isSendMessage; + wchar_t* sender; + DWORD l_sender; + wchar_t* wxid; + DWORD l_wxid; + wchar_t* message; + DWORD l_message; + wchar_t* filepath; + DWORD l_filepath; + wchar_t* time; + DWORD l_time; +}; + +// vector在内存中的表现形式 +struct VectorStruct { +#ifdef _DEBUG + DWORD v_head; +#endif + DWORD v_data; + DWORD v_end1; + DWORD v_end2; +}; + +struct UserInfo { + int errcode; + wchar_t* keyword; + int l_keyword; + wchar_t* v3; + int l_v3; + wchar_t* NickName; + int l_NickName; + wchar_t* Signature; + int l_Signature; + wchar_t* v2; + int l_v2; + wchar_t* Nation; + int l_Nation; + wchar_t* Province; + int l_Province; + wchar_t* City; + int l_City; + wchar_t* BigAvatar; + int l_BigAvatar; + wchar_t* SmallAvatar; + int l_SmallAvatar; + DWORD sex; + BOOL over; +}; + +/* +* 保存数据库单个表信息的结构体 +* name:表名;l_name:`name`字符数 +* tbl_name:表名;l_tbl_name:`tbl_name`字符数 +* sql:建表语句;l_sql:`sql`字符数 +* rootpage:表编号;l_rootpage:`rootpage`字符数 +*/ +struct TableInfoStruct { + char* name; + DWORD l_name; + char* tbl_name; + DWORD l_tbl_name; + char* sql; + DWORD l_sql; + char* rootpage; + DWORD l_rootpage; +}; + +/* +* 保存数据库信息的结构体 +* handle:数据库句柄 +* dbname:数据库名 +* l_dbname:`dbname`字符数 +* tables:保存库中所有表信息的容器 +* count:库中表的数量 +*/ +struct DbInfoStruct { + DWORD handle; + wchar_t* dbname; + DWORD l_dbname; + vector tables; + DWORD count; +}; + +/* +* 保存单个好友信息的结构体 +* wxIdAddr:wxid保存地址 +* wxNumberAddr:微信号保存地址 +* wxNickNameAddr:昵称保存地址 +* wxRemarkAddr:备注保存地址 +* WxFriendStructW:默认构造函数 +*/ +struct WxFriendStruct { + DWORD wxIdAddr; + DWORD wxNumberAddr; + DWORD wxNickNameAddr; + DWORD wxRemarkAddr; + WxFriendStruct(DWORD wxIdAddr, DWORD wxNumberAddr, DWORD wxNickNameAddr, DWORD wxRemarkAddr) { + this->wxIdAddr = wxIdAddr; + this->wxNumberAddr = wxNumberAddr; + this->wxNickNameAddr = wxNickNameAddr; + this->wxRemarkAddr = wxRemarkAddr; + } +}; \ No newline at end of file diff --git a/DWeChatRobot/wxsocket.cpp b/DWeChatRobot/wxsocket.cpp index e3ab83e..23129bf 100644 --- a/DWeChatRobot/wxsocket.cpp +++ b/DWeChatRobot/wxsocket.cpp @@ -1,32 +1,29 @@ #include "pch.h" -#include -using namespace std; -#ifdef WX_SOCKET +#ifdef USE_SOCKET +// mongoose: https://github.com/Automattic/mongoose +#include "mongoose/mongoose.c" #include static struct mg_mgr mgr; static bool httpruning = false; static const char* s_http_addr = "http://0.0.0.0:8000"; // HTTP port static const char* s_root_dir = "."; +static bool allclosed = false; // Event handler for the listening connection. // Simply serve static files from `s_root_dir` static void fn(struct mg_connection* c, int ev, void* ev_data, void* fn_data) { if (ev == MG_EV_HTTP_MSG) { struct mg_http_message* hm = (struct mg_http_message*)ev_data, tmp = { 0 }; - if (mg_http_match_uri(hm, "/api/test")) { + if (mg_http_match_uri(hm, "/api/test/")) { SendText((wchar_t*)L"filehelper", (wchar_t*)L"测试消息"); + mg_http_reply(c, 200, "", "{\"result\": \"OK\"}\n", 0, 0); + } + else if (mg_http_match_uri(hm, "/api/f2/*")) { mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"); mg_http_printf_chunk(c, "ID PROTO TYPE LOCAL REMOTE\n"); mg_http_printf_chunk(c, ""); } - else if (mg_http_match_uri(hm, "/api/f2/*")) { - mg_http_reply(c, 200, "", "{\"result\": \"%.*s\"}\n", (int)hm->uri.len,hm->uri.ptr); - } - else if (mg_http_match_uri(hm, "/api/quit/")) { - mg_http_reply(c, 200, "", "{\"result\": \"OK\"}\n", 0, 0); - httpruning = false; - } else { struct mg_http_serve_opts opts = { 0 }; opts.root_dir = s_root_dir; @@ -36,19 +33,25 @@ static void fn(struct mg_connection* c, int ev, void* ev_data, void* fn_data) { (void)fn_data; } -int HttpStart() { +void HttpStart() { mg_log_set("2"); mg_mgr_init(&mgr); mg_http_listen(&mgr, s_http_addr, fn, NULL); httpruning = true; - while (httpruning) + while(httpruning) mg_mgr_poll(&mgr, 1000); mg_mgr_free(&mgr); - return 0; + allclosed = true; } int HttpClose() { + if (!httpruning) { + return 0; + } httpruning = false; + while (!allclosed) + Sleep(100); + allclosed = false; return 0; } -#endif \ No newline at end of file +#endif // !USE_SOCKET \ No newline at end of file diff --git a/DWeChatRobot/wxsocket.h b/DWeChatRobot/wxsocket.h deleted file mode 100644 index f0a1f0c..0000000 --- a/DWeChatRobot/wxsocket.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#ifdef _DEBUG -// #define WX_SOCKET -#endif \ No newline at end of file diff --git a/DWeChatRobot/wxsocketapi.h b/DWeChatRobot/wxsocketapi.h index b7f1c68..6c14949 100644 --- a/DWeChatRobot/wxsocketapi.h +++ b/DWeChatRobot/wxsocketapi.h @@ -1,9 +1,9 @@ #pragma once -#include "wxsocket.h" -#ifdef WX_SOCKET +#ifdef USE_SOCKET #include -#include "mongoose.h" +// mongoose: https://github.com/Automattic/mongoose +#include "mongoose/mongoose.h" #pragma comment(lib,"ws2_32.lib") -int HttpStart(); -int HttpClose(); +extern "C" __declspec(dllexport) void HttpStart(); +extern "C" __declspec(dllexport) int HttpClose(); #endif \ No newline at end of file diff --git a/Release/CWeChatRobot.exe b/Release/CWeChatRobot.exe index cfed43cc7ea94e7f1184b4138989803baa2f26bc..4f7e8e3d06e632c3fab83677e4e83ad91693fb1e 100644 GIT binary patch delta 4280 zcmeH}eN>az9mk(v0yem$Ckoi8QBeYh7iq$i_h6GK6;y1QO*`ta@)86!3`(O##6m4q z)}n=iTpR&)?U6{=V)4QuM6f*rxy2x@-RajiGsJu1|)lFn;J-(O`vS z-GgqH*d*Dgf9l#us9y44mh99u&mbRf z-&0+OIg>*|td%}22qly#d@|muM-W2 z^A^*3qG{$&rViQdmhj(`>3JDx!ht2UGJ(3oy~`*_6b!qyBfb{HQCfR9-MKb9%tnk=c%BEa)aVg*_Y{)#%BDnO@VAm1fw7dfI}#6|Pyf}}p%iG>~ zfrMAV5zq)Kz$3r`vVj)xcBGwze((ku0%PD~@MnSH_4-CK!vR_6}7YRFn8{~n-;A`k#fC&%+1K=f41)f6DEx-YEU@`c* zjf7e7A@~%Njln*FST|S#c-wLG0TMJvv6B}`=mUjdA^3u&inO)uaz`|-3F~SHCx8z` zz%&>GZ-NUz7CWf4V>k%#5GV#ufmRUV(|{%D%fLDGm9QhQyxl^dw}MU_&JR(e6NjV6 zAOc4#EN?S#@U|dk&p{sr?}KSD1O5q?@d98w2!M8Q0`!AU_=B)-f@1Vn^7xlXIFET` z==1ht_})KOgu{S?w?;U8pez;;!EWz>Y49$%A19Rw3V;{*!BOxU2!>xb(H~Q`eKP*@ zDqc$lioor?B-}2K)}Qw&p{D@%K0K+N-}I@V56cC?3!j%wZKfNETHFJ=@H<<`x_IUL z&59eN5B_NL@h4BYey0D0lw9a2-nlx3wP2tr?}xNQ`<~%7;Yng2)lj;8TpBa=Zpu|Q2RzbGv=o+= z`f;_F?rTBn{&F!WY zYzTpLhP?-8(pbzHVqevfORjrXN|#pR+k>!Dc5n}+Ck393)~H~{y_C!*t0{qv?7=~Y zq6t^`V7@CXaW7(p=4fn$$1bM|HnkUz#lM$)cpagigSVL^Y4?#S=b? zPrpw!9lDoLh(1s7vghl`)i#15|Itdn%tjA-xHTW~2s7V}_TBhL%(o|SZR_2*9iO|W zsd1UrdGJ<4tbmphr}g8`zk`Co zcn#NYAD=jGl5BqaVv@!ip8Ik~{of59P?0s1_blEj+AR$Rmok zZrm=7li0R?TE^C#Bu%1fVbUQLTYr+w_o0hO$*Ezlz{!d#Sn}BBLLQ-Fk(0D-0lHGDeq56(_J;w=V^8*za@AVyNZQoUR9zFxENyD2ZK|xV zudMRdsMy>6l*VV0vWrepZgg;1#hOo%4W&Y-D3#AHtqv=cwiCCR8w0e2onW*ywwVho zZZneeOGXdGZ)Q0g9U#?z+mUyGO5%2;l@g-cvakGKY$)YFH^iS%_=8jQ<%%#3)1w+s zuFK}CaCNx4T?4L=YuGjF8gq@iCS5bGh)Zb1M>4yY zH*^~M3`6XdNm|~fHx?Vc##ZAQW6(HcoG?xsZyOWxb@_(;(){xL*8GnA?)*^xNdDD) zK~#upQ6r{_deI=-M7LNfmWdT&m)I>1h-bv0I3ZpZuZT0^O;Kagn@pwxQ-vvDYBlwl zf~FzUsOhRHVoEXV%?7j0>@}C02h3;M%;(J^^N9J1dB%LxthQ(^g_bf)ou$#zVd=62 zEu)r6%d{n8xn)VS>a8YgxwX;SZtb(4whmcGt+UoUR;4Y?rneQ^d^W!=U~9E?*t%?e zw$rwAwxDguHewsM&Dw6+QtVp0&Tg=m+5Prbd$)bSK5U<`U$L*hX}@jPIrI*jquf#F zXmoTsx*Y?KGmat0gk#ci)1h>#od&1d>2o$Zo1N#J=ba(vuyfQo=A3X&hW|1}OJ)BC Do%CFU delta 4194 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 diff --git a/Release/DWeChatRobot.dll b/Release/DWeChatRobot.dll index b9cab1da76bcc18d7acd27732740b32e2eef22b8..bbb299356b2db4b1081d9e00d4529899fb6bbfbf 100644 GIT binary patch delta 30665 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 Q>V4`u^bbuYpUU?AA8|CF82|tP delta 30762 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%0DdGB*;|A4JgtoQ7JIV0FRV9e~f z55COqV(6E2V~5w~*5YU;ICp_QugShl=bhfnpJj80-*cg<17BqL{-O_93(_4B+W(>z zAW{tr(iiYi4X}$5Sj4K}>-lMD>Dd1BU`ZKH&qB*Yw*J)t_;K3Xf(?JOHWfs&cL;G*cU)+vcn#pfrs7%|sj zM$G1g1ZSR8N_&-}3z&tJ(~xmDh_2nTQxsdagH0&>!R&A?%6}mjJavap7Z69nalTKo z!(h_f{us#W`wK`q4T~NrFr0LET(n?j9~c^q!@wQof!?zia}i&pbzC%mT?DNK+?>Ok z6+R6;L*>2T7)gZD_X$d4MHj#wL&rta%^8{V0uGfSGUuzX+KAQ*fdiJkSSk|QaNw!1 z7pEirLzSYdM|`vMi_X@?@%=310B7vZUh#PiZ1-QYHrxyO_)21Urmp<>ejAec&hs>1 z!8JP1{nf0C9o2nO`zH`ZGB#44{P}D!A9tYfkDG-`rme4?6@H zg*tiYupWBLMb-!=$!*l-r}C>z=%%M`X8j83*-e$4-hid6)uS?E#!1i1JiCQqE zK9=aFV@q^bP9FYpQD7r(m~xG@Co zp}q1zrx{a~;1^28fPN#VZ9z_)nvz4C7_<_(VH{Q>$yd9<+}6R*NPiQDQZbXV53ZHi zhuJ4G&teg=(;z*7x*LbKv{}B<)`26^Q?qbF+Nx)1>sV`=`i;K0spSw29Fn$w?mNSp z`dP&QtVnsVLo>G;TT2Xm^Zi2)$&;9~*SMdr*hm>Uj~V0%tP32(q4>sIb4JUlvDr?b zD-MUciN6&CfiK3a{kS%S8Zqbj0#wxAbX|Nt3&R>>8Wun`28QmJ4zLR7twBtKI&i7N ztu~mApQ`h3fq~ZnJLP#yU(t!%vE(Jdx}rM{^K&?exHvqos<=RYf<@<$BLy1rz>O^| zMScofLR2=Gx?E`j&%P90ro!Al3I*5)_pU?lpfj7;RrpaVl|x&o*j2cK*SJu)1NGrx~p9{2Y3e z%cNF#IV#mKe)BzB5v!T>oo?9UtcNXJfQ~#Knn2tVF<<$_qpWZdu9dj3hQiqyaxEZV z$mOON9fU*9CCGUza;8Ssqi@K+82Ql-A=eT;<1%`AXdXb)F#AC+4P`t{#5g_jY7cGz zW*>~FL}lU+IMoAj#nIycx4znrR1UP~%Xn|6fa1!>ji}k4omBO1syfUAK`Z)e zr0QZb4N9H?tjc(H69bIc&?Xb6tFjY<5T76jX!ZGe{zI|+$HOPb2ve%Cn`z{SrUICjYQ#PWLd4;6z zSE*`VLz%+S;Yh%20%#M{iS-_s8DM;**$uiV=(L}THGA=;XtSs3RE)TS7tblD3*pg$ zJJRXU-!}F4gPP$X1S=oPi)kRMq^-iz`pTW~Q9qzr{P&?(pS^wfA|JIPKkpK_2V}x3 z5WiQ4Bv*L-1o*^e+7|ZCR9hDFdb+h4m?6?w?`-wXq>cDVdN{=Q=t=COTb*=_3qgS^ zW`1xC3x_rUao?S9jJt8iP#oJrS}L5n3&wVvD|Zhm{??XB0JXLdhFaEgH@&bQiWfFn z@$^i66%F-PGDa7^tFBG>JSH`#k>9@|S5QmOw=Y0@steP9m5;agPBH(C_B{v@tc!FA zxo#@-nz`|yI?oroOL(2!+MaP#!xXjjZB?a0y?1J5l!N-b2N@+o@179}Ap1=VrRKD&TG7&7r#LQNW%YRHOME3=6D+wz}JAAvl}^ z+{yRk0;G-NaxsyvHK^3AS}Oo(WX2mAizazk)KWPAp>dQK>C_yAZ5;HDs#2iXn=nH8 zh|LOkM9U!2$Ud2sEyI16g^TU`MckjKrH}V8yQZa&I+{l>T#Oc{H18vhmOhTr+QVWj zecZJ6P`NDgL#1+=uJ~w?Pc1SRdlN^LE&*D112npmOJBwrVVDlfcc6c2Ot=S0k}q@d z^h=U%CY0kQpz}g4bEV_`F>_^jvFo6z&I=gBz+7zHI{Ozv*21aX5HcKn4sR&JHw!|} zOC+w~{V9?}T?A>x=6OH^O_!|Vi@{cxt(G}Y*D5aDLpYH#DP4Ax7N=57X7DJ?LVB#jRYnxrvvQ!sCo66a>)C6D75R(bxR zyY>9Q278h2%Kk9|;T$1*i{|tC_XpVf%Chv7%P){R@=Mh;;iL5?$S5C4*nnp-b(M4I zD%xk*?AL9jyL7tTW#P5%@Y-eJwT|%Ge9tnHwO9Dg`$VXFb`ne6KcTym2XLZG{AqNN z6)S{l!D6<2nQF}t8J6f9d_ ziAK4>?BMq2;+TBU{PS#=^DUuVso16c`yEg}Z}zC)G1sD()^_~PT$|K`gG}yPWrFrI zoEitCM5`cMdHONhg6yXy@}ar!XSN=(if;LtYbTQU7>yi0HOT3nqW z73lwtjT9#Yx(f?OUX$YNZl@F5e2l79Y{o+7D*#Tb?gbaKbX$UXK+gj}(CIrK(EOguY?=m5kA6r(mVq8Hk9 zqP-^i1PBIDQurw03`#&_PSep(j-js~M*m$-F7*yh%D!VvcaNKiURZAJR)aLKXU@-Zsd#1KCD4 zM&l&CUijt#CSDOGae-)~Q3~eigh10ER}TegP!Av1D!99-DFt8yWuT^Tdp6XX{K(OR z9L%{3qb&NeQt#Mhz)k+tNCD{4Tz)6sAitOlyWDdHAxrR0@|*#wW!f!4UWXXxPtmFl zEfke4u=lKeVAFo;g6hITExC_$zdXrviRb&^-5c}09L-l*2qV&1>CRl}){U8+Hi_?! zzX9Uu?A5>G9XJ-g`2XPD9DMdku4*IPfK+NEoVv#S6ErSui{L98xWr5HH~__4T*7tg z+f;qhxS7N<^dj-a4#kzxx-hqv75%AJS(x4@#uC3ANsQ}#$HIMC(4bTG7W+FiXk2#K zGl)8SmXN^E)J`*i7dI+AeANJ|ei>1Q!Idk#*ST~|q?4*AVORbu>@2huvSsscE_@3b zAZE2?xLN0DD*F0Adm&gZXc(Jrv6SS@ zT39X)zZb|cG3V>jS&x+)x-nsQ{wYGc*qjD^5D{FWdLj~PmwDBO4+9>6E+aBWTH{|b z#`TX1h|MoTKv^;w;V_aQzdy-Sp2){aH`%L-4u1keX+b)3Zu8#RRgjCX*<@%X=q}=0 z1z&ACdAOfDWSC*R|ss$}X_;pVfFs5)QQ zyH1HRm(#P{5puq+D>vSiW|MMJox8jyx7XlJz}N-u^Z3)GhIYBVX0C>4P{WeoOKcO3 zjoEyJ6s>t?R_vKVhOG_>beoiNk2tmfHy9}$hJd^@mS@8dP>`k+*jQejQc%b8RdOIcr4lT+uE46$MvFp0dMl4{H)*`jSS7bV|!o=ki^0}!$9TglQqU`e)oq+wbLQC zFua>_E|{rQBELqEqVIpt+0ECcX>Yv4_nEx|Ifon#$%+mRw@`Y<3kKHFgthUZoeudy z#=kJYF^vTsKyv|g7)FyyXsqlphq9T+g!y*_<~-*R3!ZbZaaf>kxeFs6AILC;AqK#7 zr_$VNfdStecpdC+2|hasiyDdGz6rq)k4IH-F@`dbkMU_A_Ic{r+}+edE-YGwaVMA8 zv=}S@kb}fMf(;v7co0+Re~ih(TeyM} z(^*_!Nh5@ztX!j0Ci?aUo8660&jyvImqN~$iGJFr8NfSwA0)8BBCyJIrDB_J#@hHf z8_bOv&}ShRDLgt8>DE8+|-~-z3(Nv|kq4G1g-oqb#(JFEc4+DJ>_~K1rVgSX+vGI}NgFr%6r;H`F~d-ghxGT0IC-g`NNc$e z)8F3%C5$f$&@ypSus8m4PoUQp=$_A)i;cs8MI4YY3@GFP(=b5K502ta#PFK1f}-hYt?Jwsa_#_(=1)69&TS_0dJ-WPy85LF zRXgu8lD?ryHuMgf{v`6LkQ`6v({==YPU_?@;B&>-&)U!Y@o&%CcX~0qHbPm^tlhcO z?Qx^BW!gt?QX5z<9z+THj5M+ohg0`lC)1%5U0dnPaS`~%A0q>4DbiM)CHPp-QEd^K z2E2#9MhwS?!z%F|!(}j>#^MCPD9ntx*)kpnL&RckOgQ*t%ESgeCX$Y)NU?)TL3{dl zQN;#8K@Gj0;`zQ=kcAdSfGca7=GRrr%_r7Sn=KDGqx}kC$W~DpQKg84Sj>E=7N}&nqA_?@=tl~OyyXIZ2Ak`5m?S3j`vh+C3 z++_=}RM|gRTY)>+{@gK>r38QOgc;I8d{pElNgb_Y1#&QO-cBA=MQj;MJ}p|%#W(~( z_*kTpEjr;up<-r7)o&VH7tdg9ik)4GHdkc*8%Kh5m45)UaC~&jtU6QhX%fYhuA0)Z zFKpFPP+e>@TgcKqqBUb_N^g1^FZlYxaDFU(SoR8FTJ)AP?XJ`89vk6ScL@_UzVSc@ z<}vb6FEnrZg3|knpmC4l!i4yP{a4;kI=(2nE{qiT1{aq3$pl)EP87sNC?J~DG6Rk! zSh0<6#X^3!=HXr2j3^v#pu-)%#oRU`seF8!2+AxNRm$*DC=5wjWIi0-HA7R}hGmP$ zeo_Ly5<~k*qvS~rd#CTu3?D>k(r{>49t_KuG`o!-A>p#r+3-8Mw=xF!&=_IhqnGM7 zh|V55gLblEzn;6zatr?^&f4}(*U%J}jYaFto5K6yT{~ag*TFt##{ycGxZ`NtKj90f z#-Z^a5IsAt8H{1$;Q03=eFd`Xdm~23FEL3Z{y?bdNJsVw?&bB(K##;ihiu_Jg-*6~ zD@~WsWANRq$?SB?iH&!x$8Ji)gezye5~tCpg9d*^LLWFSpl4nA0L{{oQ)-o_Cv}O< zB+cReN-2f{IzWx1dHkCm0_)iO z8&p&MX86kQ6fC1$WgUA6aOL;x44qT%y7Cc-EA3}pdjUOi<#)zopvQThmG%ct2u7S{ zyb!>>#tIF)Vc9|BaUAj;A2c4qQp@-OkYeokvk}y*CdC-c>}h+Rj_|WmYpZeIe9*!= zu=j;Jv^1hwSkoo;{_#FA07s5zN3S;%|n*umB#%ytSk|^e0~l_r@^qiEX_bqCrQILXG-Q!?7SwJJ|5RTN1;hu zQyxHKM;^{~e!Tq2N?pG}e}d-7Hv-;;bs_LWi4E~xCga_X?8|fHv_`0`6m~81uu_!L zHgOIV<~R2Y;7rdi%@3WFCbSjf?EeY*l4?l+9{Zt&?AD2iebYBxq$F+sFo-9jK*mQP z4wRU>Oo_|F&g%|95j3`@Bw{=&N^up~p|4wM2Ae&q%9@Re|54v79mXIf?O|0py+i3?Q$M6L=$Go z*4EO)j@HuQ+^pgVlXt80@Hwir9iU#%9KH*k-PyNBGfPHe8@o+V=QO73}DZ2l(q6v?w$(N5NMpg3SKVTO&K;cs7bL#z6)u9R)8lyc%Tn?aKjhwn!v zv^lP~nzCJ#XgW{SAU){6T1;Eq2mDv3$W|nRQ0XZwNP#e9E_(_-Y&9J5IVz{~)_=8u z34422q3af2Z?}1An`6IH)J}4Ni+U4V4&uyNxG#kb;oeZ>b|u!#GKW}EyT9p>AWvf- zvZB}RLk)Lg`S>=kK`lC2To#rOgykLK9wUyPq#*hHzH`(XMeXH0t|Sse2v8HTxq|5V z5UVZtFi4;X0W2&BoOlDD^CVXHbbO_|I6`EZ--qw~1gRyqcKENZlg9Y3E|ErcIk$mr z^|A>bgAq1tyZ`FbQjPy=t+WEwWlg)7fP)U$VlLeYvmq>RQ{vi=hwHDaxQS3dsM)WQ z?PpI+kH7@beYjfM5pW81^5B zkfi)G(Yj<%TSWDvW4LY3ldaCfth5~_R?+K9QxL1z$*`Cb9FOAgG34@ff74-`{8*cO z2v=8|b~Rs?bHLkKIMtk`Hl4(zv@7$Awv|=(rqV+fr-q3gA1w`u@*Ma+fkxi~)627gO1Y93Ndh62=;bazxj5|| zsWaJ|UsvyF+49>|{IBd+#K1WmMu_y2zERYG=tNK<&fQ$K$5V%&oep36SmcC-1>dNms{uHmy%W5r%`_}%KjaX$j6A`_}3^{pj3a$(LCuKkl4GM#$F;n%A12d@2t@QY)?welC6-M1?tnJ`b9fj-c#=EtA(=VZy|#|lx2zxE{o=3gIwa=L7I3|^Gp zkVb`LIpvf)(nrABi*#E}`!SRRw?AQmp^M!xO^uv43OV>vTgbsz<3bL;1m~YiJCj(a z`579w9CN96DGc-V?!Y>WAW!t~{WHQdT-%vkLO8z`7Jcp02p9eRKUo4mq9Ak?#zwGYfJWE3{ym%nGeap?L(t6e?00!*k*j z!!u-~QlB!|0uapCZ&m%oZ!Ef8z@iI!j`$X~&iO2^ z7RPrYYCl?CeZD>r=+7CRZ_f%eSw_)?Ps}r{V#^^SezeB~!NfiF@LIFh&6k3#xB-ys zu>$Owh==yepV2`iTw$92E zXL}X{jP3-5nXoDzAn$zjq0CX7>XKFm}W6aQ((QL;EB~JfI z<2(XIS@F=`@8M8y4p>239HDr+=RomV1J-9D6QI-V_QZjJaB7emsoxxm--V>@IExjE z-v-|xl854V!e^nq;#L0?c-mB>x!R^NW+%Bv`ND63;O30M36suwHt3FO=WZG z3?i$?iVGyg#Bhc|{*-TYh2kjrJ)zCPHjw8O2=ZKs zofVsMG+Om!PcK#N0_TMZcVOti7IC;M{z0Np+lf+!r7l9HG}S+sq6NJkf}DzT`zG+h zTOB?fiIP6A)Nx=Y7we$yXOOECCw-qa;TBCj7Nf$c64mk;w%f4LD~)5K*T5ba3142> zS=N`v64=r013}Qb5B(nJA+-m=x}{6;`wIYqH6K)V+LO)j%ZAR2+Ytv@Al=6bbB#D` zm6xIxrx|O6`wXe52VsvvHoq-tDsl_Gj2n%YVYxeX%>fzi+5a zs~^p|Y^#2iR;Tt|M*+-j!nc@uB%DuShX%y|7(<+%iL-#%o$u5h(K94!RcM92G%XWh zoZiA2nx$wh*p8Tg$k|6BvI2ojEh!v=*e!uS!7`}^`!noXzT9<QiaQ+B(a=TvxzKbX@P;*^q zFZw37oaV%X<5s!i)m*$b(LRsW?ZgqP1$&Yp__cFd(aKiLE}UlClC)-a;1Jt?!tPi~ zjdyQgUAnOTE_`VjBTIOf0lQ8(*n>++n{t2_-{$UM9i6NO3y3_yOjwu$)e1O_3Sxoe zAaA!xAP%@hKQVVyc5n}g)C*C*5v%bDQ-2f2+HrIss~Vk_-plY_x-`Pyz+B=9CckDm zQA zm%-y1WfFqXUsXxX2ZR@m?Pl~3tu`PT$9G{Ed#v!hV zZ54kE%fHvoQF7Ycx=C?(6SdDFAV;^c2>Lx5@bfIMwI9)T&GOFZ=)5YLaM>I5&vjjSsl+E2A!@6#!3_m^-mV33kIpH`4slA0lIzjJzPOrt2Mf6tFei43i09QKZ%q2=UCT0gO zo&`qUUSR`1X%LQ+;#q~Y?*Tk$8^f#}q!O{(c!7=;Y)3!`|Cr{1QSjy%IQYW|7)xUE zy%=96<9k)WvJ-IZ(??`#FJyEn4l*Lbi>xp?;sar$T&SaV45OB2>!5s2L|-~xa55B! zvplCZkXFNg`rQWY+t}2BK}%{M3mGwPeVI|vi7=9~AWR^QcLhFZAJy?hM(xx1(Km}e z^kP(x*X{=2hRgal&<+EXlI$0Ri`Nhdtbr-{V5ku2PY)zpNYruNF``Vx=GP$jftmr> zVDzbggKE?H67gs3^Cy)=Wvxkh0!s}_xdpd=(2Te=wCT!fsiqF65ofPjUGpdo?=WZY z?1GxrGQPtCG1arG73ZjuuW~Ib}Ythd0QwAOhi*ths20@xUcSS;+ zAWfWGPp{Ou?gS&Iasc9$2%u5G!u{MrP#!pDP`C#lP~vZF>Ua~EC`H%jI4`ZAfsI{G zF)tQnqByJ@phSGsQ^T z2~gfyhiC2P7kBWN`VxP=BJo#CJ%9a=I{x}s4_+^SzvX4TnA4=RY=uW9&o+2Myj&VL zu>|eKO@b{vb|+Di2TG6w#DttXaZ4+D8V?&n;nW2f@4fgnx$u>9ICcSH(`#_sISAVq z_zgy~9_U!8ZazRK<0OD=Mx`P4!ctgMfhh~XHz78;z!cE)VvAs{4$npk0f)k^SZ}nd zaGAXje?B360FwM`w^E~F!xlmuQEpVabD)}Zj6f_Wn>GBP_6dXs-#u3n^gdYTS@_DiiiG12FgTn~)38ze9$6JPA$Yw+`QjZRA-1J;;CSFb6sHg9|Bv znoC%`xfG}w6j05ns4(tOW;-u|1L4%g2!h&hYKHEiZ{6TWWO$+h6$_xw{%lmH<6x(5 za+H<7yYOSjul9lDFn-a{)N)k5N85^`apCNkoVe!+MD~pVbae9A0zv5LwI+4LtVU(7 z9A6GA8=lHej~gt-@7$mi-LHKgEWt$Ksm(xyqYUPBtkh_;K8u9n5bA92rCD7`*}irR z(Z8aH{qu%f%lVIWj>goEPw_B`?K0u+;zbBLr43SAdi-~3!&90;O?Zl*KiBi;I{u{j zad?V}KW+S(&Yv0lIh8-N_;VJ2=J01Oe_Hr+B7ZvY#HuWbPnRmwt z_^~K>-hfA5EdCo#Zs5m31|HeDNqXcp6U19iZ2ul?|AU>c#i3oL`(HCdJOTU%9cYEM zj}UYYC9z@BE{|ykOA%_{!e5wb9E^!DWR?yppk?s1$fFQ8UHND~e!&nM;b$oJN_BdQ zQTKghJozM|!c*!wH|qFP!gF|0ge7l7dt&!yElb@2UsmroDv)Tr8i2;weA%n@~KJp!*0t z`6@^JmMT&8>g$Mrkzd4;cf*IvvmXt7&F?>E>c9UOErl}bxOc^Tgo0q5;VEfoLg2^2 zWWeYIx*u?s`ZhwSb1DgMau9*`AErP012&sdMe1xk-f`6wt2SAT_z1&)SNXk=e_nY) zL|H=dRFv+ca>#dc<%zyjH@aEis@eAqmYfT(noi5 zq0;=YaQw+|Wqko>MtI48=;^)-e-B{Q2>%TJ-Ec?Y2H-4!WxzS$7Q)rT(ccQhy#%)e zZXuitE*EYl9Q}>MJ0s$s^Smx!m&f6ae>OM=+zPmQI6vGLxLt5TxE{D(IAJW(!ezlZ z;M{QaaDKRLa6z~pxB)mTaNFPZfhenl-k% zHLIT%cpjgx>RH?BnzgpNn$=HB9!guf`dh2ltX*xZS+}yLUPnjZ8~$ire&A>LR$tA0 zPnA@@YW4K$x;mto0->0Wcm6}m=4WOuo4@86J;kCmPpy%b<&O+J0~*$>X{cEi^-NzW z2+usdyvFBS4$Dl#qZ zGY@UFsOH;pO@jm;SILrRjc?U+dYo&G@2OSQ)ir23o-c~y(R-hW8@-@^*b7iS^S`NhlEUav3(9^(ka}qCF zi|6-NHC8pO^sTCwZcZXRy{cAN^-R^%H8aSE{tTJa!{o!7M13^ut*-$W491Agd$t zJ^kFOdV;T7xh7KQb<^Od<`=vT`g>&hDD0UvjS(8ZEw5VnEos#=HNrFX*+P|Ey=u*j zXE>jpsh<@|Lq7B=4#gP4>!ye5t7~tdhr$h!hL=F>$g-s>-!!6sZB=8W9P%Mt^ORl( z-iCUJsx>k%g|nZokCY7`a-ffUB&mLR1BvkR+EsPvc?(MyEU-N}rJ(|Nr!-8b;&?x( zrM`ro{b=p9g=<#VOe?CAR+5s6$#!%=WXI?(x1!N^D#d@f7sd|+UwE9TzOlh!5K6y1HQ`ae^ zKO3YfDPu~*ebm<}FX_Q2^B-Nr`Hb2SY>NI8Y_?p<_i(OM{cvuT&Eu=7oqIPCIi=z5 zhlz;X8C4JCyV8i2s%@*Qo~fCO0uXaEtgbo+oB@2JgzvbwM}I zu&d&n1$IE0!Bv=b#@*x3sG~C~?s31W*Bu(jcxKL-v*+yDc}ewqb?erxs#~{i)xGz1 z!gWy%jqRa4DOPY*1zDj2C>SGE$2lSMV5o`m3J*Om#2swXsO*$ur03&QR2bZv3WLf? zB$ejMDPv<`3vb|NV#+-3!2#K6(<(Sj5thG`4A(_t@o;%Iy*Rc66k-vsd=jR4MJyRk ztzhj^N$^C2nJ9>rmt{g$88;0Qfse8&nUtGL(Z-EjrBpJW!VYS2`PnYdi%kcBP|V$Q z@1xT&!`%j__ceyg%d#D16$b5f0$9~(r+hIlh)XIUIaax_x=N_1_CR}w%7^M(1-E)N zx0tWw#7a(B!pNYD7MEBoK%6jL^if=5oM}Fl3_)O*p5S@e71JNv_J`7}T<&5D)|^y7x32xVmKhw~NNh9r=>)0D zh-KrB-IxqJy<957lppj412Wx`$@ZZ<8?A(HSw(wL6^zF^lRA#25u6;lf?=v*tJ1N~ zXjbP0Ct+}O`>%=w6R~)o&fyH1%5()o4g?0HWz@{-C~LbT74AcCgmaq*#LNae;toeu zM6L;|gf9Wut;y73^o%Gy!N+ho?PN0Gi+l9vdOU1j$$`ykmp(gmVj#G% z#gOiFERanFx`NrLn1e9^;;L-yobJX}a2^nF=*FS^lF`jMYslSetIx=Jev8eW3#y@% zoL&z*{p6nWM4o)wBBOynTYRO)S;X9SLBZm{as0 z#|E2z!p-r4q=XA>)?YPnE=J!Pd~x0UVW%vG8u>a+%I8TKbnFS!rBkTVT1)jsU$so(lY}C zfLM39O9zPcF_wWzh3C0*=g=;ZnL!-e!t~@)$-!VtqND6Af$=0d(}76ZaY$`E4)IMU z9k%Od&Z1jgt$NsxE_rDiw5{su#n4EC?o(yn{m@lhODIY#1+DnV! zIM44D=~y<;{2;SA-4Z%BH_t^Fs|(mn%PuQHz!>wSm=yr zp~)c*N66d{X=`iblCU40BvpoCg6+}klVnBJf*ql-!|W-(m;O-^*el5hsiGgalEEZd zk;yO_p$B^Ulvtk4(mT!5f)&V67=322>T2G@esq=Rc~TwhidEzMoyEblDRFG$hD2&9 zPzfwU5+@FcBE?A;KG{@}RV7$h*zQVnu4Hag$r`F87>$TnJr&P`dLX~Iowsmt7IN1# z+p`+$xt7+s?Q=P{Z(&7oT=U$z+Gh6TezeY*Gq-&P8rpV0y`J^c{=p-ayBF24EGf<1 zNxz$S@4H|65xf+Hz#m4gLE7*T(iRHA_k?q0WAI#rbR1>)&y4KKm%;Z&UP9$}QHKA_ zcvjh^Zg%i<|KQV~|8Nn!ta130;PWHdd(QDoQQ%+T>H__t$kgO~zC)G$sj#Eye>;3$ zd3@UCF!J#njF#ui5EWz2?xFOKst_8dQRWr7bQCZXO(gvln$-4 z9rrxT3h5Eh7>X8c`{Q$HQ5qEg8G6rMg|r$_c5a_&n>FY3lh&uW_udL0Fs0K!D4#j1 zgtWHRw~d{&Cw1?ehh}XrJ^k!EM~jbAT0{HrTAjEPgxAj1jMujnxb!?-;f@?tykSRZ zx;mF;)wMU%kuPDW)n~(+DXbr`b+~(6ym=HhV)I#b7f~2q z3M!!2$mrp1p+XqLyX-7j3&Sfq8^-X)ods)Wc*SSK7#;^02fldHbgY=u9}-eIET1n; z)4pM?y8U1{rI}tAm0*prd3NiT_N3z31Z5!AJC&68F8<1uE5jXhKYi-qJe_Q)w6T`; z2{GIpZ3JUJd@kzbn6gI!0FFFuo} z+dBCGu#X`;o(?!M>2)|)C!I-$N_l~TmIAgFcaIBW{iN`7FT9w;^vUtuo#qEtk;{IL zL~--wc)6V6(S z2A;4xsaU<0tvw*1^HT}CL~&8I9~f=AqEyeU_pik94+eTnU&C|HW<^?o!*d2 zEyID6)}nHgzh3=&JZ-`}7QjZ(_!3};3t*Q6hQA?3b`-##2Mlp_vKlg%zi!-vGY0fW zLjmjoz={C#6~G1n!y5`@djaeuVE94`8CL)s{$s@G&<0lkD+TObz=pd18Z-Rgj~NcX zZ~;8$h;yaeQ*&_kj7^8fn5-Sy7I&O3GV#I%^bFsUPK99F&T$ec>WsZ|_$((|*PW)$ z*<2C%-35cS+f#Xxq=#a{QP3TCX2PbTeg$aZTZYYqbulxR&SWWc0i<>0{8&2M9gKrq z7A6&RD#LM?Lhl(W4Z&nMPH9XyzYmRJ@-Bt8^}(J?v?F>@o1ygS6Y-6N1=<|UWOG5K z28u~b2VJ8X^y6;U>NRlDxE&jP0kGQP@~VTY9=&Rs(R$5{X0PZ51n(N|4=i*&gl=H3 zCX)@<)Ld7)uw{CE%_1_VZGK&g;NxBF1#My=Uvm-(1b`bDj6%XN>H=p=&Vz?xKBQB9 zWHya(hN5Zofj+Uv29j_R%(|9Hj#MDZ7?k#bU;=(4XqiA=Z*O}PzU3KbLY|Xz?NBFl z02WUwkZXt8j`&VdUF*DS+8gK080@`4fX7Tp_$tzvM}+DE$rP)bOt~&zx;r!Dn2aY0 z7O*Ac8-#kd5m+L3(S9dGi7uR-0xPKRUdFC>w+qGKI{=MP`xX0Lgqi7(6iP1`CbyFa zGbRaHPa+w|Sw_A^B6y)QPHJFrQkOO%emo(9gs1T&kXVM;0U_T6U#I~O{Y!$`RE&_# zq^lcImSCFH5?Iqw8ls^?p%GrxgGnEWb#|wnKr)Ev=8K$U zPb{5EQpYUbFE|SW(VX5`Ho!bXgxCZob0;;*(}7$`-hYZe?u(goLU7IJi`+^R(U){K zfN%#0fs265w<*S0%w+d7cszU&+DlSwBRjx3e zQ;xt24Yqv+23&?+g~jK$K*R4}g#peYrkgE9Ij0wx2`9tWZXpucGjd+imFn=I1Y>n# z)PyXjtNM=?ZyMPS*2I!vVqQ&=Z(Y!s$z@XMnTUsDu3KPs(@DG;W%W)+cW0-Q&co)8 zxVGC#_aO+52m#{YAw(3wEi^u{Km%cYK}?~5NaTXXK|yJ2#+)}$`K_lbm95^H?1`@R zS@g*j*r7JV|Kl)vHrg}(pX%w0oAhi%Q_TdNyNYoxn}~Nskai#qAe}@a9Nq;%szDlR z=%a=L0>^_jVo}UriznD5G`?j+N(KrXTM;aL_0jgxah! z!NZrq$LGeXt+ILTGpp1x4x3Ce9K`!Tj#bv@WXk;ZC8Nz?CgUVJ;(Z(lBr{eSVv~9X z9?V2AQVcEwb*oWsAwnj-+=V>8xUJw7D1F#aqSoFjA zQT$kb5?{s(d@VnVZ{~yia(*p;4}TxOo!`Un<6q!k;g9gY;NRlk=Z6WSgfYS-VVWQa zhEOXs3hlxT!g67)uwJ-Fcu?3S>=9lNUKWlBuL-Aw4~0Jn!^E-TcyW?gCRU2IVv~5S zxL6E|F>$%LN?a>$6z>u57atUNiF?Es#23XQ;wkZM@k8+s;#lui?}Of5-sikO^&a!S z?mg`t?(_RveAoGI@@?|n?|aI3$am8BrSD2(zVIZR%cizj{PHp}wVlsa~i}&}M7JdWC+w z{bd53&d{-yl6JWRPz8KYdTj8m>wN|mV! zugHq2OjjC|`O5W5ScxierAx^wy~=8(UsQRiZO$%#Bv|nkTYfXAU z&*I2 zUTJTzx7gH)zX{83E&mArEPsgCAu;(=o?4_}-ILdAWSAd_aCv zF2)GElM!idYQhi1}tR7R}Q%7pw*B;Y8)3)k$MzhgleBXH0_{=CV zQ)aPs&?>dJ**~-o*e~0MF;ge))ArZ>MgDUC%YJmE2JbZDwg__goVeF_L>eZ~ltc1u z@+0zo`5pNqdAM?ga<{Tec~&{0{8lMdSE`SzZ>yuUBCSq)Nt>tl=?C@k#;=WHbC#+5 zxB36ge~Qv=fiE4m8GHyUX1q`)R0}?#MhFODp1zTfI;9^;uSj1=6Cnjp%LnE4%IC`0)v0Q=+NG`rAAYPpuf72Z zF4C^jEcB{XTdb|n)@XNXTeQcuz1jioeT~y+=}Yyk`b6+2Xxw4!Ht=_Vj7v??Y%rtd za?I*O=Chd9Bbd{PmT5Iwi!rCmtvU8G%-lA6pZ#C{PwBXpGM16c`C@(-|Bw6te^9sx zl3eU<^)B+>>z(48?wjX($hQsBDk#5HQ`#bZjeZLxY^o(%WBdrEkcH4WpYtW)Nv9AO z?gKZT5Do~3g<|mo@vyha_Z{C(tnH8#m$K4k=|1T(X^-@R^e@s0>7?|5^odj?PmpKJ zF}Yv9RsOcTReoMRhPD5WT&gTl5|H>il?Rla%5G%<((-fVHRa!xQ_9ES*%-A*y&5_| zRio-H>UQvLpZXK^XX>l!N%cc@gjTFoYxP=-wgZdoHfO_3!Z_TvkSnc3shZO@a z`>eIroz@oXyVir&qt;$%kz>}cu~sg(IjodQTeMZ%wrAMQcALG(4%$&WWv{Srve(<2 z?fdNS*}LpLOo}W03;mA&HvdNdPXELHe{koepO7ywJ%so27T?52_#65E;6LG?f(HJY zI8$ta)*;@Dy<@%2-ud2uH|kyEz0JGV`@Hu>=+-y9#5c-!rH}W0;VYJ=NPg*BDJeZ6 z?Ujy5uSxGnm&nEPWLcCO>p^H{R6Wyk4QD&;mYOC6z#??M`oq9n1SM@lg_CxiwI#u&&w$=#AU8*ItUhM_# z744XIO8ZFrZ>?09^%{M)-l{Lr*XdjI9r`2sllpTyF-99j24_q$s6vTj=viSk*48>< zgK&qiN%)Si6_T|>*ol?)7$oc|;Td7SFaSw=3G42#a8x)hye^y+-V**(cvtv9_*nQ< z_(C8eCzguk*r|M?iZxjy){70|_2N=7EbbQvM6$#6_1=LUXsho7-$hch)FLgF!jRT= z(gtaVv{Tv*i5-v*OGl;Skk^l;Po**7A19Z}rd%Vp%V9YxzpkCs@Y1kesn_cbdW*gg zt23;}^?rSWzFps`Kcf%m2lSWp!}@WZ`j^Wwz9N1cRvpKeVlSyg@Y2Vte4Ni>kA8+f K$^+rgy#5ER-#!@t literal 0 HcmV?d00001 diff --git a/Release/socket/wxDriver.dll b/Release/socket/wxDriver.dll new file mode 100644 index 0000000000000000000000000000000000000000..95af4021665a5377c803b21d5b0ab3107be15301 GIT binary patch literal 15360 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 +#include +#include "driverdata.h" +using namespace std; +#pragma warning(disable:4311;disable:4302;disable:4312) +#define DLLEXPORT extern "C" __declspec(dllexport) + +#ifdef _WIN64 + PVOID GetSystem32ProcAddr(PCWSTR ObjectName, PCSTR procName); +#endif +BOOL InjectDll(DWORD dwId, const wchar_t* szPath); +BOOL RemoveDll(DWORD dwId, PCWSTR dllname); + +BOOL CreateConsole(); +BOOL isFileExists_stat(wstring name); +DWORD GetWeChatPid(); + +extern HANDLE GlobalProcess; +extern PVOID pRemoteGetProc; + +DLLEXPORT BOOL StartRobotService(); +DLLEXPORT BOOL StopRobotService(); \ No newline at end of file diff --git a/wxDriver/driverdata.h b/wxDriver/driverdata.h new file mode 100644 index 0000000..c653b83 --- /dev/null +++ b/wxDriver/driverdata.h @@ -0,0 +1,2 @@ +#pragma once +#define DLLNAME L"SWeChatRobot.dll" \ No newline at end of file diff --git a/wxDriver/framework.h b/wxDriver/framework.h new file mode 100644 index 0000000..002956a --- /dev/null +++ b/wxDriver/framework.h @@ -0,0 +1,6 @@ +锘#pragma once +#ifndef _WIN64 +#define WIN32_LEAN_AND_MEAN // 浠 Windows 澶存枃浠朵腑鎺掗櫎鏋佸皯浣跨敤鐨勫唴瀹 +#endif +// Windows 澶存枃浠 +#include diff --git a/wxDriver/inject.cpp b/wxDriver/inject.cpp new file mode 100644 index 0000000..ca32e3c --- /dev/null +++ b/wxDriver/inject.cpp @@ -0,0 +1,112 @@ +#include "pch.h" +#include "driver.h" + +BOOL InjectDll(DWORD dwId, const wchar_t* szPath) +{ + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwId); + if (!hProcess) + return false; + + LPVOID pRemoteAddress = VirtualAllocEx(hProcess, NULL, 1, MEM_COMMIT, PAGE_READWRITE); + SIZE_T dwWriteSize = 0; + if (pRemoteAddress) + { + WriteProcessMemory(hProcess, pRemoteAddress, szPath, wcslen(szPath) * 2 + 2, &dwWriteSize); + } + else { + CloseHandle(hProcess); + return false; + } +#ifdef _WIN64 + PVOID pFunc = GetSystem32ProcAddr(L"\\KnownDlls32\\kernel32.dll","LoadLibraryW"); + if (pFunc == 0) { + VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE); + CloseHandle(hProcess); + return false; + } +#else + PVOID pFunc = LoadLibraryW; +#endif + HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, pRemoteAddress, NULL, NULL); + if (hThread) { + WaitForSingleObject(hThread, INFINITE); + CloseHandle(hThread); + } + else { + VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE); + CloseHandle(hProcess); + return false; + } + VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE); + CloseHandle(hProcess); + return true; +} + +BOOL RemoveDll(DWORD dwId,PCWSTR dllname) { + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId); + if (!hProcess) + return false; + LPVOID pRemoteAddress = VirtualAllocEx(hProcess, NULL, 1, MEM_COMMIT, PAGE_READWRITE); + SIZE_T dwWriteSize = 0; + HANDLE hThread = NULL; + DWORD dwHandle, dwID; + PVOID pFunc = NULL; + if (pRemoteAddress) + WriteProcessMemory(hProcess, pRemoteAddress, dllname, wcslen(dllname) * 2 + 2, &dwWriteSize); + else { + return false; + } +#ifdef _WIN64 + pFunc = GetSystem32ProcAddr(L"\\KnownDlls32\\kernel32.dll", "GetModuleHandleW"); +#else + pFunc = GetModuleHandleW; +#endif + hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, pRemoteAddress, 0, &dwID); + if (hThread) { + WaitForSingleObject(hThread, INFINITE); + GetExitCodeThread(hThread, &dwHandle); + CloseHandle(hThread); + } + else { + VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE); + CloseHandle(hProcess); + return false; + } + if (!dwHandle) { + VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE); + CloseHandle(hProcess); + return true; + } +#ifdef _WIN64 + pFunc = GetSystem32ProcAddr(L"\\KnownDlls32\\kernel32.dll", "FreeConsole"); +#else + pFunc = FreeConsole; +#endif + hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, NULL, 0, &dwID); + if (hThread) { + WaitForSingleObject(hThread, INFINITE); + CloseHandle(hThread); + } + else { + VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE); + CloseHandle(hProcess); + return false; + } +#ifdef _WIN64 + pFunc = GetSystem32ProcAddr(L"\\KnownDlls32\\kernel32.dll", "FreeLibrary"); +#else + pFunc = FreeLibrary; +#endif + hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, (LPVOID)(unsigned long long)dwHandle, 0, &dwID); + if (hThread) { + WaitForSingleObject(hThread, INFINITE); + CloseHandle(hThread); + } + else { + VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE); + CloseHandle(hProcess); + return false; + } + VirtualFreeEx(hProcess, pRemoteAddress, 0, MEM_RELEASE); + return true; +} \ No newline at end of file diff --git a/wxDriver/ntapi.cpp b/wxDriver/ntapi.cpp new file mode 100644 index 0000000..2ddd815 --- /dev/null +++ b/wxDriver/ntapi.cpp @@ -0,0 +1,90 @@ +#include "pch.h" +#ifdef _WIN64 +#include "driver.h" +#include "ntapi.h" +#pragma comment(lib,"ntdll.lib") + +HMODULE hNtdll = GetModuleHandle(L"ntdll.dll"); +pZwOpenSection ZwOpenSection = (pZwOpenSection)GetProcAddress(hNtdll, "ZwOpenSection"); +pZwQuerySection ZwQuerySection = (pZwQuerySection)GetProcAddress(hNtdll, "ZwQuerySection"); +pZwMapViewOfSection ZwMapViewOfSection = (pZwMapViewOfSection)GetProcAddress(hNtdll, "ZwMapViewOfSection"); +pZwUnmapViewOfSection ZwUnmapViewOfSection = (pZwUnmapViewOfSection)GetProcAddress(hNtdll, "ZwUnmapViewOfSection"); +pNtClose NtClose = (pNtClose)GetProcAddress(hNtdll, "NtClose"); +pRtlImageNtHeader RtlImageNtHeader = (pRtlImageNtHeader)GetProcAddress(hNtdll, "RtlImageNtHeader"); +pRtlImageDirectoryEntryToData RtlImageDirectoryEntryToData = (pRtlImageDirectoryEntryToData)GetProcAddress(hNtdll, "RtlImageDirectoryEntryToData"); + +FORCEINLINE VOID RtlInitUnicodeString( + _Out_ PUNICODE_STRING DestinationString, + _In_opt_ PCWSTR SourceString +) +{ + if (SourceString) + DestinationString->MaximumLength = (DestinationString->Length = (USHORT)(wcslen(SourceString) * sizeof(WCHAR))) + sizeof(UNICODE_NULL); + else + DestinationString->MaximumLength = DestinationString->Length = 0; + + DestinationString->Buffer = (PWCH)SourceString; +} + +static PVOID getRVA(PVOID Base, ULONG_PTR BaseAddress, PCSTR Name) +{ + if (PIMAGE_NT_HEADERS32 pinth = (PIMAGE_NT_HEADERS32)RtlImageNtHeader(Base)) + { + BaseAddress -= pinth->OptionalHeader.AddressOfEntryPoint; + DWORD Size, exportRVA; + if (PIMAGE_EXPORT_DIRECTORY pied = (PIMAGE_EXPORT_DIRECTORY) + RtlImageDirectoryEntryToData(Base, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &Size)) + { + exportRVA = RtlPointerToOffset(Base, pied); + DWORD NumberOfFunctions = pied->NumberOfFunctions; + DWORD NumberOfNames = pied->NumberOfNames; + if (0 < NumberOfNames && NumberOfNames <= NumberOfFunctions) + { + PDWORD AddressOfFunctions = (PDWORD)RtlOffsetToPointer(Base, pied->AddressOfFunctions); + PDWORD AddressOfNames = (PDWORD)RtlOffsetToPointer(Base, pied->AddressOfNames); + PWORD AddressOfNameOrdinals = (PWORD)RtlOffsetToPointer(Base, pied->AddressOfNameOrdinals); + DWORD a = 0, b = NumberOfNames, o; + do + { + o = (a + b) >> 1; + int i = strcmp(RtlOffsetToPointer(Base, AddressOfNames[o]), Name); + if (!i) + { + DWORD Rva = AddressOfFunctions[AddressOfNameOrdinals[o]]; + return (ULONG_PTR)Rva - (ULONG_PTR)exportRVA < Size ? 0 : RtlOffsetToPointer(BaseAddress, Rva); + } + 0 > i ? a = o + 1 : b = o; + } while (a < b); + } + } + } + return 0; +} + +PVOID GetSystem32ProcAddr(PCWSTR ObjectName, PCSTR procName) +{ + PVOID pv = 0; + OBJECT_ATTRIBUTES oa; + UNICODE_STRING oadll; + RtlInitUnicodeString(&oadll, ObjectName); + InitializeObjectAttributes(&oa, &oadll, OBJ_INHERIT, NULL, NULL); + HANDLE hSection; + int hr = ZwOpenSection(&hSection, SECTION_QUERY | SECTION_MAP_READ, &oa); + if (0 <= hr) + { + SECTION_IMAGE_INFORMATION sii; + if (0 <= ZwQuerySection(hSection, SectionImageInformation, &sii, sizeof(sii), 0)) + { + PVOID BaseAddress = 0; + SIZE_T ViewSize = 0; + if (0 <= ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0, 0, 0, &ViewSize, ViewUnmap, 0, PAGE_READONLY)) + { + pv = getRVA(BaseAddress, (ULONG_PTR)sii.TransferAddress, procName); + ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); + } + } + NtClose(hSection); + } + return pv; +} +#endif \ No newline at end of file diff --git a/wxDriver/ntapi.h b/wxDriver/ntapi.h new file mode 100644 index 0000000..68a6a00 --- /dev/null +++ b/wxDriver/ntapi.h @@ -0,0 +1,187 @@ +#pragma once +#include + +/* +* 函数指针、数据结构以及宏参考如下仓库 +* https://github.com/winsiderss/systeminformer +*/ + +#define RtlPointerToOffset(Base, Pointer) ((ULONG)(((PCHAR)(Pointer)) - ((PCHAR)(Base)))) +#define RtlOffsetToPointer(Base, Offset) ((PCHAR)(((PCHAR)(Base)) + ((ULONG_PTR)(Offset)))) +#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1) + +#ifndef OBJ_PROTECT_CLOSE +#define OBJ_PROTECT_CLOSE 0x00000001 +#endif +#ifndef OBJ_INHERIT +#define OBJ_INHERIT 0x00000002 +#endif +#ifndef OBJ_AUDIT_OBJECT_CLOSE +#define OBJ_AUDIT_OBJECT_CLOSE 0x00000004 +#endif + +#define InitializeObjectAttributes(p, n, a, r, s) { \ + (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ + (p)->RootDirectory = r; \ + (p)->Attributes = a; \ + (p)->ObjectName = n; \ + (p)->SecurityDescriptor = s; \ + (p)->SecurityQualityOfService = NULL; \ + } + +typedef enum _SECTION_INHERIT +{ + ViewShare = 1, + ViewUnmap = 2 +} SECTION_INHERIT; + +typedef enum _SECTION_INFORMATION_CLASS +{ + SectionBasicInformation, + SectionImageInformation, + SectionRelocationInformation, + SectionOriginalBaseInformation, + SectionInternalImageInformation, + MaxSectionInfoClass +} SECTION_INFORMATION_CLASS; + +typedef struct _UNICODE_STRING +{ + USHORT Length; + USHORT MaximumLength; + _Field_size_bytes_part_(MaximumLength, Length) PWCH Buffer; +} UNICODE_STRING, * PUNICODE_STRING; + +typedef struct _OBJECT_ATTRIBUTES +{ + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES; + +typedef struct _SECTION_IMAGE_INFORMATION +{ + PVOID TransferAddress; + ULONG ZeroBits; + SIZE_T MaximumStackSize; + SIZE_T CommittedStackSize; + ULONG SubSystemType; + union + { + struct + { + USHORT SubSystemMinorVersion; + USHORT SubSystemMajorVersion; + }; + ULONG SubSystemVersion; + }; + union + { + struct + { + USHORT MajorOperatingSystemVersion; + USHORT MinorOperatingSystemVersion; + }; + ULONG OperatingSystemVersion; + }; + USHORT ImageCharacteristics; + USHORT DllCharacteristics; + USHORT Machine; + BOOLEAN ImageContainsCode; + union + { + UCHAR ImageFlags; + struct + { + UCHAR ComPlusNativeReady : 1; + UCHAR ComPlusILOnly : 1; + UCHAR ImageDynamicallyRelocated : 1; + UCHAR ImageMappedFlat : 1; + UCHAR BaseBelow4gb : 1; + UCHAR ComPlusPrefer32bit : 1; + UCHAR Reserved : 2; + }; + }; + ULONG LoaderFlags; + ULONG ImageFileSize; + ULONG CheckSum; +} SECTION_IMAGE_INFORMATION, * PSECTION_IMAGE_INFORMATION; + + +typedef +NTSYSCALLAPI +PIMAGE_NT_HEADERS +(NTAPI* +pRtlImageNtHeader)( + _In_ PVOID BaseOfImage +); + +typedef +NTSYSCALLAPI +PVOID +(NTAPI* +pRtlImageDirectoryEntryToData)( + _In_ PVOID BaseOfImage, + _In_ BOOLEAN MappedAsImage, + _In_ USHORT DirectoryEntry, + _Out_ PULONG Size +); + +typedef +NTSYSCALLAPI +NTSTATUS +(NTAPI* +pZwOpenSection)( + _Out_ PHANDLE SectionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_ POBJECT_ATTRIBUTES ObjectAttributes +); + +typedef +NTSYSCALLAPI +NTSTATUS +(NTAPI* +pZwQuerySection)( + _In_ HANDLE SectionHandle, + _In_ SECTION_INFORMATION_CLASS SectionInformationClass, + _Out_writes_bytes_(SectionInformationLength) PVOID SectionInformation, + _In_ SIZE_T SectionInformationLength, + _Out_opt_ PSIZE_T ReturnLength +); + +typedef +NTSYSCALLAPI +NTSTATUS +(NTAPI* +pZwMapViewOfSection)( + _In_ HANDLE SectionHandle, + _In_ HANDLE ProcessHandle, + _Inout_ _At_(*BaseAddress, _Readable_bytes_(*ViewSize) _Writable_bytes_(*ViewSize) _Post_readable_byte_size_(*ViewSize)) PVOID* BaseAddress, + _In_ ULONG_PTR ZeroBits, + _In_ SIZE_T CommitSize, + _Inout_opt_ PLARGE_INTEGER SectionOffset, + _Inout_ PSIZE_T ViewSize, + _In_ SECTION_INHERIT InheritDisposition, + _In_ ULONG AllocationType, + _In_ ULONG Win32Protect +); + +typedef +NTSYSCALLAPI +NTSTATUS +(NTAPI* +pZwUnmapViewOfSection)( + _In_ HANDLE ProcessHandle, + _In_opt_ PVOID BaseAddress +); + +typedef +NTSYSCALLAPI +NTSTATUS +(NTAPI* +pNtClose)( + _In_ _Post_ptr_invalid_ HANDLE Handle +); \ No newline at end of file diff --git a/wxDriver/pch.cpp b/wxDriver/pch.cpp new file mode 100644 index 0000000..b6fb8f4 --- /dev/null +++ b/wxDriver/pch.cpp @@ -0,0 +1,5 @@ +锘// pch.cpp: 涓庨缂栬瘧鏍囧ご瀵瑰簲鐨勬簮鏂囦欢 + +#include "pch.h" + +// 褰撲娇鐢ㄩ缂栬瘧鐨勫ご鏃讹紝闇瑕佷娇鐢ㄦ婧愭枃浠讹紝缂栬瘧鎵嶈兘鎴愬姛銆 diff --git a/wxDriver/pch.h b/wxDriver/pch.h new file mode 100644 index 0000000..9660927 --- /dev/null +++ b/wxDriver/pch.h @@ -0,0 +1,13 @@ +锘// pch.h: 杩欐槸棰勭紪璇戞爣澶存枃浠躲 +// 涓嬫柟鍒楀嚭鐨勬枃浠朵粎缂栬瘧涓娆★紝鎻愰珮浜嗗皢鏉ョ敓鎴愮殑鐢熸垚鎬ц兘銆 +// 杩欒繕灏嗗奖鍝 IntelliSense 鎬ц兘锛屽寘鎷唬鐮佸畬鎴愬拰璁稿浠g爜娴忚鍔熻兘銆 +// 浣嗘槸锛屽鏋滄澶勫垪鍑虹殑鏂囦欢涓殑浠讳綍涓涓湪鐢熸垚涔嬮棿鏈夋洿鏂帮紝瀹冧滑鍏ㄩ儴閮藉皢琚噸鏂扮紪璇戙 +// 璇峰嬁鍦ㄦ澶勬坊鍔犺棰戠箒鏇存柊鐨勬枃浠讹紝杩欏皢浣垮緱鎬ц兘浼樺娍鏃犳晥銆 + +#ifndef PCH_H +#define PCH_H + +// 娣诲姞瑕佸湪姝ゅ棰勭紪璇戠殑鏍囧ご +#include "framework.h" + +#endif //PCH_H diff --git a/wxDriver/wxDriver.vcxproj b/wxDriver/wxDriver.vcxproj new file mode 100644 index 0000000..735935e --- /dev/null +++ b/wxDriver/wxDriver.vcxproj @@ -0,0 +1,183 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {b8740c2a-cbe7-4873-9669-e0dfec4a3b8d} + wxDriver + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Configuration)\socket\ + + + false + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Configuration)\socket\ + + + true + $(ProjectName)64 + $(SolutionDir)$(Configuration)\socket\ + + + false + $(ProjectName)64 + $(SolutionDir)$(Configuration)\socket\ + + + + Level3 + true + WIN32;_DEBUG;WXDRIVER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + WIN32;NDEBUG;WXDRIVER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + + + + + Level3 + true + _DEBUG;WXDRIVER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + NDEBUG;WXDRIVER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/wxDriver/wxDriver.vcxproj.filters b/wxDriver/wxDriver.vcxproj.filters new file mode 100644 index 0000000..e18bc6c --- /dev/null +++ b/wxDriver/wxDriver.vcxproj.filters @@ -0,0 +1,51 @@ +锘 + + + + {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/wxDriver/wxDriver.vcxproj.user b/wxDriver/wxDriver.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/wxDriver/wxDriver.vcxproj.user @@ -0,0 +1,4 @@ +锘 + + + \ No newline at end of file -- GitLab