d3d11

dllmain.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <windows.h>
#include <d3d11.h>
#include <dxgi.h>
#include <iostream>
#include "imgui.h"
#include "imgui_impl_win32.h"
#include "imgui_impl_dx11.h"
#include "MinHook.h"

// 链接库(也可以写在 CMakeLists 里)
#pragma comment(lib, "d3d11.lib")

// --- 类型定义 ---
typedef HRESULT(STDMETHODCALLTYPE* Present_t)(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags);
Present_t oPresent = nullptr;

// --- 全局变量 ---
ID3D11Device* g_pd3dDevice = nullptr;
ID3D11DeviceContext* g_pd3dContext = nullptr;
ID3D11RenderTargetView* g_mainRenderTargetView = nullptr;
bool g_Initialized = false;

// 外部声明 ImGui 消息处理函数
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

// --- 渲染 Hook 函数 ---
HRESULT STDMETHODCALLTYPE hkPresent(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags) {
if (!g_Initialized) {
if (SUCCEEDED(pSwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&g_pd3dDevice))) {
g_pd3dDevice->GetImmediateContext(&g_pd3dContext);
DXGI_SWAP_CHAIN_DESC sd;
pSwapChain->GetDesc(&sd);

ImGui::CreateContext();
ImGui_ImplWin32_Init(sd.OutputWindow);
ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dContext);
g_Initialized = true;
}
}

// 创建或更新渲染目标
if (g_mainRenderTargetView == nullptr) {
ID3D11Texture2D* pBackBuffer = nullptr;
pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
if (pBackBuffer) {
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView);
pBackBuffer->Release();
}
}

// 开始绘制
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();

// 绘制你的方框
ImGui::GetBackgroundDrawList()->AddRect(ImVec2(50, 50), ImVec2(250, 250), IM_COL32(0, 255, 0, 255), 0, 0, 3.0f);
ImGui::SetNextWindowPos(ImVec2(60, 60));
ImGui::Begin("D3D11 Hook", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
ImGui::Text("Status: INJECTED");
ImGui::End();

ImGui::Render();
g_pd3dContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL);
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

return oPresent(pSwapChain, SyncInterval, Flags);
}

// --- 核心:寻找 VTable 逻辑 ---
DWORD WINAPI MainThread(LPVOID lpReserved) {
// 1. 创建临时窗口和设备以获取 VTable 地址
DXGI_SWAP_CHAIN_DESC sd = {};
sd.BufferCount = 1;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = GetForegroundWindow(); // 临时借用
sd.SampleDesc.Count = 1;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

ID3D11Device* pTmpDevice = nullptr;
ID3D11DeviceContext* pTmpContext = nullptr;
IDXGISwapChain* pTmpSwapChain = nullptr;
D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;

if (FAILED(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &featureLevel, 1, D3D11_SDK_VERSION, &sd, &pTmpSwapChain, &pTmpDevice, NULL, &pTmpContext))) {
return FALSE;
}

// 2. 拿到虚函数表
void** vTable = *(void***)pTmpSwapChain;

// 3. Hook IDXGISwapChain::Present (索引为 8)
if (MH_Initialize() == MH_OK) {
// vTable[8] 是 Present, vTable[13] 是 ResizeBuffers
MH_CreateHook(vTable[8], &hkPresent, reinterpret_cast<LPVOID*>(&oPresent));
MH_EnableHook(MH_ALL_HOOKS);
}

// 清理临时资源
pTmpSwapChain->Release();
pTmpContext->Release();
pTmpDevice->Release();

return TRUE;
}

BOOL WINAPI DllMain(HMODULE hMod, DWORD dwReason, LPVOID lpReserved) {
if (dwReason == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls(hMod);
CreateThread(nullptr, 0, MainThread, hMod, 0, nullptr);
}
return TRUE;
}

CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

# 【核心】禁用 vcpkg 所有的自动集成行为
set(VCPKG_MANIFEST_MODE OFF CACHE BOOL "Disable vcpkg manifest" FORCE)
set(X_VCPKG_APPLOCAL_DEPS_INSTALL OFF CACHE BOOL "Disable applocal copy" FORCE)

project(GLBoxHook LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)

# 1. 统一输出目录到 bin
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

# 2. ImGui 路径 (保持不变)
set(IMGUI_DIR "C:/D/test/CCpp/ccpplib/imgui")
include_directories(${IMGUI_DIR} ${IMGUI_DIR}/backends)

# 1. 更新 ImGui 源码搜集(换成 D3D11 后端)
# 搜集 DX11 后端文件
set(IMGUI_SOURCES
${IMGUI_DIR}/imgui.cpp
${IMGUI_DIR}/imgui_draw.cpp
${IMGUI_DIR}/imgui_widgets.cpp
${IMGUI_DIR}/imgui_tables.cpp
${IMGUI_DIR}/backends/imgui_impl_win32.cpp
${IMGUI_DIR}/backends/imgui_impl_dx11.cpp
)


# 3. 手动链接 vcpkg 下的 MinHook (硬路径)
set(VCPKG_BASE "C:/D/test/CCpp/ccpplib/vcpkg/vcpkg/installed/x64-windows-static")
include_directories("${VCPKG_BASE}/include")
link_directories("${VCPKG_BASE}/lib")

# 4. 生成 DLL
add_library(${PROJECT_NAME} SHARED dllmain.cpp ${IMGUI_SOURCES})

# 5. 链接系统库和 minhook
# 注意:如果链接报错,请检查 lib 目录下是否叫 minhook.lib 还是 libMinHook.x64.lib
# 2. 链接 D3D 核心库
# 链接 D3D11 必备库
target_link_libraries(${PROJECT_NAME} PRIVATE
minhook.x64.lib
d3d11
dxgi
d3dcompiler
)

add_definitions(-DUNICODE -D_UNICODE -D_CRT_SECURE_NO_WARNINGS)
if(MSVC)
add_compile_options("/utf-8")
endif()
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)