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