从哪里开始创建 D3D11 Hook 来制作游戏叠加层?

0 c++ directx overlay directx-11

我目前正在开发我的第一个 D3D 项目,其中涉及为游戏创建叠加层,以便向用户呈现实时信息。实际的数据采集已经处理完毕,将通过消息系统发送。目前,我的程序适用于无边框全屏模式,并且正在调整它以在窗口模式下按比例缩放(以确保所有内容都指向正确的位置,无论大小如何)。该应用程序是游戏的父级,但是,当游戏进入真正的全屏模式时,一切都会崩溃。研究表明,据我了解,我需要创建一个假的 .dll,并将其插入到游戏的本地目录中。该 .dll 将被打开,而不是它正在寻找的实际 directX DLL,我可以在那里制作所需的图形。

为了回答一些潜在的问题,我无法直接访问游戏,而且,虽然相关游戏的开发者已经同意这一点,但我宁愿它不要被反作弊软件捕获和惩罚。此外,我希望将性能影响保持在最低限度,因此目前覆盖层的 FPS 相当低(~10fps)。

预先感谢您的任何帮助!

Gui*_*ing 5

这是我刚刚使用的 D3D11 Present x64 蹦床挂钩项目。你可以在返回之前在里面画画hkPresent(),你画的任何东西都会显示在屏幕上。

#include <Windows.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#include <DirectXMath.h>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dcompiler.lib")

#define SAFE_RELEASE(p) if (p) { p->Release(); p = nullptr; } 

void* Tramp64(void* src, void* dst, int len)
{
    int MinLen = 14;

    if (len < MinLen) return NULL;

    BYTE stub[] = {
    0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [$+6]
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // ptr
    };

    void* pTrampoline = VirtualAlloc(0, len + sizeof(stub), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    DWORD dwOld = 0;
    VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &dwOld);

    uintptr_t retto = (uintptr_t)src + len;

    // trampoline
    memcpy(stub + 6, &retto, 8);
    memcpy((void*)((uintptr_t)pTrampoline), src, len);
    memcpy((void*)((uintptr_t)pTrampoline + len), stub, sizeof(stub));

    // orig
    memcpy(stub + 6, &dst, 8);
    memcpy(src, stub, sizeof(stub));

    for (int i = MinLen; i < len; i++)
    {
        *(BYTE*)((uintptr_t)src + i) = 0x90;
    }

    VirtualProtect(src, len, dwOld, &dwOld);
    return (void*)((uintptr_t)pTrampoline);
}

bool GetD3D11SwapchainDeviceContext(void** pSwapchainTable, size_t Size_Swapchain, void** pDeviceTable, size_t Size_Device, void** pContextTable, size_t Size_Context)
{
    WNDCLASSEX wc{ 0 };
    wc.cbSize = sizeof(wc);
    wc.lpfnWndProc = DefWindowProc;
    wc.lpszClassName = TEXT("dummy class");

    if (!RegisterClassEx(&wc))
    {
        return false;
    }


    DXGI_SWAP_CHAIN_DESC swapChainDesc{ 0 };
    swapChainDesc.BufferCount = 1;
    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    swapChainDesc.OutputWindow = GetForegroundWindow();
    swapChainDesc.SampleDesc.Count = 1;
    swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
    swapChainDesc.Windowed = TRUE;

    D3D_FEATURE_LEVEL featureLevel;

    IDXGISwapChain* pDummySwapChain = nullptr;
    ID3D11Device* pDummyDevice = nullptr;
    ID3D11DeviceContext* pDummyContext = nullptr;

    HRESULT hr = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_REFERENCE, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &swapChainDesc, &pDummySwapChain, &pDummyDevice, &featureLevel, nullptr);
    if (FAILED(hr))
    {
        DestroyWindow(swapChainDesc.OutputWindow);
        UnregisterClass(wc.lpszClassName, GetModuleHandle(nullptr));
        return false;
    }

    if (pSwapchainTable && pDummySwapChain)
    {
        memcpy(pSwapchainTable, *reinterpret_cast<void***>(pDummySwapChain), Size_Swapchain);
    }

    if (pDeviceTable && pDummyDevice)
    {
        memcpy(pDeviceTable, *reinterpret_cast<void***>(pDummyDevice), Size_Device);
    }

    if (pContextTable && pDummyContext)
    {
        memcpy(pContextTable, *reinterpret_cast<void***>(pDummyContext), Size_Context);
    }

    SAFE_RELEASE(pDummySwapChain);
    SAFE_RELEASE(pDummyDevice);
    SAFE_RELEASE(pDummyContext);

    DestroyWindow(swapChainDesc.OutputWindow);
    UnregisterClass(wc.lpszClassName, GetModuleHandle(nullptr));

    return true;
}

void* SwapChain[18];
void* Device[40];
void* Context[108];

typedef HRESULT(__fastcall* tPresent)(IDXGISwapChain* pThis, UINT SyncInterval, UINT Flags);
tPresent oPresent = nullptr;

HRESULT __fastcall hkPresent(IDXGISwapChain* pThis, UINT SyncInterval, UINT Flags)
{
    return oPresent(pThis, SyncInterval, Flags);
}

DWORD WINAPI MainThread(HMODULE hModule)
{
    if (GetD3D11SwapchainDeviceContext(SwapChain, sizeof(SwapChain), Device, sizeof(Device), Context, sizeof(Context)))
    {
        oPresent = (tPresent)Tramp64(SwapChain[8], hkPresent, 19);
    }

    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)MainThread, hModule, 0, nullptr);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
Run Code Online (Sandbox Code Playgroud)

这是几个人的代码的组合:我、Broihon、Traxin 和 A200K