How to hook d3d9 and call my detour function?

Viewed 61

I'm trying to hook d3d9 EndScene in a game: Tibia otclient.

What I want to do is translate ingame XYZ coordinates to screen XY coordinates.

The typical WorldToScreen function.

Here I share the code I'm trying to use:

main.dll

#include "stdafx.h"
#include <windows.h>
#include "mem.h"
#include "gh_d3d9.h"

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;
}

mem.cpp

#include "stdafx.h"
#include "mem.h"

bool Hook(char* src, char* dst, int len)
{
    if (len < 5) return false;

    DWORD curProtection;

    VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &curProtection);

    memset(src, 0x90, len);

    uintptr_t relativeAddress = (uintptr_t)(dst - src - 5);

    *src = (char)0xE9;
    *(uintptr_t*)(src + 1) = (uintptr_t)relativeAddress;

    DWORD temp;
    VirtualProtect(src, len, curProtection, &temp);

    return true;
}

char* TrampHook(char* src, char* dst, unsigned int len)
{
    if (len < 5) return 0;

    // Create the gateway (len + 5 for the overwritten bytes + the jmp)
    char* gateway = (char*)VirtualAlloc(0, len + 5, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    // Put the bytes that will be overwritten in the gateway
    memcpy(gateway, src, len);

    // Get the gateway to destination addy
    uintptr_t gateJmpAddy = (uintptr_t)(src - gateway - 5);

    // Add the jmp opcode to the end of the gateway
    *(gateway + len) = (char)0xE9;

    // Add the address to the jmp
    *(uintptr_t*)(gateway + len + 1) = gateJmpAddy;

    // Place the hook at the destination
    if (Hook(src, dst, len))
    {
        return gateway;
    }
    else return nullptr;
}

As you can see in this image, I have EndScene address in vtable.

enter image description here

But I don't know why my function that is drawing a rectangle will never execute:

enter image description here

How should I hook DirectX and call my function?

EDIT:

Checking with Cheat Engine, my hook is loaded:

enter image description here

But it won't execute :(

0 Answers
Related