DirectX和Direct3D教程和源代码

本文介绍了在游戏开发中如何使用DirectX,特别是Direct3D9和Direct3D11进行钩子设置。推荐使用创建虚拟设备的方法,复制虚函数表以实现通用的钩子功能,而非依赖于模式扫描。文中详细阐述了这一技术,并提供了适用于x86和x64平台的函数复制示例。
摘要由CSDN通过智能技术生成

当使用DirectX attack游戏时,你需要钩住D3DDevice的某些成员函数并知道它的地址。许多人会使用模式扫描来获取功能或设备的地址。这不是一个通用的方法。
首选的、推荐的和最好的方法是创建自己的虚拟设备,复制虚函数表项,这样就可以钩住函数。

虚拟设备的方法
这种方法是100倍的更好和通用的。你创建你自己的设备对象,它获得你可以复制的vTable地址。这是一个由所有设备对象共享的vTable。你现在可以使用常规钩子或vTable钩子,它们会影响游戏的设备。您还可以通过连接这些函数并从eax寄存器中抓取“this指针”来获取设备地址。
下面是我复制d3d9和d3d11接口的虚函数。当然可以在x86和x64上工作。

Direct3d9

static HWND window;

BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam)
{
    DWORD wndProcId;
    GetWindowThreadProcessId(handle, &wndProcId);

    if (GetCurrentProcessId() != wndProcId)
        return TRUE; // skip to next window

    window = handle;
    return FALSE; // window found abort search
}

HWND GetProcessWindow()
{
    window = NULL;
    EnumWindows(EnumWindowsCallback, NULL);
    return window;
}

bool GetD3D9Device(void ** pTable, size_t Size)
{
    if (!pTable)
        return false;

    IDirect3D9 * pD3D = Direct3DCreate9(D3D_SDK_VERSION);

    if (!pD3D)
        return false;

    IDirect3DDevice9 * pDummyDevice = NULL;

    // options to create dummy device
    D3DPRESENT_PARAMETERS d3dpp = {};
    d3dpp.Windowed = false;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = GetProcessWindow();

    HRESULT dummyDeviceCreated = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice);

    if (dummyDeviceCreated != S_OK)
    {
        // may fail in windowed fullscreen mode, trying again with windowed mode
        d3dpp.Windowed = !d3dpp.Windowed;

        dummyDeviceCreated = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice);

        if (dummyDeviceCreated != S_OK)
        {
            pD3D->Release();
            return false;
        }
    }

    memcpy(pTable, *reinterpret_cast<void***>(pDummyDevice), Size);

    pDummyDevice->Release();
    pD3D->Release();
    return true;
}

void * d3d9Device[119];
if (GetD3D9Device(d3d9Device, sizeof(d3d9Device)))
{
    //hook stuff using the dumped addresses
}

Direct3d11

template <class T>
void SAFE_RELEASE(T * t)
{
    if (t)
    {
        t->Release();
    }
}

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

    HWND hWnd = CreateWindow(wc.lpszClassName, TEXT(""), WS_DISABLED, 0, 0, 0, 0, NULL, NULL, NULL, nullptr);

    DXGI_SWAP_CHAIN_DESC swapChainDesc{ 0 };
    swapChainDesc.BufferCount                    = 1;
    swapChainDesc.BufferDesc.Format                = DXGI_FORMAT_R8G8B8A8_UNORM;
    swapChainDesc.BufferUsage                    = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapChainDesc.OutputWindow                    = hWnd;
    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[] =
    {
        D3D_FEATURE_LEVEL_9_1,
        D3D_FEATURE_LEVEL_9_2,
        D3D_FEATURE_LEVEL_9_3,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_11_1,
        D3D_FEATURE_LEVEL_12_0,
        D3D_FEATURE_LEVEL_12_1
    };
   
    IDXGISwapChain        * pDummySwapChain    = nullptr;
    ID3D11Device        * pDummyDevice        = nullptr;
    ID3D11DeviceContext * pDummyContext        = nullptr;

    if (FAILED(D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, featureLevel, 1, D3D11_SDK_VERSION, &swapChainDesc, &pDummySwapChain, &pDummyDevice, nullptr, &pDummyContext)))
    {
        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];

if (GetD3D11SwapchainDeviceContext(SwapChain, sizeof(SwapChain), Device, sizeof(Device), Context, sizeof(Context)))
{
    //hook stuff using the dumped addresses
}

通用钩子dxd9 - dxd12, opengl和vulkan

#include "kiero.h"
#include <d3d9.h>
#include <MinHook.h>
#include <Windows.h>

typedef long(__stdcall* EndScene)(LPDIRECT3DDEVICE);
EndScene oEndScene = NULL;

long __stdcall hkEndScene(LPDIRECT3DDEVICE pDevice)
{
  static bool init = false;
  if (!init)
  {
    MessageBox(0, "Boom! It's works!", "Kiero", MB_OK);
    init = true;
  }

  return oEndScene(pDevice);
}

int kieroExampleThread()
{
  if (kiero::init(kiero::RenderType::D3D9) == kiero::Status::Success)
  {
    kiero::bind(42, oEndScene, hkEndScene);
  }

  return 0;
}

BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID)
{
  DisableThreadLibraryCalls(hInstance);

  switch (fdwReason)
  {
    case DLL_PROCESS_ATTACH:
      CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)kieroExampleThread, NULL, 0, NULL);
      break;
  }

  return TRUE;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Meta.Qing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值