You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用MinHook正确Hook D3D12的CopyTextureRegion方法

代码失效原因

ID3D12GraphicsCommandList::CopyTextureRegion是COM接口的成员方法,不会以独立命名符号的形式从d3d12.dll导出,用GetProcAddress按函数名查询必然返回空地址。这类虚函数走接口虚表分发逻辑,和你之前成功Hook的D3D12CreateDevice这类全局导出函数的寻址逻辑完全不同。

正确Hook实现方案

用MinHook Hook COM成员方法的核心是直接修改虚表中对应位置的函数地址,操作流程如下:

  • 获取一个有效的ID3D12GraphicsCommandList实例指针:既可以用渲染流程中正常创建的CommandList对象,也可以临时创建临时CommandList对象取虚表地址(同版本接口的所有实例共享同一张虚函数表,临时对象用完释放即可)。
  • 从实例头部取出虚表指针,定位CopyTextureRegion方法在虚表中的对应偏移位置,用MinHook对该地址创建Hook即可。

参考实现代码:

// 原函数指针定义,签名、调用约定必须和原方法完全匹配
typedef HRESULT(WINAPI* CopyTextureRegion_Original)(
    ID3D12GraphicsCommandList* pThis,
    const D3D12_TEXTURE_COPY_LOCATION* pDst,
    UINT DstX,
    UINT DstY,
    UINT DstZ,
    const D3D12_TEXTURE_COPY_LOCATION* pSrc,
    const D3D12_BOX* pSrcBox
);
CopyTextureRegion_Original oCopyTextureRegion = nullptr;

// 自定义Hook函数
HRESULT WINAPI HK_CopyTextureRegion(
    ID3D12GraphicsCommandList* pThis,
    const D3D12_TEXTURE_COPY_LOCATION* pDst,
    UINT DstX,
    UINT DstY,
    UINT DstZ,
    const D3D12_TEXTURE_COPY_LOCATION* pSrc,
    const D3D12_BOX* pSrcBox)
{
    // 自定义Hook逻辑写在这里
    return oCopyTextureRegion(pThis, pDst, DstX, DstY, DstZ, pSrc, pSrcBox);
}

// Hook初始化逻辑
void InitCopyTextureRegionHook()
{
    // 假设你已经通过正常流程拿到了有效的D3D12设备指针pDevice
    ID3D12CommandAllocator* pTempAllocator = nullptr;
    ID3D12GraphicsCommandList* pTempCmdList = nullptr;
    // 创建临时资源用于取虚表
    pDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&pTempAllocator));
    pDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, pTempAllocator, nullptr, IID_PPV_ARGS(&pTempCmdList));

    // 取虚表指针:COM对象首地址存储的就是虚表指针
    void** pVTable = *reinterpret_cast<void***>(pTempCmdList);
    // 基类ID3D12GraphicsCommandList中CopyTextureRegion的固定虚表索引,若调试异常可自行核对虚表偏移
    constexpr int VTABLE_INDEX_CopyTextureRegion = 16;
    void* pTargetFunc = pVTable[VTABLE_INDEX_CopyTextureRegion];

    // 创建并启用Hook
    MH_CreateHook(pTargetFunc, &HK_CopyTextureRegion, reinterpret_cast<void**>(&oCopyTextureRegion));
    MH_EnableHook(pTargetFunc);

    // 释放临时资源
    pTempCmdList->Close();
    pTempCmdList->Release();
    pTempAllocator->Release();
}

注意事项

  • 虚表索引从0开始计数,需要把所有父接口(IUnknown、ID3D12Object、ID3D12DeviceChild、ID3D12CommandList)的方法全部计入偏移。COM接口二进制规范要求已发布的基类接口不能修改方法顺序,正常情况下上述索引在所有Win10/Win11版本中通用,如果调试发现调用异常,可以在调试器中直接查看虚表内存,匹配函数签名确认正确位置。
  • Hook函数的返回值、参数列表、调用约定必须和原方法完全一致,x86下COM方法默认使用__stdcall调用约定,x64下统一使用微软x64快速调用约定,签名不匹配会直接触发程序崩溃。
  • 同版本接口的所有实例共享同一张虚表,只需要修改一次虚表对应位置的函数地址,所有该接口实例调用CopyTextureRegion时都会走到Hook逻辑中,不需要给每个实例单独部署Hook。

内容的提问来源于stack exchange,提问作者Heinz Josef

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 06:18:24