Jump to content
Returning Members: Password Reset Required ×

Recommended Posts

Posted (edited)

Here's a full D3D8 Hook Tutorial in English, including all steps from knowledge prerequisites to debugging and logging.

📘 1. Prerequisites

Before diving into D3D8 hooking, you should be familiar with the following:

TopicDescription

C/C++ ProgrammingKnow classes, pointers, function pointers

DLL BasicsUnderstand how DLLs work and are injected

Windows APIBasic Win32 programming and message loop

Assembly & MemoryBasic understanding of memory layout and vtables

DirectX 8 ConceptsHow Direct3D8 renders (e.g., EndScene, Reset)

🧰 2. Required Tools

ToolPurposeRecommendation

Visual Studio 2019/2022Build and debug C++ projects✅

DirectX 8 SDKProvides d3d8.h, d3d8.lib, etc.✅

DLL InjectorInject your DLL into the target process[Extreme Injector, Process Hacker, or custom one]

Cheat EngineMemory inspection/debugging✅

DebugView or file loggerFor logging without a console✅

🛠️ 3. Create the Hook DLL Project

3.1 Set up a Visual Studio Project

Open Visual Studio → Create New Project → C++ Dynamic-Link Library (DLL)

Name it something like D3D8Hook

Set Project Properties:

C/C++ > General > Additional Include Directories: Add the DirectX SDK Include path

Linker > Input > Additional Dependencies: Add d3d8.lib, d3dx8.lib

3.2 Write the Hooking Code

// D3D8Hook.cpp

// D3D8Hook.cpp

#include <Windows.h>
#include <d3d8.h>
#include <d3dx8.h>

typedef HRESULT(APIENTRY* EndScene_t)(LPDIRECT3DDEVICE8 pDevice);
EndScene_t oEndScene = nullptr;

DWORD WINAPI MainThread(LPVOID);

// Hook implementation
HRESULT APIENTRY hkEndScene(LPDIRECT3DDEVICE8 pDevice)
{
    static bool once = false;
    if (!once)
    {
        MessageBoxA(0, "D3D8 Hooked!", "Success", MB_OK);
        once = true;
    }

    return oEndScene(pDevice);  // Call the original
}

void HookFunction()
{
    IDirect3D8* pD3D = Direct3DCreate8(D3D_SDK_VERSION);
    if (!pD3D) return;

    D3DPRESENT_PARAMETERS d3dpp = {};
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = GetForegroundWindow();

    IDirect3DDevice8* pDevice = nullptr;
    if (SUCCEEDED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
        d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice)))
    {
        void** vtable = *(void***)pDevice;
        oEndScene = (EndScene_t)vtable[35];

        DWORD oldProtect;
        VirtualProtect(&vtable[35], sizeof(void*), PAGE_EXECUTE_READWRITE, &oldProtect);
        vtable[35] = (void*)&hkEndScene;
        VirtualProtect(&vtable[35], sizeof(void*), oldProtect, &oldProtect);

        pDevice->Release();
    }

    pD3D->Release();
}

DWORD WINAPI MainThread(LPVOID)
{
    HookFunction();
    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID)
{
    if (reason == DLL_PROCESS_ATTACH)
        CreateThread(nullptr, 0, MainThread, nullptr, 0, nullptr);
    return TRUE;
}

3.3 Build the DLL

Use Build → Build Solution (Ctrl + Shift + B) and find the DLL in:

csharp

复制编辑

[YourProjectFolder]\x86\Debug\D3D8Hook.dll

Make sure it's compiled for x86 if the target process is 32-bit.

🧬 4. Injecting the DLL

Method 1: Use an Injector Tool

Start the game or D3D8-based application

Open an injector (e.g., Extreme Injector or Process Hacker)

Select the target process and inject D3D8Hook.dll

Method 2: Write Your Own Injector (optional)

cpp

复制编辑

HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPID); LPVOID addr = VirtualAllocEx(hProc, NULL, len, MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(hProc, addr, dllPath, len, NULL); CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, addr, 0, NULL);

🪛 5. Debugging and Logging

5.1 Output to DebugView

Use this to see logs:

cpp

复制编辑

OutputDebugStringA("D3D8 Hook initialized!");

You can view logs with DebugView by Sysinternals.

5.2 Write Logs to File

cpp

复制编辑

void Log(const char* msg) { FILE* f = fopen("C:\\D3D8_Hook_Log.txt", "a+"); if (f) { fprintf(f, "%s\n", msg); fclose(f); } }

5.3 Use Visual Studio Debugger

Build your DLL in Debug mode

Launch the target app

Attach Visual Studio (Debug → Attach to Process)

Set breakpoints in hkEndScene or elsewhere

✅ Common Issues & Fixes

IssuePossible Cause

Game crashesWrong vtable index or uninitialized pointers

Nothing happensHook not applied or wrong process architecture

DLL fails to injectMissing dependencies or wrong platform (x64 vs x86)

Edited by kennylovecode
Posted (edited)

And Next. how to use your D3D8 hook to render a custom UI inside the game/client.

🖼️ Goal: Render Custom UI Over Game Screen

We’ll do this by drawing inside the hkEndScene() function, which runs every frame right before the screen is presented.

✅ Prerequisites

You must have:

Already hooked EndScene (as we did above)

Access to the LPDIRECT3DDEVICE8 pointer

Initialized DirectX 8 properly in the target context

🧰 Tools and Libraries (Optional)

You can either:

Use raw D3D8 drawing functions (simple, less dependency)

Or use libraries like:

ImGui + D3D8 backend (more complex, but easier to make UIs)

D3DXFont / D3DXSprite (from d3dx8.lib)

Let’s start with a raw example, then show how to add ImGui.

🧪 Step-by-Step: Drawing Text and Boxes in hkEndScene

🔹 1. Draw Text with D3DXFont

LPD3DXFONT pFont = nullptr;

HRESULT APIENTRY hkEndScene(LPDIRECT3DDEVICE8 pDevice)
{
    if (!pFont) {
        D3DXCreateFont(pDevice, 20, 0, FW_NORMAL, 1, FALSE,
                       DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
                       ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
                       "Arial", &pFont);
    }

    RECT rect = { 10, 10, 300, 300 };
    pFont->DrawTextA(NULL, "Hello from Hook!", -1, &rect, DT_NOCLIP, D3DCOLOR_ARGB(255, 255, 0, 0));

    return oEndScene(pDevice);
}

🔎 This renders “Hello from Hook!” in red text at the top-left of the screen.

🔹 2. Draw a Filled Rectangle (Box)

void DrawBox(LPDIRECT3DDEVICE8 pDevice, float x, float y, float width, float height, D3DCOLOR color)
{
    struct Vertex {
        float x, y, z, rhw;
        DWORD color;
    };

    Vertex vertices[] = {
        { x, y, 0.0f, 1.0f, color },
        { x + width, y, 0.0f, 1.0f, color },
        { x, y + height, 0.0f, 1.0f, color },
        { x + width, y + height, 0.0f, 1.0f, color },
    };

    pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
    pDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
    pDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
    pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(Vertex));
}

// Inside hkEndScene
DrawBox(pDevice, 50, 50, 100, 20, D3DCOLOR_ARGB(150, 0, 255, 0)); // semi-transparent green box

🧱 Bonus: Show Health Bar Above Entity

Assuming you know the screen position (x, y) of the entity, you can do:

float healthPercent = 0.7f; // 70% health
DrawBox(pDevice, x, y - 10, 50, 5, D3DCOLOR_ARGB(150, 0, 0, 0)); // background
DrawBox(pDevice, x, y - 10, 50 * healthPercent, 5, D3DCOLOR_ARGB(200, 0, 255, 0)); // foreground

🎨 Optional: Use ImGui for Modern UI

ImGui works with D3D8 too, with slight setup. You’ll need:

ImGui

D3D8 backend (use imgui_impl_dx8.cpp)

Windows message handler (imgui_impl_win32.cpp)

In hkEndScene:

ImGui_ImplDX8_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();

ImGui::Begin("Custom UI");
ImGui::Text("Injected Overlay!");
ImGui::End();

ImGui::Render();
ImGui_ImplDX8_RenderDrawData(ImGui::GetDrawData());

🧪 Debug Tips

Ensure EndScene is being called (log or breakpoint)

Use OutputDebugString or write to file for diagnostics

If the overlay doesn’t show:

Make sure the render state is correct

The game window must be the foreground window (for some methods)

Try drawing solid rectangles first (not text)

✅ Summary

FeatureMethod

✅ TextD3DXCreateFont, DrawTextA

✅ Box/RectanglesCustom vertex arrays + DrawPrimitiveUP

✅ UIImGui (with D3D8 backend)

✅ Health BarCombine rectangles and entity coordinates

Edited by kennylovecode
Posted

What I am sharing is an idea of how to do it, not a complete project. But this idea is a feasible path that I have fully verified, not a hypothesis.

There is an ancient Chinese saying that "teach him how to fish is better then just give a man a fish". I think this is very important.

Posted

Peak 💫

Hooking D3D strides/font/Endscene etc..... would give player new GUI costume improvement

few months ago tried to hook D3D but i could not find D3D8 libs SDK 

Can you share any ref for d3d8 lib sdk 

 

Posted (edited)
6 hours ago, zMagic said:

Peak 💫

Hooking D3D strides/font/Endscene etc..... would give player new GUI costume improvement

few months ago tried to hook D3D but i could not find D3D8 libs SDK 

Can you share any ref for d3d8 lib sdk 

 

you can find it from "google", or github.com or anywhere if you search!

Even you can ask CHATGPT for the download link to this file, and it can provide it to you completely, which is much better than asking on a forum, waiting, waiting, waiting, and then giving up.

Edited by kennylovecode
Posted
On 6/27/2025 at 9:00 AM, Airplist said:

Can't use d3d9?

Depends on how old the client is. The original client was made using DX8.1.

Posted

I tried to do these things with d3d9, which can write to the console but not to the game interface, so I used d3d8. Should we set up a module or group chat specifically for this? This way it would be easier to learn from each other.

Posted
3 hours ago, Airplist said:

I tried to do these things with d3d9, which can write to the console but not to the game interface, so I used d3d8. Should we set up a module or group chat specifically for this? This way it would be easier to learn from each other.
我用 d3d9 尝试做过这些事情,虽然能写入控制台但无法写入游戏界面,所以改用了 d3d8。我们应该专门建立一个模块或群聊来讨论这个吗?这样互相学习会更容易。

As far as I know, most 2D version game clients are basically based on D3D8. If you have the capability, it can be changed to D3D9 or higher versions through hooking, but this requires deeper research

Posted

It is easy to draw, but it is somewhat difficult to change or add new functions. I will learn it next and we can communicate on the relevant topic.

Posted

Yes, actually I am willing to discuss and exchange these technologies, just as I have made some attempts and want to share them with everyone.
But it seems that not many people are interested...       

5 hours ago, Airplist said:

It is easy to draw, but it is somewhat difficult to change or add new functions. I will learn it next and we can communicate on the relevant topic.
绘制起来很容易,但修改或添加新功能有些困难。我接下来会学习它,我们可以就相关话题进行交流。

 

Posted

The main reason is that not many people take it seriously and just want to get what they want directly, so they are all waiting and watching.

Posted

So the community problem with the free system is that they don't need to put in any effort to receive the fruits of your labor and share them.
In fact, I used to run a points community in my country, which required sharing and earning point rewards to exchange for other people's labor achievements.
I think this is the only healthy and benign community...

Posted

Yes, that’s better. Or you need to share some tutorials yourself to get points. You can use the points to view the information shared by others. If you don’t have the ability to share, you have to buy points to buy the information shared by others.

Posted

But I don't know why they didn't do so. It seems that sharing is an obligation, and it rarely brings something valuable because people lack motivation.

Posted
7 hours ago, kennylovecode said:

But I don't know why they didn't do so. It seems that sharing is an obligation, and it rarely brings something valuable because people lack motivation.

This forum has a different mindset than the other forum, for sure. We're about open information and examples here. Showing how to do things to empower those who want to do things on their own. The mindset for the longest time was hording information in private groups. But I think there's enough people here now that recognize the strength of sharing information and getting more people involved. It doesn't mean share everything, but sharing knowledge is huge.

Posted

I think this is the right direction, just like what open-source communities like GitHub are doing. You've actually been doing this kind of thing for a long time, open-sourcing many projects and compiling some resources, including your ConquerWiki. But you'll find that this doesn't attract much fresh blood, because the developers for this Conquer game are almost fixed, and very few people are interested in the game, let alone those who would study it.

Posted

I used to do this few years ago, but for other purposes of the game. You can also disable some functions of the game and start rendering by your own module.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...