从哪里开始创建D3D11挂钩以制作游戏画面?

时间:2018-12-19 00:01:54

标签: c++ directx overlay directx-11

我目前正在从事我的第一个D3D项目,该项目涉及为游戏创建一个覆盖图,以便向用户提供实时信息。实际的数据采集已处理,并将通过消息系统发送。目前,我有该程序可用于无边界全屏模式,并且正在调整它以使其在窗口模式下按比例缩放(以确保无论大小,一切都指向正确的位置)。该应用程序是游戏的父母,但是,当游戏进入真正的全屏模式时,一切都会崩溃。研究表明,据我所知,我需要创建一个假的.dll,并将其插入游戏的本地目录。该.dll将打开,而不是它正在寻找的实际DirectX,我可以在其中完成所需的图形。

要回答一些潜在的问题,我没有直接访问该游戏的权限,尽管对于有问题的游戏,开发人员可以这样做,但我希望它不会受到反作弊的惩罚软件。此外,我想将性能降到最低,因此目前重叠式广告的FPS相当低(〜10fps)。

在此先感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

这是我刚刚使用过的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;
}

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