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

如何从ID3D11PixelShader对象获取已编译的像素着色器字节码

D3D11 从ID3D11PixelShader获取着色器字节码方案

D3D11 原生公开的ID3D11PixelShader接口没有提供类似D3D9 GetFunction的直接获取字节码的方法,可通过以下两种方案实现需求:


方案1:Hook ID3D11Device::CreatePixelShader 缓存映射(兼容性最高,推荐逆向场景使用)

  • D3D11所有像素着色器实例都通过ID3D11Device::CreatePixelShader接口创建,调用时的前两个参数分别是原始着色器字节码指针、字节码长度,第四个参数是输出的ID3D11PixelShader对象指针。
  • 你可以Hook这个创建接口,在每次着色器创建时将「着色器对象地址 -> 字节码副本」的映射存入自定义哈希表,后续拿到任意ID3D11PixelShader实例直接查表即可获取对应字节码。
  • 该方案兼容所有Windows版本,不依赖运行时内部实现,稳定性最高,是游戏逆向、Mod开发领域的通用实现。

方案2:通过私有GUID直接读取字节码(依赖运行时实现,兼容性一般)

微软D3D11运行时内部会将原始着色器字节码存储在着色器对象的私有数据区,可通过指定GUID调用ID3D11DeviceChild::GetPrivateData方法读取:

  1. 首先定义私有GUID:GUID_D3D11_SHADER_BYTECODE = {0x3d4dd49e, 0x5ed3, 0x4E45, {0xb5, 0xa1, 0xf2, 0x55, 0xc5, 0x04, 0x04, 0x8f}}
  2. 调用GetPrivateData读取字节码,示例代码如下:
UINT bytecodeSize = 0;
// 第一次调用查询需要的缓冲区大小
HRESULT hr = pPixelShader->GetPrivateData(GUID_D3D11_SHADER_BYTECODE, &bytecodeSize, nullptr);
if (SUCCEEDED(hr) && bytecodeSize > 0) {
    void* pBytecode = malloc(bytecodeSize);
    // 第二次调用读取字节码内容
    hr = pPixelShader->GetPrivateData(GUID_D3D11_SHADER_BYTECODE, &bytecodeSize, pBytecode);
    if (SUCCEEDED(hr)) {
        // 读取成功,pBytecode即为原始DXBC格式的着色器字节码
    }
    free(pBytecode);
}
  • 该方案依赖D3D11运行时的内部实现,部分旧版本Windows、定制版系统可能读取失败,仅建议作为辅助方案使用。

附加说明

拿到DXBC格式的字节码后,可直接调用d3dcompiler_xx.dll导出的D3DDisassemble函数反编译为可读的HLSL汇编代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 13:24:03