Source Code D3D9 EndScene Hook Template Using Dummy Device

Hexui Undetected CSGO Cheats PUBG Accounts

Rake

I'm not your friend
Administrator
Jan 21, 2014
13,306
79,068
2,484
How long you been coding/hacking?
5 years
This is a simple D3D9 EndScene Hook Template, you can hit compile and inject it into any Direct3D9 game and it will show a red box on the screen.

Credits to @Broihon @0xDEC0DE @Solaire their code was instrumental in creating this little template.

This template gets the D3D9 Device Pointer and EndScene address using:
https://guidedhacking.com/threads/get-direct3d9-and-direct3d11-devices-dummy-device-method.11867/

Then we do a Trampoline Hook after getting the address of EndScene from the vTable. This is not VMT hooking.

Here is what main.cpp looks like:
C++:
bool bInit = false;
tEndScene oEndScene = nullptr;
LPDIRECT3DDEVICE9 pD3DDevice = nullptr;
void* d3d9Device[119];

HRESULT APIENTRY hkEndScene(LPDIRECT3DDEVICE9 pDevice)
{
    if (bInit == false)
    {
        pD3DDevice = pDevice;
        bInit = true;
    }

    //draw stuff here like so:
    DrawFilledRect(200, 200, 200, 200, D3DCOLOR_ARGB(255, 255, 0, 0), pDevice);

    return oEndScene(pDevice);
}

DWORD WINAPI Init(HMODULE hModule)
{
    if (GetD3D9Device(d3d9Device, sizeof(d3d9Device)))
    {
        oEndScene = (tEndScene)TrampHook((char*)d3d9Device[42], (char*)hkEndScene, 7);
    }
    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        CloseHandle(CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)Init, hModule, 0, nullptr));
    }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
If you know nothing about Direct3D, do this guide:
https://guidedhacking.com/threads/how-to-get-started-with-directx-9-make-your-menu-hacks.10402

Stay tuned for a more thorough release and a bone ESP using this source code also.
 

Attachments

You can download 0 Attachments

StraightArrow

Dank Tier Donator
Aug 28, 2020
4
208
0
Hi,
Thanks for this code. It's been useful. I was trying to test some other functions with this. Namely, I need Present to be hooked. It does not seem to work. I "printed out" the address that present points to (the vtable for present is this btw d3d9Device[17]). And I got a relative jmp to another jmp to the overlayrenderer. I've tried breakpointing in multiple spots in that chain and have had no hits. By comparison, I tried this with begin scene and it worked just fine and looked similar to end scene. I looked at the pix data for my game and I see Present is a part of IDirect3dswapchain9 instead of idirect3ddevice9. Could this be the culprit? I also read something about d3d9 using the COM-Model so functions are not as cut and dry. I was thinking of pattern scanning if this dummydevice/vtable method doesn't work. Is that a better route?
 

StraightArrow

Dank Tier Donator
Aug 28, 2020
4
208
0
Hi @Rake, thanks for the reply. I wanted to try to figure it out before replying again, and I got really close, but now I'm stuck. I think D3D9 works differently and we don't have IDXGISwapChain->Present. It's more like IDirect3DSwapChain9:: Present. So what I did was, I kept the d3d Dummy device active and executed this
C++:
IDirect3DSwapChain9* pDummySwapchain;
    HRESULT dummySwapCreated = d3ddevice->CreateAdditionalSwapChain(d3dpresentparam, &pDummySwapchain);
    //swapchain[3] is probably what present we need;
    memcpy(pSwapchainTable, *reinterpret_cast<void***>(pDummySwapchain), Size_Swapchain);
So basically creating an additional swapchain object and copying its vtable. Encouragingly, breakpoints were hitting when I breakpointed calls with this vtable, so I'm like 80% sure I'm hitting the real-time present call.
BUT.
For some reason copying instructions to the gateway has created issues. Basically, the first few bytes of Present are a jmp instruction, then another jmp instruction (instead of easy stuff with begin scene/end scene like mov push etc). When I copy that jmp instruction +address to my gateway I get undefined behavior. It's weird because the bytes are EXACTLY the same as Present's first bytes (e9 xyz), but when I check with cheat engine the final, actual jmp location will be random every time. I was thinking, does this have something to do with jmping between such different address spaces e.g. my dll vs d3d9? Is the memcpy having undefined behavior? Thanks for all your help thus far.
 

Rake

I'm not your friend
Administrator
Jan 21, 2014
13,306
79,068
2,484
@StraightArrow many softwares hook these functions, such as Discord Overlay, Steam Overlay, Windows GAme Presence/Xbox overlay, MSI Afterburner, Fraps, OBS etc... First try disabling all of these and see if the jmps disappear.

Our tutorials and source codes are PoCs for beginners to learn.

If your stolen bytes include relative offsets then you must resolve these at runtime by changing the stolen bytes, something like this:
absolute_address = old_EIP + relative offset
new_relative_offset = absolute_address - new_EIP

If it's a jmp and it just jmps to some other Windows DLL, then maybe you just need to follow the jmp and then hook whatever function that is instead. For instance with OpenGL we wanna hook glSwapBuffers, but it turns out we have to hook wgl_SwapBuffers instead which is some Windows implementation of it.

You can also hook the overlay software instead.

Regardless of all that, you can use some popular hooking libs like Polyhook which will follow the jmps for you and fix the stolen bytes for you automatically.

So, if it's just relative offsets in your stolen bytes, resolve them. If it's a jmp, code your hook to detect jmps using a disassembler & follow the jmp and hook there
 
Community Mods