#include <Windows.h> #include <d3dx9.h> #include "imgui.h" #include "imgui_impl_dx9.h" #include "imgui_internal.h" #pragma comment(lib,"d3d9.lib") #pragma comment(lib,"d3dx9.lib") #pragma pack(push) #pragma pack(1) #ifndef _WIN64
#pragma execution_character_set("utf-8")
struct JmpCode { private: const BYTE jmp; DWORD address;
public: JmpCode(DWORD srcAddr, DWORD dstAddr): jmp(0xE9) { setAddress(srcAddr, dstAddr); }
void setAddress(DWORD srcAddr, DWORD dstAddr) { address = dstAddr - srcAddr - sizeof(JmpCode); } }; #else struct JmpCode { private: BYTE jmp[6]; uintptr_t address;
public: JmpCode(uintptr_t srcAddr, uintptr_t dstAddr) { static const BYTE JMP[] = { 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00 }; memcpy(jmp, JMP, sizeof(jmp)); setAddress(srcAddr, dstAddr); }
void setAddress(uintptr_t srcAddr, uintptr_t dstAddr) { address = dstAddr; } }; #endif #pragma pack(pop)
void hook(void* originalFunction, void* hookFunction, BYTE* oldCode) { JmpCode code((uintptr_t)originalFunction, (uintptr_t)hookFunction); DWORD oldProtect, oldProtect2; VirtualProtect(originalFunction, sizeof(code), PAGE_EXECUTE_READWRITE, &oldProtect); memcpy(oldCode, originalFunction, sizeof(code)); memcpy(originalFunction, &code, sizeof(code)); VirtualProtect(originalFunction, sizeof(code), oldProtect, &oldProtect2); }
void unhook(void* originalFunction, BYTE* oldCode) { DWORD oldProtect, oldProtect2; VirtualProtect(originalFunction, sizeof(JmpCode), PAGE_EXECUTE_READWRITE, &oldProtect); memcpy(originalFunction, oldCode, sizeof(JmpCode)); VirtualProtect(originalFunction, sizeof(JmpCode), oldProtect, &oldProtect2); }
void* endSceneAddr = NULL; BYTE endSceneOldCode[sizeof(JmpCode)];
WNDPROC oWndProc = nullptr; HWND Window = nullptr;
BOOL is_init = FALSE;
bool show_another_window = false;
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK hkWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_KEYDOWN: switch (wParam) { case VK_F9: MessageBox(0, 0, 0, 0); break; } break; } if (ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam)) return 1;
return CallWindowProc(oWndProc, hWnd, uMsg, wParam, lParam); }
HRESULT STDMETHODCALLTYPE MyEndScene(IDirect3DDevice9* thiz) { if (is_init == FALSE) { is_init = TRUE; ImGuiIO& io = ImGui::GetIO(); io.DeltaTime = 1.0f / 60.0f; D3DDEVICE_CREATION_PARAMETERS d3dcp{ 0 }; thiz->GetCreationParameters(&d3dcp); ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\simkai.ttf", 14.0f, NULL, io.Fonts->GetGlyphRangesChinese()); ImGui_ImplDX9_Init(d3dcp.hFocusWindow, thiz); ImGui::StyleColorsDark();
unhook(endSceneAddr, endSceneOldCode); HRESULT hr = thiz->EndScene(); hook(endSceneAddr, MyEndScene, endSceneOldCode); return hr;
}
static float f = 0.0f; static int counter = 0; static char sz[256] = { 0 };
ImGui_ImplDX9_NewFrame(); ImGui::Begin("LyShark.com 辅助GUI主菜单");
ImGui::Checkbox("弹出子窗口", &show_another_window); ImGui::SliderFloat("浮点条", &f, 0.0f, 1.0f);
ImGui::InputText("输入内容", sz, 256, 0, 0, 0);
if (ImGui::Button("点我触发")) { counter++; }
ImGui::SameLine(); ImGui::Text("触发次数 = %d", counter);
ImGui::Text("当前FPS: %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::End();
if (show_another_window) { ImGui::Begin("我是子窗体", &show_another_window); ImGui::Text(" 您好,LyShark, 这是一个测试窗体 !");
if (ImGui::Button("关闭窗体")) { show_another_window = false; }
ImGui::End(); } ImGui::EndFrame();
ImGui::Render(); ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
unhook(endSceneAddr, endSceneOldCode); HRESULT hr = thiz->EndScene(); hook(endSceneAddr, MyEndScene, endSceneOldCode); return hr; }
DWORD WINAPI initHookThread(LPVOID dllMainThread) {
WaitForSingleObject(dllMainThread, INFINITE); CloseHandle(dllMainThread);
WNDCLASSEX wc = {}; wc.cbSize = sizeof(wc); wc.style = CS_OWNDC; wc.hInstance = GetModuleHandle(NULL); wc.lpfnWndProc = DefWindowProc; wc.lpszClassName = L"Window";
if (RegisterClassEx(&wc) == 0) { return 0; }
HWND hwnd = CreateWindowEx(0, wc.lpszClassName, L"", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, NULL, NULL, wc.hInstance, NULL); if (hwnd == NULL) { return 0; }
IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION); if (d3d9 == NULL) { DestroyWindow(hwnd); return 0; }
D3DPRESENT_PARAMETERS pp = {}; pp.Windowed = TRUE; pp.SwapEffect = D3DSWAPEFFECT_COPY;
IDirect3DDevice9* device; if (FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &pp, &device))) { d3d9->Release(); DestroyWindow(hwnd); return 0; }
endSceneAddr = (*(void***)device)[42]; hook(endSceneAddr, MyEndScene, endSceneOldCode);
d3d9->Release(); device->Release(); DestroyWindow(hwnd); return 0; }
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { DWORD dwCurProcessId = *((DWORD*)lParam); DWORD dwProcessId = 0;
GetWindowThreadProcessId(hwnd, &dwProcessId); if (dwProcessId == dwCurProcessId && GetParent(hwnd) == NULL) { *((HWND *)lParam) = hwnd; return FALSE; } return TRUE; }
HWND GetMainWindow() { DWORD dwCurrentProcessId = GetCurrentProcessId(); if (!EnumWindows(EnumWindowsProc, (LPARAM)&dwCurrentProcessId)) { return (HWND)dwCurrentProcessId; } return NULL; }
BOOL APIENTRY DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) {
switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH:
HANDLE curThread; if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &curThread, SYNCHRONIZE, FALSE, 0)) return FALSE; CloseHandle(CreateThread(NULL, 0, initHookThread, curThread, 0, NULL));
Window = GetMainWindow();
oWndProc = (WNDPROC)SetWindowLongA(Window, GWL_WNDPROC, (LONG)hkWndProc); if (oWndProc == nullptr) return 1;
ImGui::CreateContext(); break;
case DLL_PROCESS_DETACH: if (endSceneAddr != NULL) unhook(endSceneAddr, endSceneOldCode); break;
break;
case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break; } return TRUE; }
|