diff --git a/DbkeyHook.sln b/DbkeyHook.sln new file mode 100644 index 0000000..2457d24 --- /dev/null +++ b/DbkeyHook.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.35931.194 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DbkeyHook", "DbkeyHook.vcxproj", "{B8305ABB-1F1B-4FD5-AF77-A1F7C9CB67FD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B8305ABB-1F1B-4FD5-AF77-A1F7C9CB67FD}.Debug|x64.ActiveCfg = Debug|x64 + {B8305ABB-1F1B-4FD5-AF77-A1F7C9CB67FD}.Debug|x64.Build.0 = Debug|x64 + {B8305ABB-1F1B-4FD5-AF77-A1F7C9CB67FD}.Debug|x86.ActiveCfg = Debug|Win32 + {B8305ABB-1F1B-4FD5-AF77-A1F7C9CB67FD}.Debug|x86.Build.0 = Debug|Win32 + {B8305ABB-1F1B-4FD5-AF77-A1F7C9CB67FD}.Release|x64.ActiveCfg = Release|x64 + {B8305ABB-1F1B-4FD5-AF77-A1F7C9CB67FD}.Release|x64.Build.0 = Release|x64 + {B8305ABB-1F1B-4FD5-AF77-A1F7C9CB67FD}.Release|x86.ActiveCfg = Release|Win32 + {B8305ABB-1F1B-4FD5-AF77-A1F7C9CB67FD}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8CABB8D3-3F51-4D43-A140-C354CCCC4C28} + EndGlobalSection +EndGlobal diff --git a/DbkeyHook.vcxproj b/DbkeyHook.vcxproj new file mode 100644 index 0000000..85995c4 --- /dev/null +++ b/DbkeyHook.vcxproj @@ -0,0 +1,178 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {b8305abb-1f1b-4fd5-af77-a1f7c9cb67fd} + DbkeyHook + 10.0 + mmmojo_64 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;DBKEYHOOK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + WIN32;NDEBUG;DBKEYHOOK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + + + + + Level3 + true + _DEBUG;DBKEYHOOK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + NDEBUG;DBKEYHOOK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + + + + + + + + + + + Create + Create + Create + Create + + + + + Document + + + + + + + \ No newline at end of file diff --git a/DbkeyHook.vcxproj.filters b/DbkeyHook.vcxproj.filters new file mode 100644 index 0000000..6ca96f3 --- /dev/null +++ b/DbkeyHook.vcxproj.filters @@ -0,0 +1,41 @@ + + + + + {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/DbkeyHook.vcxproj.user b/DbkeyHook.vcxproj.user new file mode 100644 index 0000000..0f14913 --- /dev/null +++ b/DbkeyHook.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dllmain.cpp b/dllmain.cpp new file mode 100644 index 0000000..f0c3c55 --- /dev/null +++ b/dllmain.cpp @@ -0,0 +1,253 @@ +// dllmain.cpp : 定义 DLL 应用程序的入口点。 +#include "pch.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//x64汇编 +#include "wrapper.h" + + +// 劫持mmmojo_64.dll -> mmmojo_64_true.dll +#pragma comment(linker, "/EXPORT:AppendMMSubProcessSwitchNative=mmmojo_64_true.AppendMMSubProcessSwitchNative,@1") +#pragma comment(linker, "/EXPORT:CreateMMMojoEnvironment=mmmojo_64_true.CreateMMMojoEnvironment,@2") +#pragma comment(linker, "/EXPORT:CreateMMMojoWriteInfo=mmmojo_64_true.CreateMMMojoWriteInfo,@3") +#pragma comment(linker, "/EXPORT:GetHandleVerifier=mmmojo_64_true.GetHandleVerifier,@4") +#pragma comment(linker, "/EXPORT:GetMMMojoReadInfoAttach=mmmojo_64_true.GetMMMojoReadInfoAttach,@5") +#pragma comment(linker, "/EXPORT:GetMMMojoReadInfoMethod=mmmojo_64_true.GetMMMojoReadInfoMethod,@6") +#pragma comment(linker, "/EXPORT:GetMMMojoReadInfoRequest=mmmojo_64_true.GetMMMojoReadInfoRequest,@7") +#pragma comment(linker, "/EXPORT:GetMMMojoReadInfoSync=mmmojo_64_true.GetMMMojoReadInfoSync,@8") +#pragma comment(linker, "/EXPORT:GetMMMojoWriteInfoAttach=mmmojo_64_true.GetMMMojoWriteInfoAttach,@9") +#pragma comment(linker, "/EXPORT:GetMMMojoWriteInfoRequest=mmmojo_64_true.GetMMMojoWriteInfoRequest,@10") +#pragma comment(linker, "/EXPORT:InitializeMMMojo=mmmojo_64_true.InitializeMMMojo,@11") +#pragma comment(linker, "/EXPORT:IsSandboxedProcess=mmmojo_64_true.IsSandboxedProcess,@12") +#pragma comment(linker, "/EXPORT:RemoveMMMojoEnvironment=mmmojo_64_true.RemoveMMMojoEnvironment,@13") +#pragma comment(linker, "/EXPORT:RemoveMMMojoReadInfo=mmmojo_64_true.RemoveMMMojoReadInfo,@14") +#pragma comment(linker, "/EXPORT:RemoveMMMojoWriteInfo=mmmojo_64_true.RemoveMMMojoWriteInfo,@15") +#pragma comment(linker, "/EXPORT:SendMMMojoWriteInfo=mmmojo_64_true.SendMMMojoWriteInfo,@16") +#pragma comment(linker, "/EXPORT:SetMMMojoConfiguration=mmmojo_64_true.SetMMMojoConfiguration,@17") +#pragma comment(linker, "/EXPORT:SetMMMojoEnvironmentCallbacks=mmmojo_64_true.SetMMMojoEnvironmentCallbacks,@18") +#pragma comment(linker, "/EXPORT:SetMMMojoEnvironmentInitParams=mmmojo_64_true.SetMMMojoEnvironmentInitParams,@19") +#pragma comment(linker, "/EXPORT:SetMMMojoWriteInfoMessagePipe=mmmojo_64_true.SetMMMojoWriteInfoMessagePipe,@20") +#pragma comment(linker, "/EXPORT:SetMMMojoWriteInfoResponseSync=mmmojo_64_true.SetMMMojoWriteInfoResponseSync,@21") +#pragma comment(linker, "/EXPORT:ShutdownMMMojo=mmmojo_64_true.ShutdownMMMojo,@22") +#pragma comment(linker, "/EXPORT:StartMMMojoEnvironment=mmmojo_64_true.StartMMMojoEnvironment,@23") +#pragma comment(linker, "/EXPORT:StopMMMojoEnvironment=mmmojo_64_true.StopMMMojoEnvironment,@24") +#pragma comment(linker, "/EXPORT:SwapMMMojoWriteInfoCallback=mmmojo_64_true.SwapMMMojoWriteInfoCallback,@25") +#pragma comment(linker, "/EXPORT:SwapMMMojoWriteInfoMessage=mmmojo_64_true.SwapMMMojoWriteInfoMessage,@26") + +extern "C" uint64_t HijackLogic(uint64_t key_class); //劫持逻辑 +extern "C" uint64_t g_imgbase = 0; //Weixin.dll的基址 +extern "C" uint64_t g_hook_offset = 0; //要hook的偏移 +extern "C" uint8_t * g_transfer_zone = 0; //中转指令内存 + +struct OrgInfo +{ + uint64_t addr; //地址 + size_t org_size; //原始机器码长度 + uint8_t org_opcodes[256]; //被HOOK之前原始的机器码 +}; +std::vector g_org_info; + +void OutputDebugPrintf(const char* strOutputString, ...) +{ +#define OUT_DEBUG_BUF_LEN 512 + char strBuffer[OUT_DEBUG_BUF_LEN] = { 0 }; + va_list vlArgs; + va_start(vlArgs, strOutputString); + _vsnprintf_s(strBuffer, sizeof(strBuffer) - 1, strOutputString, vlArgs); //_vsnprintf_s _vsnprintf + va_end(vlArgs); + OutputDebugStringA(strBuffer); //OutputDebugString // OutputDebugStringW +} + + +std::string toHexString(const uint8_t* data, size_t size) { + std::stringstream ss; + ss << std::hex << std::setfill('0'); + for (size_t i = 0; i < size; ++i) { + ss << std::setw(2) << static_cast(data[i]); + } + return ss.str(); +} + +/** + * @brief 恢复HOOK写入的字节. + */ +void HookEnd(uint8_t type) +{ + //写入原机器码 + if (g_org_info.size() != 0) { + for (auto& org_info : g_org_info) + { + if (org_info.addr == 0) { + OutputDebugString(TEXT("[DbkeyHook] Hook Addr is 0")); + continue; + } + BOOL bRet = WriteProcessMemory(GetCurrentProcess(), (LPVOID)org_info.addr, org_info.org_opcodes, org_info.org_size, NULL); + if (bRet == NULL) + OutputDebugPrintf("[DbkeyHook] Write Hook Org Bytes Failed! [%d]", GetLastError()); + } + } + if (type == 2) { + if (g_transfer_zone) { + if (!VirtualFree(g_transfer_zone, 0, MEM_RELEASE)) { + OutputDebugPrintf("[DbkeyHook] Free Transfer Mem Failed! [%d]", GetLastError()); + return; + } + } + } +} + + +uint64_t HijackLogic(uint64_t a4/*r9*/) +{ + + uint64_t key_class = a4; + uint64_t DbkeyLength_addr = key_class + 0x18, DbkeyLength = 0; + uint64_t Dbkey_addr_offet = key_class + 0x8, DbkeyAddr = 0; + + + ReadProcessMemory(GetCurrentProcess(), (LPCVOID)DbkeyLength_addr, &DbkeyLength, 4, NULL); // + ReadProcessMemory(GetCurrentProcess(), (LPCVOID)Dbkey_addr_offet, &DbkeyAddr, 8, NULL); // + + OutputDebugPrintf("[DbkeyHook] DbkeyLength = [%d],DbkeyAddr = 0x%llX", DbkeyLength, DbkeyAddr); + + if (!DbkeyAddr || DbkeyLength != 32) { + return 0; + } + + uint8_t db_key[32]; + + BOOL bRet = ReadProcessMemory(GetCurrentProcess(), (LPCVOID)DbkeyAddr, db_key, 32, NULL); + if (!bRet) + { + OutputDebugPrintf("[DbkeyHook] Read db_key Bytes Failed! [%d]", GetLastError()); + return 0; + } + + std::string db_key_Str = toHexString(db_key, sizeof(db_key)); + OutputDebugPrintf("[DbkeyHook] GET DBkey String [%s]", db_key_Str.c_str()); + + std::ofstream file("dbkey.txt"); // 默认覆盖模式 + if (file.is_open()) { + file << db_key_Str; // 写入文本 + file.close(); // 显式关闭文件(可选,析构时会自动关闭) + //获取到dbkey就取消hook + HookEnd(1); + OutputDebugPrintf("[DbkeyHook] Write dbkey to dbkey.txt"); + } + else { + + OutputDebugPrintf("[DbkeyHook] Write dbkey.txt Failed! [%d]", GetLastError()); + } + + + return 0; + +} + + +void HookStart(HMODULE hModule) +{ + HMODULE weixin_dll_base = GetModuleHandle(_T("Weixin.dll")); + if (weixin_dll_base == NULL) + { + OutputDebugPrintf("[DbkeyHook] Get Weixin.dll's ImgBase Failed! [%d]", GetLastError()); + return; + } + g_imgbase = (uint64_t)weixin_dll_base; + g_hook_offset = 0x0C0A9A6;// 这个是4.0.5.7的 4.0.3.43 = 0x0BC91A6 + + //读取Hook点原机器码 + uint64_t hook_addr = g_imgbase + g_hook_offset; + uint8_t hook_opcode[] = {/*mov rax, 地址*/0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*jmp rax*/0xFF, 0xE0 }; + size_t hook_size = sizeof(hook_opcode); //12个字节 + + OrgInfo hook_org_info;// 记录原始字节信息 + hook_org_info.addr = hook_addr; //记录地址 + hook_org_info.org_size = hook_size; //记录要写多少个字节 + BOOL bRet = ReadProcessMemory(GetCurrentProcess(), (LPCVOID)hook_addr, hook_org_info.org_opcodes, hook_size, NULL); + if (!bRet) + { + OutputDebugPrintf("[DbkeyHook] Read Hook Org Bytes Failed! [%d]", GetLastError()); + return; + } + g_org_info.push_back(hook_org_info); //记录 + + + + //构造中转区机器码 原指令 + jmp far + size_t org_insns_len = hook_size; //暂时先写死 + g_transfer_zone = (uint8_t*)VirtualAlloc(NULL, 64, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!g_transfer_zone) { + OutputDebugPrintf("[DbkeyHook] Alloc Transfer Mem Failed! [%d]", GetLastError()); + return; + } + + bRet = ReadProcessMemory(GetCurrentProcess(), (LPCVOID)hook_addr, g_transfer_zone, org_insns_len, NULL); + if (!bRet) + { + OutputDebugPrintf("[DbkeyHook] Read Transfer Zone Org Bytes Failed! [%d]", GetLastError()); + return; + } + + uint8_t jmp_org_opcode[] = { 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0 }; + uint64_t next_insn_addr = hook_addr + org_insns_len; + for (size_t i = 0; i < sizeof(uint64_t); i++) //跳回去 + jmp_org_opcode[i + 2] = *((uint8_t*)(&next_insn_addr) + i); + memcpy(g_transfer_zone + org_insns_len, jmp_org_opcode, sizeof(jmp_org_opcode)); + OutputDebugPrintf("[DbkeyHook] g_transfer_zone Addr: 0x%llX", g_transfer_zone); + + + + //写入劫持机器码 跳转到HijackLogicWarpper函数处 + uint64_t hijacklogic_addr = (uint64_t)(&HijackLogicWarpper); + for (size_t i = 0; i < sizeof(uint64_t); i++) + { + hook_opcode[i + 2] = *((uint8_t*)(&hijacklogic_addr) + i); + } + bRet = WriteProcessMemory(GetCurrentProcess(), (LPVOID)hook_addr, hook_opcode, hook_size, NULL); + if (bRet == NULL) + { + OutputDebugPrintf("[DbkeyHook] Write Hook Bytes Failed! [%d]", GetLastError()); + return; + } + + +} + + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hModule); //防止多次调用 + //不知道为什么不会自动加载mmmojo_64_true.dll 直接手动加载 + OutputDebugPrintf("[DbkeyHook] Load mmmojo_64_true.dll: 0x%llX", LoadLibrary(TEXT("mmmojo_64_true.dll"))); + OutputDebugString(TEXT("[DbkeyHook] Begin Hook and Hijack!")); + HookStart(hModule); + break; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + OutputDebugString(TEXT("[DbkeyHook] Restore Hook Bytes!")); + HookEnd(2); + break; + } + return TRUE; +} + diff --git a/framework.h b/framework.h new file mode 100644 index 0000000..3f0fc4a --- /dev/null +++ b/framework.h @@ -0,0 +1,5 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 +// Windows 头文件 +#include diff --git a/pch.cpp b/pch.cpp new file mode 100644 index 0000000..db1a479 --- /dev/null +++ b/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: 与预编译标头对应的源文件 + +#include "pch.h" + +// 当使用预编译的头时,需要使用此源文件,编译才能成功。 diff --git a/pch.h b/pch.h new file mode 100644 index 0000000..aa4549e --- /dev/null +++ b/pch.h @@ -0,0 +1,13 @@ +// pch.h: 这是预编译标头文件。 +// 下方列出的文件仅编译一次,提高了将来生成的生成性能。 +// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。 +// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。 +// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。 + +#ifndef PCH_H +#define PCH_H + +// 添加要在此处预编译的标头 +#include "framework.h" + +#endif //PCH_H diff --git a/wrapper.asm b/wrapper.asm new file mode 100644 index 0000000..a6c5594 --- /dev/null +++ b/wrapper.asm @@ -0,0 +1,50 @@ +EXTERN HijackLogic: PROC ; ⲿ + +EXTERN g_transfer_zone: QWORD ; ⲿ + +.CODE + +; ջ룺 64 λģʽ£úʱջ 16 ֽڶ +HijackLogicWarpper PROC + push rbx ; ѹͨüĴ + push rcx + push rdx + push rsi + push rdi + push rbp + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + pushfq ; ѹeflags + + sub rsp, 28h ; ջ + mov rcx, r9 ; Ϊarg4 + call HijackLogic ; HijackLogic ޸KeyClassڴ + add rsp, 28h ; ָջ + + popfq ; ָeflags + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rbp + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx ; ָͨüĴ + + mov rax, qword ptr [g_transfer_zone] ; raxֵg_transfer_zone + jmp rax ; תתڴִԭָ +HijackLogicWarpper ENDP + +END \ No newline at end of file diff --git a/wrapper.h b/wrapper.h new file mode 100644 index 0000000..bab621c --- /dev/null +++ b/wrapper.h @@ -0,0 +1,4 @@ +#pragma once +#include + +extern "C" uint64_t HijackLogicWarpper(uint64_t PixCloudInstance); \ No newline at end of file