Detours学习8 - D3D虚函数表
前言
关于Direct X
的拦截一般情况下才用类的虚表来完成,这种方法更通用,不区别所使用的操作系统。还有一种方法则是找出类其中一个函数的地址,然后通过IDA
等工具来找出其它函数的偏移量来完成,依据所查找的资料得出不同的操作系统可能会存在偏移量不一致的情况,最终会导致拦截失败。
在VS中的导出虚函数表
在DirectX SDK
中的相关例子中,打开对应的工程按如下方式操作:
-
打开项目属性页,
配置属性|C/C++|命令行|其它选项(D)
-
例如:
/d1 reportSingleClassLayoutIDirect3DDevice9
可以导出IDirect3DDevice9
的继承和虚函数表信息
关于DirectX 8/9
这两种版本是通过Direct3DCreate8
和Direct3DCreate9
来创建一个IDirect3D8*
和IDirect3D9*
的实例,然后通过创建的实例调用CreateDevice
函数来创建IDirect3DDevice8*
和IDirect3DDevice9*
的实例,最后通过这个创建的实例的各个成员方法来完成绘制,其中将数据最终输出是通过EndScense
函数来完成,所以在这两个版本中完成目标进程的写屏则就是对EndScense
函数的拦截。
-
通过
/d1 reportSingleClassLayoutIDirect3DDevice9
导出的IDirect3DDevice9
的虚表信息如下:IDirect3DDevice9::$vftable@: | &IDirect3DDevice9_meta | 0 0 | &IDirect3DDevice9::QueryInterface 1 | &IDirect3DDevice9::AddRef 2 | &IDirect3DDevice9::Release 3 | &IDirect3DDevice9::TestCooperativeLevel 4 | &IDirect3DDevice9::GetAvailableTextureMem 5 | &IDirect3DDevice9::EvictManagedResources 6 | &IDirect3DDevice9::GetDirect3D 7 | &IDirect3DDevice9::GetDeviceCaps 8 | &IDirect3DDevice9::GetDisplayMode 9 | &IDirect3DDevice9::GetCreationParameters 10 | &IDirect3DDevice9::SetCursorProperties 11 | &IDirect3DDevice9::SetCursorPosition 12 | &IDirect3DDevice9::ShowCursor 13 | &IDirect3DDevice9::CreateAdditionalSwapChain 14 | &IDirect3DDevice9::GetSwapChain 15 | &IDirect3DDevice9::GetNumberOfSwapChains 16 | &IDirect3DDevice9::Reset 17 | &IDirect3DDevice9::Present 18 | &IDirect3DDevice9::GetBackBuffer 19 | &IDirect3DDevice9::GetRasterStatus 20 | &IDirect3DDevice9::SetDialogBoxMode 21 | &IDirect3DDevice9::SetGammaRamp 22 | &IDirect3DDevice9::GetGammaRamp 23 | &IDirect3DDevice9::CreateTexture 24 | &IDirect3DDevice9::CreateVolumeTexture 25 | &IDirect3DDevice9::CreateCubeTexture 26 | &IDirect3DDevice9::CreateVertexBuffer 27 | &IDirect3DDevice9::CreateIndexBuffer 28 | &IDirect3DDevice9::CreateRenderTarget 29 | &IDirect3DDevice9::CreateDepthStencilSurface 30 | &IDirect3DDevice9::UpdateSurface 31 | &IDirect3DDevice9::UpdateTexture 32 | &IDirect3DDevice9::GetRenderTargetData 33 | &IDirect3DDevice9::GetFrontBufferData 34 | &IDirect3DDevice9::StretchRect 35 | &IDirect3DDevice9::ColorFill 36 | &IDirect3DDevice9::CreateOffscreenPlainSurface 37 | &IDirect3DDevice9::SetRenderTarget 38 | &IDirect3DDevice9::GetRenderTarget 39 | &IDirect3DDevice9::SetDepthStencilSurface 40 | &IDirect3DDevice9::GetDepthStencilSurface 41 | &IDirect3DDevice9::BeginScene 42 | &IDirect3DDevice9::EndScene 43 | &IDirect3DDevice9::Clear 44 | &IDirect3DDevice9::SetTransform 45 | &IDirect3DDevice9::GetTransform 46 | &IDirect3DDevice9::MultiplyTransform 47 | &IDirect3DDevice9::SetViewport 48 | &IDirect3DDevice9::GetViewport 49 | &IDirect3DDevice9::SetMaterial 50 | &IDirect3DDevice9::GetMaterial 51 | &IDirect3DDevice9::SetLight 52 | &IDirect3DDevice9::GetLight 53 | &IDirect3DDevice9::LightEnable 54 | &IDirect3DDevice9::GetLightEnable 55 | &IDirect3DDevice9::SetClipPlane 56 | &IDirect3DDevice9::GetClipPlane 57 | &IDirect3DDevice9::SetRenderState 58 | &IDirect3DDevice9::GetRenderState 59 | &IDirect3DDevice9::CreateStateBlock 60 | &IDirect3DDevice9::BeginStateBlock 61 | &IDirect3DDevice9::EndStateBlock 62 | &IDirect3DDevice9::SetClipStatus 63 | &IDirect3DDevice9::GetClipStatus 64 | &IDirect3DDevice9::GetTexture 65 | &IDirect3DDevice9::SetTexture 66 | &IDirect3DDevice9::GetTextureStageState 67 | &IDirect3DDevice9::SetTextureStageState 68 | &IDirect3DDevice9::GetSamplerState 69 | &IDirect3DDevice9::SetSamplerState 70 | &IDirect3DDevice9::ValidateDevice 71 | &IDirect3DDevice9::SetPaletteEntries 72 | &IDirect3DDevice9::GetPaletteEntries 73 | &IDirect3DDevice9::SetCurrentTexturePalette 74 | &IDirect3DDevice9::GetCurrentTexturePalette 75 | &IDirect3DDevice9::SetScissorRect 76 | &IDirect3DDevice9::GetScissorRect 77 | &IDirect3DDevice9::SetSoftwareVertexProcessing 78 | &IDirect3DDevice9::GetSoftwareVertexProcessing 79 | &IDirect3DDevice9::SetNPatchMode 80 | &IDirect3DDevice9::GetNPatchMode 81 | &IDirect3DDevice9::DrawPrimitive 82 | &IDirect3DDevice9::DrawIndexedPrimitive 83 | &IDirect3DDevice9::DrawPrimitiveUP 84 | &IDirect3DDevice9::DrawIndexedPrimitiveUP 85 | &IDirect3DDevice9::ProcessVertices 86 | &IDirect3DDevice9::CreateVertexDeclaration 87 | &IDirect3DDevice9::SetVertexDeclaration 88 | &IDirect3DDevice9::GetVertexDeclaration 89 | &IDirect3DDevice9::SetFVF 90 | &IDirect3DDevice9::GetFVF 91 | &IDirect3DDevice9::CreateVertexShader 92 | &IDirect3DDevice9::SetVertexShader 93 | &IDirect3DDevice9::GetVertexShader 94 | &IDirect3DDevice9::SetVertexShaderConstantF 95 | &IDirect3DDevice9::GetVertexShaderConstantF 96 | &IDirect3DDevice9::SetVertexShaderConstantI 97 | &IDirect3DDevice9::GetVertexShaderConstantI 98 | &IDirect3DDevice9::SetVertexShaderConstantB 99 | &IDirect3DDevice9::GetVertexShaderConstantB 100 | &IDirect3DDevice9::SetStreamSource 101 | &IDirect3DDevice9::GetStreamSource 102 | &IDirect3DDevice9::SetStreamSourceFreq 103 | &IDirect3DDevice9::GetStreamSourceFreq 104 | &IDirect3DDevice9::SetIndices 105 | &IDirect3DDevice9::GetIndices 106 | &IDirect3DDevice9::CreatePixelShader 107 | &IDirect3DDevice9::SetPixelShader 108 | &IDirect3DDevice9::GetPixelShader 109 | &IDirect3DDevice9::SetPixelShaderConstantF 110 | &IDirect3DDevice9::GetPixelShaderConstantF 111 | &IDirect3DDevice9::SetPixelShaderConstantI 112 | &IDirect3DDevice9::GetPixelShaderConstantI 113 | &IDirect3DDevice9::SetPixelShaderConstantB 114 | &IDirect3DDevice9::GetPixelShaderConstantB 115 | &IDirect3DDevice9::DrawRectPatch 116 | &IDirect3DDevice9::DrawTriPatch 117 | &IDirect3DDevice9::DeletePatch 118 | &IDirect3DDevice9::CreateQuery -
从导出的虚表可以找到我们感兴趣的函数
EndScense
的索引是42
,可以根据IDirect3DDevice*
指向的首地址做偏移到得EndScense
的地址void** pVtbl = *reinterpret_cast<void***>(pDevice); TureEndScense = (TEndScense)pVtbl[42];
关于DirectX 10/11
这两个版本中引入了IDXGISwapChain
的对象,最终输出是在此对象中的Present
函数中完成的,那么要完成目标进程的写屏则是对它进行拦截
-
通过
/d1 reportSingleClassLayoutIDXGISwapChain
导出的IDXGISwapChain
的虚函数表的信息如下:class IDXGISwapChain size(4) : > +-- - | +-- - (base class IDXGIDeviceSubObject) | | +-- - (base class IDXGIObject) | | | +-- - (base class IUnknown) | | | | {vfptr} | | | +-- - | | +-- - | +-- - +-- - IDXGISwapChain::$vftable@: | &IDXGISwapChain_meta | 0 0 | &IUnknown::QueryInterface 1 | &IUnknown::AddRef 2 | &IUnknown::Release 3 | &IDXGIObject::SetPrivateData 4 | &IDXGIObject::SetPrivateDataInterface 5 | &IDXGIObject::GetPrivateData 6 | &IDXGIObject::GetParent 7 | &IDXGIDeviceSubObject::GetDevice 8 | &IDXGISwapChain::Present 9 | &IDXGISwapChain::GetBuffer 10 | &IDXGISwapChain::SetFullscreenState 11 | &IDXGISwapChain::GetFullscreenState 12 | &IDXGISwapChain::GetDesc 13 | &IDXGISwapChain::ResizeBuffers 14 | &IDXGISwapChain::ResizeTarget 15 | &IDXGISwapChain::GetContainingOutput 16 | &IDXGISwapChain::GetFrameStatistics 17 | &IDXGISwapChain::GetLastPresentCount -
通过导出的虚表我们可以找出
Present
的索引为8,Dx10、Dx11
在这个类上面没有区别,所以可以通过偏移得到此函数的地址:void** pSwapChainVtbl = *reinterpret_cast<void***>(swapChain); TruePresent = (PF_Present)pSwapChainVtbl[8]; -
通过上面的导出命令同时会导出
ID3D11DeviceContext
的虚表,它和ID3D10DeviceContext
是有一些区别的,拦截它们之中的函数则能对目标进程做更丰富的二次绘制处理,下面列出ID3D11DeviceContext
的虚表:class ID3D11DeviceContext size(4): +--- | +--- (base class ID3D11DeviceChild) | | +--- (base class IUnknown) | | | {vfptr} | | +--- | +--- +--- ID3D11DeviceContext::$vftable@: | &ID3D11DeviceContext_meta | 0 0 | &IUnknown::QueryInterface 1 | &IUnknown::AddRef 2 | &IUnknown::Release 3 | &ID3D11DeviceChild::GetDevice 4 | &ID3D11DeviceChild::GetPrivateData 5 | &ID3D11DeviceChild::SetPrivateData 6 | &ID3D11DeviceChild::SetPrivateDataInterface 7 | &ID3D11DeviceContext::VSSetConstantBuffers 8 | &ID3D11DeviceContext::PSSetShaderResources 9 | &ID3D11DeviceContext::PSSetShader 10 | &ID3D11DeviceContext::PSSetSamplers 11 | &ID3D11DeviceContext::VSSetShader 12 | &ID3D11DeviceContext::DrawIndexed 13 | &ID3D11DeviceContext::Draw 14 | &ID3D11DeviceContext::Map 15 | &ID3D11DeviceContext::Unmap 16 | &ID3D11DeviceContext::PSSetConstantBuffers 17 | &ID3D11DeviceContext::IASetInputLayout 18 | &ID3D11DeviceContext::IASetVertexBuffers 19 | &ID3D11DeviceContext::IASetIndexBuffer 20 | &ID3D11DeviceContext::DrawIndexedInstanced 21 | &ID3D11DeviceContext::DrawInstanced 22 | &ID3D11DeviceContext::GSSetConstantBuffers 23 | &ID3D11DeviceContext::GSSetShader 24 | &ID3D11DeviceContext::IASetPrimitiveTopology 25 | &ID3D11DeviceContext::VSSetShaderResources 26 | &ID3D11DeviceContext::VSSetSamplers 27 | &ID3D11DeviceContext::Begin 28 | &ID3D11DeviceContext::End 29 | &ID3D11DeviceContext::GetData 30 | &ID3D11DeviceContext::SetPredication 31 | &ID3D11DeviceContext::GSSetShaderResources 32 | &ID3D11DeviceContext::GSSetSamplers 33 | &ID3D11DeviceContext::OMSetRenderTargets 34 | &ID3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews 35 | &ID3D11DeviceContext::OMSetBlendState 36 | &ID3D11DeviceContext::OMSetDepthStencilState 37 | &ID3D11DeviceContext::SOSetTargets 38 | &ID3D11DeviceContext::DrawAuto 39 | &ID3D11DeviceContext::DrawIndexedInstancedIndirect 40 | &ID3D11DeviceContext::DrawInstancedIndirect 41 | &ID3D11DeviceContext::Dispatch 42 | &ID3D11DeviceContext::DispatchIndirect 43 | &ID3D11DeviceContext::RSSetState 44 | &ID3D11DeviceContext::RSSetViewports 45 | &ID3D11DeviceContext::RSSetScissorRects 46 | &ID3D11DeviceContext::CopySubresourceRegion 47 | &ID3D11DeviceContext::CopyResource 48 | &ID3D11DeviceContext::UpdateSubresource 49 | &ID3D11DeviceContext::CopyStructureCount 50 | &ID3D11DeviceContext::ClearRenderTargetView 51 | &ID3D11DeviceContext::ClearUnorderedAccessViewUint 52 | &ID3D11DeviceContext::ClearUnorderedAccessViewFloat 53 | &ID3D11DeviceContext::ClearDepthStencilView 54 | &ID3D11DeviceContext::GenerateMips 55 | &ID3D11DeviceContext::SetResourceMinLOD 56 | &ID3D11DeviceContext::GetResourceMinLOD 57 | &ID3D11DeviceContext::ResolveSubresource 58 | &ID3D11DeviceContext::ExecuteCommandList 59 | &ID3D11DeviceContext::HSSetShaderResources 60 | &ID3D11DeviceContext::HSSetShader 61 | &ID3D11DeviceContext::HSSetSamplers 62 | &ID3D11DeviceContext::HSSetConstantBuffers 63 | &ID3D11DeviceContext::DSSetShaderResources 64 | &ID3D11DeviceContext::DSSetShader 65 | &ID3D11DeviceContext::DSSetSamplers 66 | &ID3D11DeviceContext::DSSetConstantBuffers 67 | &ID3D11DeviceContext::CSSetShaderResources 68 | &ID3D11DeviceContext::CSSetUnorderedAccessViews 69 | &ID3D11DeviceContext::CSSetShader 70 | &ID3D11DeviceContext::CSSetSamplers 71 | &ID3D11DeviceContext::CSSetConstantBuffers 72 | &ID3D11DeviceContext::VSGetConstantBuffers 73 | &ID3D11DeviceContext::PSGetShaderResources 74 | &ID3D11DeviceContext::PSGetShader 75 | &ID3D11DeviceContext::PSGetSamplers 76 | &ID3D11DeviceContext::VSGetShader 77 | &ID3D11DeviceContext::PSGetConstantBuffers 78 | &ID3D11DeviceContext::IAGetInputLayout 79 | &ID3D11DeviceContext::IAGetVertexBuffers 80 | &ID3D11DeviceContext::IAGetIndexBuffer 81 | &ID3D11DeviceContext::GSGetConstantBuffers 82 | &ID3D11DeviceContext::GSGetShader 83 | &ID3D11DeviceContext::IAGetPrimitiveTopology 84 | &ID3D11DeviceContext::VSGetShaderResources 85 | &ID3D11DeviceContext::VSGetSamplers 86 | &ID3D11DeviceContext::GetPredication 87 | &ID3D11DeviceContext::GSGetShaderResources 88 | &ID3D11DeviceContext::GSGetSamplers 89 | &ID3D11DeviceContext::OMGetRenderTargets 90 | &ID3D11DeviceContext::OMGetRenderTargetsAndUnorderedAccessViews 91 | &ID3D11DeviceContext::OMGetBlendState 92 | &ID3D11DeviceContext::OMGetDepthStencilState 93 | &ID3D11DeviceContext::SOGetTargets 94 | &ID3D11DeviceContext::RSGetState 95 | &ID3D11DeviceContext::RSGetViewports 96 | &ID3D11DeviceContext::RSGetScissorRects 97 | &ID3D11DeviceContext::HSGetShaderResources 98 | &ID3D11DeviceContext::HSGetShader 99 | &ID3D11DeviceContext::HSGetSamplers 100 | &ID3D11DeviceContext::HSGetConstantBuffers 101 | &ID3D11DeviceContext::DSGetShaderResources 102 | &ID3D11DeviceContext::DSGetShader 103 | &ID3D11DeviceContext::DSGetSamplers 104 | &ID3D11DeviceContext::DSGetConstantBuffers 105 | &ID3D11DeviceContext::CSGetShaderResources 106 | &ID3D11DeviceContext::CSGetUnorderedAccessViews 107 | &ID3D11DeviceContext::CSGetShader 108 | &ID3D11DeviceContext::CSGetSamplers 109 | &ID3D11DeviceContext::CSGetConstantBuffers 110 | &ID3D11DeviceContext::ClearState 111 | &ID3D11DeviceContext::Flush 112 | &ID3D11DeviceContext::GetType 113 | &ID3D11DeviceContext::GetContextFlags 114 | &ID3D11DeviceContext::FinishCommandList
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗