hook opengl
OpenGL 是一个状态机,程序每一帧都会调用 glFlush、glFinish 或 Windows 特有的 wglSwapBuffers 来结束当前帧的绘制。 我们要做的就是:
- 定位目标程序调用的
wglSwapBuffers 地址。
- 劫持(Hook)这个地址,指向我们自己的函数。
- 在我们的函数里,先用 OpenGL 画一个方框,然后再调用原有的函数完成显示。
dll
dllamin.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
| #include <windows.h> #include <GL/gl.h> #include <wrl/client.h> #include "imgui.h" #include "imgui_impl_win32.h" #include "imgui_impl_opengl3.h" #include <MinHook.h>
typedef BOOL(WINAPI* twglSwapBuffers)(HDC hdc); twglSwapBuffers oSwapBuffers = nullptr;
bool g_Initialized = false;
void DrawOverlay() { ImGui::NewFrame();
ImDrawList* drawList = ImGui::GetBackgroundDrawList();
ImVec2 p1 = ImVec2(100, 100); ImVec2 p2 = ImVec2(300, 300); ImU32 color = IM_COL32(255, 0, 0, 255);
drawList->AddRect(p1, p2, color, 0.0f, 0, 2.0f);
ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); }
BOOL WINAPI hSwapBuffers(HDC hdc) { if (!g_Initialized) { HWND hWnd = WindowFromDC(hdc); ImGui::CreateContext(); ImGui_ImplWin32_Init(hWnd); ImGui_ImplOpenGL3_Init(); g_Initialized = true; }
ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplWin32_NewFrame();
DrawOverlay();
return oSwapBuffers(hdc); }
DWORD WINAPI MainThread(LPVOID lpReserved) { if (MH_Initialize() == MH_OK) { void* pTarget = (void*)GetProcAddress(GetModuleHandleA("opengl32.dll"), "wglSwapBuffers"); MH_CreateHook(pTarget, &hSwapBuffers, reinterpret_cast<LPVOID*>(&oSwapBuffers)); MH_EnableHook(pTarget); } return 0; }
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID reserved) { if (reason == DLL_PROCESS_ATTACH) { DisableThreadLibraryCalls(hModule); CloseHandle(CreateThread(nullptr, 0, MainThread, hModule, 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
| # 【核心】禁用 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)
set(IMGUI_SOURCES ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_widgets.cpp ${IMGUI_DIR}/imgui_tables.cpp ${IMGUI_DIR}/imgui_demo.cpp ${IMGUI_DIR}/backends/imgui_impl_win32.cpp ${IMGUI_DIR}/backends/imgui_impl_opengl3.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 target_link_libraries(${PROJECT_NAME} PRIVATE minhook.x64.lib opengl32 gdi32 dwmapi )
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)
|