├── ss.png ├── GH_D3D11_Hook ├── shadez.h ├── GH_D3D11_Hook.vcxproj.filters ├── D3D_VMT_Indices.h ├── GH_D3D11_Hook.vcxproj └── DllMain.cpp ├── LICENSE ├── GH_D3D11_Hook.sln ├── .gitattributes ├── .gitignore └── README.md /ss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guidedhacking/GH_D3D11_Hook/HEAD/ss.png -------------------------------------------------------------------------------- /GH_D3D11_Hook/shadez.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | constexpr const char* szShadez = R"( 4 | // Constant buffer 5 | cbuffer ConstantBuffer : register(b0) 6 | { 7 | matrix projection; 8 | } 9 | 10 | // PSI (PixelShaderInput) 11 | struct PSI 12 | { 13 | float4 pos : SV_POSITION; 14 | float4 color : COLOR; 15 | }; 16 | 17 | // VertexShader 18 | PSI VS( float4 pos : POSITION, float4 color : COLOR ) 19 | { 20 | PSI psi; 21 | psi.color = color; 22 | pos = mul( pos, projection ); 23 | psi.pos = pos; 24 | return psi; 25 | } 26 | 27 | // PixelShader 28 | float4 PS(PSI psi) : SV_TARGET 29 | { 30 | return psi.color; 31 | } 32 | )"; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GuidedHacking.com Source Available License 2 | Version 1, 05-14-2025 3 | 4 | Disclaimer: 5 | This project contains code developed and published by Guided Hacking LLC. 6 | GuidedHacking® sells educational content including source codes like this. 7 | 8 | GuidedHacking® - The Game Hacking Bible® - © 2025 Guided Hacking LLC. All Rights Reserved. 9 | 10 | Licensed Materials: 11 | Source code, compiled binaries, documentation, image and video assets, including original, modified or derivative versions. 12 | 13 | Limited Use License: 14 | 1. You may use these materials only in non-commercial private, personal projects. 15 | 2. Distribution of these materials in any form, including compiled, modified, or derivative works is not permitted. 16 | 17 | This software is provided AS IS without any warranties, express or implied, and Guided Hacking LLC is not liable for any damages arising from the use of these materials. 18 | 19 | Any rights not expressly granted by the license are reserved by Guided Hacking LLC. -------------------------------------------------------------------------------- /GH_D3D11_Hook/GH_D3D11_Hook.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | Header Files 28 | 29 | 30 | -------------------------------------------------------------------------------- /GH_D3D11_Hook.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GH_D3D11_Hook", "GH_D3D11_Hook\GH_D3D11_Hook.vcxproj", "{A8FB3836-0DEF-44D2-9E70-F4BA3360E43F}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {A8FB3836-0DEF-44D2-9E70-F4BA3360E43F}.Debug|x64.ActiveCfg = Debug|x64 17 | {A8FB3836-0DEF-44D2-9E70-F4BA3360E43F}.Debug|x64.Build.0 = Debug|x64 18 | {A8FB3836-0DEF-44D2-9E70-F4BA3360E43F}.Debug|x86.ActiveCfg = Debug|Win32 19 | {A8FB3836-0DEF-44D2-9E70-F4BA3360E43F}.Debug|x86.Build.0 = Debug|Win32 20 | {A8FB3836-0DEF-44D2-9E70-F4BA3360E43F}.Release|x64.ActiveCfg = Release|x64 21 | {A8FB3836-0DEF-44D2-9E70-F4BA3360E43F}.Release|x64.Build.0 = Release|x64 22 | {A8FB3836-0DEF-44D2-9E70-F4BA3360E43F}.Release|x86.ActiveCfg = Release|Win32 23 | {A8FB3836-0DEF-44D2-9E70-F4BA3360E43F}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {F249AAB7-C986-4D42-8ACF-B0BE37FD2DD7} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /GH_D3D11_Hook/D3D_VMT_Indices.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum class IDXGISwapChainVMT { 4 | QueryInterface, 5 | AddRef, 6 | Release, 7 | SetPrivateData, 8 | SetPrivateDataInterface, 9 | GetPrivateData, 10 | GetParent, 11 | GetDevice, 12 | Present, 13 | GetBuffer, 14 | SetFullscreenState, 15 | GetFullscreenState, 16 | GetDesc, 17 | ResizeBuffers, 18 | ResizeTarget, 19 | GetContainingOutput, 20 | GetFrameStatistics, 21 | GetLastPresentCount, 22 | }; 23 | 24 | enum class ID3D11DeviceVMT { 25 | QueryInterface, 26 | AddRef, 27 | Release, 28 | CreateVideoDecoder, 29 | CreateVideoProcessor, 30 | CreateAuthenticatedChannel, 31 | CreateCryptoSession, 32 | CreateVideoDecoderOutputView, 33 | CreateVideoProcessorInputView, 34 | CreateVideoProcessorOutputView, 35 | CreateVideoProcessorEnumerator, 36 | GetVideoDecoderProfileCount, 37 | GetVideoDecoderProfile, 38 | CheckVideoDecoderFormat, 39 | GetVideoDecoderConfigCount, 40 | GetVideoDecoderConfig, 41 | GetContentProtectionCaps, 42 | CheckCryptoKeyExchange, 43 | SetPrivateData, 44 | SetPrivateDataInterface, 45 | }; 46 | 47 | enum class ID3D11DeviceContextVMT { 48 | QueryInterface, 49 | AddRef, 50 | Release, 51 | GetDevice, 52 | GetPrivateData, 53 | SetPrivateData, 54 | SetPrivateDataInterface, 55 | VSSetConstantBuffers, 56 | PSSetShaderResources, 57 | PSSetShader, 58 | PSSetSamplers, 59 | VSSetShader, 60 | DrawIndexed, 61 | Draw, 62 | Map, 63 | Unmap, 64 | PSSetConstantBuffers, 65 | IASetInputLayout, 66 | IASetVertexBuffers, 67 | IASetIndexBuffer, 68 | DrawIndexedInstanced, 69 | DrawInstanced, 70 | GSSetConstantBuffers, 71 | GSSetShader, 72 | IASetPrimitiveTopology, 73 | VSSetShaderResources, 74 | VSSetSamplers, 75 | Begin, 76 | End, 77 | GetData, 78 | SetPredication, 79 | GSSetShaderResources, 80 | GSSetSamplers, 81 | OMSetRenderTargets, 82 | OMSetRenderTargetsAndUnorderedAccessViews, 83 | OMSetBlendState, 84 | OMSetDepthStencilState, 85 | SOSetTargets, 86 | DrawAuto, 87 | DrawIndexedInstancedIndirect, 88 | DrawInstancedIndirect, 89 | Dispatch, 90 | DispatchIndirect, 91 | RSSetState, 92 | RSSetViewports, 93 | RSSetScissorRects, 94 | CopySubresourceRegion, 95 | CopyResource, 96 | UpdateSubresource, 97 | CopyStructureCount, 98 | ClearRenderTargetView, 99 | ClearUnorderedAccessViewUint, 100 | ClearUnorderedAccessViewFloat, 101 | ClearDepthStencilView, 102 | GenerateMips, 103 | SetResourceMinLOD, 104 | GetResourceMinLOD, 105 | ResolveSubresource, 106 | ExecuteCommandList, 107 | HSSetShaderResources, 108 | HSSetShader, 109 | HSSetSamplers, 110 | HSSetConstantBuffers, 111 | DSSetShaderResources, 112 | DSSetShader, 113 | DSSetSamplers, 114 | DSSetConstantBuffers, 115 | CSSetShaderResources, 116 | CSSetUnorderedAccessViews, 117 | CSSetShader, 118 | CSSetSamplers, 119 | CSSetConstantBuffers, 120 | VSGetConstantBuffers, 121 | PSGetShaderResources, 122 | PSGetShader, 123 | PSGetSamplers, 124 | VSGetShader, 125 | PSGetConstantBuffers, 126 | IAGetInputLayout, 127 | IAGetVertexBuffers, 128 | IAGetIndexBuffer, 129 | GSGetConstantBuffers, 130 | GSGetShader, 131 | IAGetPrimitiveTopology, 132 | VSGetShaderResources, 133 | VSGetSamplers, 134 | GetPredication, 135 | GSGetShaderResources, 136 | GSGetSamplers, 137 | OMGetRenderTargets, 138 | OMGetRenderTargetsAndUnorderedAccessViews, 139 | OMGetBlendState, 140 | OMGetDepthStencilState, 141 | SOGetTargets, 142 | RSGetState, 143 | RSGetViewports, 144 | RSGetScissorRects, 145 | HSGetShaderResources, 146 | HSGetShader, 147 | HSGetSamplers, 148 | HSGetConstantBuffers, 149 | DSGetShaderResources, 150 | DSGetShader, 151 | DSGetSamplers, 152 | DSGetConstantBuffers, 153 | CSGetShaderResources, 154 | CSGetUnorderedAccessViews, 155 | CSGetShader, 156 | CSGetSamplers, 157 | CSGetConstantBuffers, 158 | ClearState, 159 | Flush, 160 | GetType, 161 | GetContextFlags, 162 | FinishCommandList, 163 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GH D3D11 Hook 2 | 3 | Barebones D3D11 hook. 4 | x86/x64 Compatible 5 | 6 | ![screenshot](https://github.com/guided-hacking/GH_D3D11_Hook/blob/master/ss.png "FarCry5 Example") 7 | 8 | [BareBones D3D11 Hook Thread on GH](https://guidedhacking.com/threads/d3d11-barebones-hook-poc.11939/) 9 | 10 | This is about the simplest example I could create for hooking DirectX 11. 11 | The code is heavily commented and doesn't rely on any external libraries. 12 | As long as you have a recent version of the Windows SDK then this code should run. 13 | 14 | The example is a DLL that you inject into a game using DirectX 11 and it should render a triangle in the top left corner of the screen. 15 | 16 | The code creates a dummy device and swapchain to get the address of Present out of the dummy swapchain's virtual method table. Then we create a simple trampoline hook to detour Present and render our triangle. 17 | 18 | While the code isn't extremely elegant, it's not meant to be. 19 | This is just a simple PoC to demonstrate one way, a fairly decent way imo, of hooking 20 | direct3d 11 and rendering our own simple geometry. 21 | 22 | This project is a Direct3D 11 hook, which is essentially a way to intercept and manipulate the rendering of 3D graphics in a game or other 3D application. This is a powerful tool for game modding, reverse engineering, and cheat development. 23 | 24 | Features 25 | -------- 26 | 27 | The GH_D3D11_Hook project provides the following features: 28 | 29 | 1. DirectX Hooking: This project uses a technique known as "hooking" to intercept the DirectX 11 API calls, allowing you to manipulate the rendering process. 30 | 31 | 2. Shader Compilation: The project includes functionality for compiling shaders, which are programs that run on the GPU to perform graphics calculations. 32 | 33 | 3. Rendering: The project includes code for rendering a basic triangle using the hooked DirectX 11 API. This serves as an example of how you can use the hook to modify the rendering process. 34 | 35 | 4. Memory Management: The project includes robust memory management, with safe release macros for DirectX objects. 36 | 37 | Code Overview 38 | ------------- 39 | 40 | The main file of the project is `DllMain.cpp`, which contains the implementation of the DirectX 11 hook. Here's a brief overview of some key parts of the code: 41 | 42 | - `hkPresent`: This is the hooked version of the `Present` function, which is a DirectX function that updates the screen with the rendered frame. This function is where the magic happens: it's where we intercept the `Present` call and add our own rendering code. 43 | 44 | - `HookD3D`: This function sets up the hook by creating a dummy DirectX device and swap chain, getting the virtual method table (VMT) of the swap chain, and replacing the `Present` function in the VMT with our own function. 45 | 46 | - `InitD3DHook`: This function initializes the hook by getting the DirectX device and context, setting up the render target view, and initializing the shaders and buffers for rendering. 47 | 48 | - `Render`: This function is where we add our own rendering code. In this case, it renders a simple triangle. 49 | 50 | - `CompileShader`: This function compiles a shader from source code. 51 | 52 | - `FindMainWindow` and `EnumWindowsCallback`: These functions are used to find the main window of the process, which is needed to create the dummy DirectX device and swap chain. 53 | 54 | 55 | Frequently Asked Questions 56 | -------------------------- 57 | 58 | Q: What is DirectX? 59 | 60 | A: DirectX is a collection of APIs (Application Programming Interfaces) for handling tasks related to multimedia, especially game programming and video, on Microsoft platforms. 61 | 62 | Q: What is a DirectX hook? 63 | 64 | A: A DirectX hook is a technique that allows you to intercept and manipulate the DirectX API calls made by an application. This can be used for a variety of purposes, such as modifying the rendering process, capturing frames, or injecting custom shaders. 65 | 66 | Q: What is a shader? 67 | 68 | A: A shader is a type of program that is run on the GPU (Graphics Processing Unit). Shaders are used to perform calculations related to rendering, such as vertex transformations, lighting calculations, or pixel coloring. 69 | 70 | Q: What is a VMT (Virtual Method Table)? 71 | 72 | A: A VMT, or Virtual Method Table, is a mechanism used in C++ to support dynamic dispatch (or runtime method binding). Each class with virtual functions (or an inherited interface) has its own VMT. A VMT is essentially an array of function pointers that the compiler creates for us. When we declare a class with some virtual methods, the compiler silently writes some code to create the VMT for that class. 73 | 74 | Prerequisites 75 | ------------- 76 | 77 | To use this code, you should have a good understanding of C++ and Windows programming. You should also be familiar with DirectX 11 and graphics programming concepts. Knowledge of reverse engineering techniques and assembly language will also be helpful. 78 | 79 | End Goal 80 | -------- 81 | 82 | The end goal of this project is to provide a robust and flexible DirectX 11 hook that can be used as a starting point for game modding, reverse engineering, or cheat development. The provided code demonstrates how to set up the hook and use it to modify the rendering process, but it can be extended to perform more complex tasks. 83 | 84 | Key Pieces of Code 85 | ------------------ 86 | 87 | The key pieces of this project are the hooking mechanism (`HookD3D` function), the hooked `Present` function (`hkPresent`), and the rendering code in the `Render` function. These pieces of code demonstrate the core functionality of the DirectX 11 hook. 88 | 89 | Associated Resources​ 90 | --------------------- 91 | 92 | - [Source Code - D3D11 X64 Present Hook](https://guidedhacking.com/threads/d3d11-x64-present-hook.15283/) 93 | - [Source Code - D3D11 Barebones hook PoC](https://guidedhacking.com/threads/d3d11-barebones-hook-poc.11939/) 94 | - [Source Code - D3D11 SWBF2 Cheats ( 2017 )](https://guidedhacking.com/threads/star-wars-battlefront-ii-hacks-swbf2-cheats-2017.15348/) 95 | - [DirectX11 Hook and Logger](https://guidedhacking.com/threads/directx11-hook-and-logger.11910/) 96 | 97 | GuidedHacking® - The Game Hacking Bible® - © 2025 Guided Hacking LLC. All Rights Reserved. 98 | -------------------------------------------------------------------------------- /GH_D3D11_Hook/GH_D3D11_Hook.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {A8FB3836-0DEF-44D2-9E70-F4BA3360E43F} 24 | GHD3D11Hook 25 | 10.0 26 | 27 | 28 | 29 | DynamicLibrary 30 | true 31 | v142 32 | Unicode 33 | 34 | 35 | DynamicLibrary 36 | false 37 | v142 38 | true 39 | Unicode 40 | 41 | 42 | DynamicLibrary 43 | true 44 | v142 45 | Unicode 46 | 47 | 48 | DynamicLibrary 49 | false 50 | v142 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | Disabled 77 | true 78 | true 79 | 80 | 81 | 82 | 83 | Level3 84 | Disabled 85 | true 86 | true 87 | 88 | 89 | 90 | 91 | Level3 92 | MaxSpeed 93 | true 94 | true 95 | true 96 | true 97 | 98 | 99 | true 100 | true 101 | 102 | 103 | 104 | 105 | Level3 106 | MaxSpeed 107 | true 108 | true 109 | true 110 | true 111 | 112 | 113 | true 114 | true 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /GH_D3D11_Hook/DllMain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #pragma comment(lib, "d3d11.lib") 6 | #pragma comment(lib, "d3dcompiler.lib") 7 | 8 | #define safe_release(p) if (p) { p->Release(); p = nullptr; } 9 | 10 | #include "shadez.h" 11 | #include "D3D_VMT_Indices.h" 12 | #define VMT_PRESENT (UINT)IDXGISwapChainVMT::Present 13 | #define PRESENT_STUB_SIZE 5 14 | 15 | // d3d11 related object ptrs 16 | using namespace DirectX; 17 | 18 | ID3D11Device* pDevice = nullptr; 19 | IDXGISwapChain* pSwapchain = nullptr; 20 | ID3D11DeviceContext* pContext = nullptr; 21 | ID3D11RenderTargetView* pRenderTargetView = nullptr; 22 | ID3D11VertexShader* pVertexShader = nullptr; 23 | ID3D11InputLayout* pVertexLayout = nullptr; 24 | ID3D11PixelShader* pPixelShader = nullptr; 25 | ID3D11Buffer* pVertexBuffer = nullptr; 26 | ID3D11Buffer* pIndexBuffer = nullptr; 27 | ID3D11Buffer* pConstantBuffer = nullptr; 28 | 29 | // Changing this to an array of viewports 30 | #define MAINVP 0 31 | D3D11_VIEWPORT pViewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]{ 0 }; 32 | XMMATRIX mOrtho; 33 | 34 | struct ConstantBuffer 35 | { 36 | XMMATRIX mProjection; 37 | }; 38 | 39 | struct Vertex 40 | { 41 | XMFLOAT3 pos; 42 | XMFLOAT4 color; 43 | }; 44 | 45 | HRESULT __stdcall hkPresent( IDXGISwapChain* pThis, UINT SyncInterval, UINT Flags ); 46 | using fnPresent = HRESULT( __stdcall* )(IDXGISwapChain* pThis, UINT SyncInterval, UINT Flags); 47 | void* ogPresent; // Pointer to the original Present function 48 | fnPresent ogPresentTramp; // Function pointer that calls the Present stub in our trampoline 49 | void* pTrampoline = nullptr; // Pointer to jmp instruction in our trampoline that leads to hkPresent 50 | char ogBytes[PRESENT_STUB_SIZE]; // Buffer to store original bytes from Present 51 | 52 | bool Hook( void* pSrc, void* pDst, size_t size ); 53 | bool WriteMem( void* pDst, char* pBytes, size_t size ); 54 | bool HookD3D(); 55 | bool CompileShader( const char* szShader, const char * szEntrypoint, const char * szTarget, ID3D10Blob ** pBlob ); 56 | bool InitD3DHook( IDXGISwapChain* pSwapchain ); 57 | void CleanupD3D(); 58 | void Render(); 59 | 60 | // adding this code ripped off SO to find the "main window" as a fallback to RSGetViewports 61 | struct HandleData 62 | { 63 | DWORD pid; 64 | HWND hWnd; 65 | }; 66 | HWND FindMainWindow( DWORD dwPID ); 67 | BOOL CALLBACK EnumWindowsCallback( HWND hWnd, LPARAM lParam ); 68 | 69 | void MainThread( void* pHandle ) 70 | { 71 | // Hook d3d 72 | if (HookD3D()) 73 | { 74 | // END key to unload 75 | while (!GetAsyncKeyState( VK_END )); 76 | } 77 | 78 | // Cleanup and unload dll 79 | CleanupD3D(); 80 | WriteMem( ogPresent, ogBytes, PRESENT_STUB_SIZE ); 81 | VirtualFree( (void*)ogPresentTramp, 0x1000, MEM_RELEASE ); 82 | CreateThread( 0, 0, (LPTHREAD_START_ROUTINE)FreeLibrary, pHandle, 0, 0 ); 83 | } 84 | 85 | BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved ) 86 | { 87 | switch (fdwReason) 88 | { 89 | case DLL_PROCESS_ATTACH: 90 | DisableThreadLibraryCalls( hinstDLL ); 91 | CreateThread( nullptr, 0, (LPTHREAD_START_ROUTINE)MainThread, hinstDLL, 0, nullptr ); 92 | break; 93 | case DLL_PROCESS_DETACH: 94 | 95 | break; 96 | } 97 | return TRUE; 98 | } 99 | 100 | bool Hook( void* pSrc, void* pDst, size_t size ) 101 | { 102 | DWORD dwOld; 103 | uintptr_t src = (uintptr_t)pSrc; 104 | uintptr_t dst = (uintptr_t)pDst; 105 | 106 | if (!VirtualProtect( pSrc, size, PAGE_EXECUTE_READWRITE, &dwOld )) 107 | return false; 108 | 109 | *(char*)src = (char)0xE9; 110 | *(int*)(src + 1) = (int)(dst - src - 5); 111 | 112 | VirtualProtect( pSrc, size, dwOld, &dwOld ); 113 | return true; 114 | } 115 | 116 | bool WriteMem( void* pDst, char* pBytes, size_t size ) 117 | { 118 | DWORD dwOld; 119 | if (!VirtualProtect( pDst, size, PAGE_EXECUTE_READWRITE, &dwOld )) 120 | return false; 121 | 122 | memcpy( pDst, pBytes, PRESENT_STUB_SIZE ); 123 | 124 | VirtualProtect( pDst, size, dwOld, &dwOld ); 125 | return true; 126 | } 127 | 128 | bool HookD3D() 129 | { 130 | // Create a dummy device, get swapchain vmt, hook present. 131 | D3D_FEATURE_LEVEL featLevel; 132 | DXGI_SWAP_CHAIN_DESC sd{ 0 }; 133 | sd.BufferCount = 1; 134 | sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 135 | sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 136 | sd.BufferDesc.Height = 800; 137 | sd.BufferDesc.Width = 600; 138 | sd.BufferDesc.RefreshRate = { 60, 1 }; 139 | sd.OutputWindow = GetForegroundWindow(); 140 | sd.Windowed = TRUE; 141 | sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; 142 | sd.SampleDesc.Count = 1; 143 | sd.SampleDesc.Quality = 0; 144 | HRESULT hr = D3D11CreateDeviceAndSwapChain( nullptr, D3D_DRIVER_TYPE_REFERENCE, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &sd, &pSwapchain, &pDevice, &featLevel, nullptr ); 145 | if (FAILED( hr )) 146 | return false; 147 | 148 | // Get swapchain vmt 149 | void** pVMT = *(void***)pSwapchain; 150 | 151 | // Get Present's address out of vmt 152 | ogPresent = (fnPresent)(pVMT[VMT_PRESENT]); 153 | 154 | // got what we need, we can release device and swapchain now 155 | // we'll be stealing the game's. 156 | safe_release( pSwapchain ); 157 | safe_release( pDevice ); 158 | 159 | // Create a code cave to trampoline to our hook 160 | // We'll try to do this close to present to make sure we'll be able to use a 5 byte jmp (important for x64) 161 | void* pLoc = (void*)((uintptr_t)ogPresent - 0x2000); 162 | void* pTrampLoc = nullptr; 163 | while (!pTrampLoc) 164 | { 165 | pTrampLoc = VirtualAlloc( pLoc, 1, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE ); 166 | pLoc = (void*)((uintptr_t)pLoc + 0x200); 167 | } 168 | ogPresentTramp = (fnPresent)pTrampLoc; 169 | 170 | // write original bytes to trampoline 171 | // write jmp to hook 172 | memcpy( ogBytes, ogPresent, PRESENT_STUB_SIZE ); 173 | memcpy( pTrampLoc, ogBytes, PRESENT_STUB_SIZE ); 174 | 175 | pTrampLoc = (void*)((uintptr_t)pTrampLoc + PRESENT_STUB_SIZE); 176 | 177 | // write the jmp back into present 178 | *(char*)pTrampLoc = (char)0xE9; 179 | pTrampLoc = (void*)((uintptr_t)pTrampLoc + 1); 180 | uintptr_t ogPresRet = (uintptr_t)ogPresent + 5; 181 | *(int*)pTrampLoc = (int)(ogPresRet - (uintptr_t)pTrampLoc - 4); 182 | 183 | // write the jmp to our hook 184 | pTrampoline = pTrampLoc = (void*)((uintptr_t)pTrampLoc + 4); 185 | #ifdef _WIN64 186 | // if x64, gazzillion byte absolute jmp 187 | char pJmp[] = { 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00 }; 188 | WriteMem( pTrampLoc, pJmp, ARRAYSIZE( pJmp ) ); 189 | pTrampLoc = (void*)((uintptr_t)pTrampLoc + ARRAYSIZE( pJmp )); 190 | *(uintptr_t*)pTrampLoc = (uintptr_t)hkPresent; 191 | #else 192 | // if x86, normal 0xE9 jmp 193 | *(char*)pTrampLoc = (char)0xE9; 194 | pTrampLoc = (void*)((uintptr_t)pTrampLoc + 1); 195 | *(int*)pTrampLoc = (uintptr_t)hkPresent - (uintptr_t)pTrampLoc - 4; 196 | #endif 197 | 198 | // hook present, place a normal mid-function at the beginning of the Present function 199 | return Hook(ogPresent, pTrampoline, PRESENT_STUB_SIZE); 200 | } 201 | 202 | bool CompileShader( const char* szShader, const char * szEntrypoint, const char * szTarget, ID3D10Blob ** pBlob ) 203 | { 204 | ID3D10Blob* pErrorBlob = nullptr; 205 | 206 | auto hr = D3DCompile( szShader, strlen( szShader ), 0, nullptr, nullptr, szEntrypoint, szTarget, D3DCOMPILE_ENABLE_STRICTNESS, 0, pBlob, &pErrorBlob ); 207 | if (FAILED( hr )) 208 | { 209 | if (pErrorBlob) 210 | { 211 | char szError[256]{ 0 }; 212 | memcpy( szError, pErrorBlob->GetBufferPointer(), pErrorBlob->GetBufferSize() ); 213 | MessageBoxA( nullptr, szError, "Error", MB_OK ); 214 | } 215 | return false; 216 | } 217 | return true; 218 | } 219 | 220 | bool InitD3DHook( IDXGISwapChain * pSwapchain ) 221 | { 222 | HRESULT hr = pSwapchain->GetDevice( __uuidof(ID3D11Device), (void**)&pDevice ); 223 | if (FAILED( hr )) 224 | return false; 225 | 226 | pDevice->GetImmediateContext( &pContext ); 227 | pContext->OMGetRenderTargets( 1, &pRenderTargetView, nullptr ); 228 | 229 | // If for some reason we fail to get a render target, create one. 230 | // This will probably never happen with a real game but maybe certain test environments... :P 231 | if (!pRenderTargetView) 232 | { 233 | // Get a pointer to the back buffer for the render target view 234 | ID3D11Texture2D* pBackbuffer = nullptr; 235 | hr = pSwapchain->GetBuffer( 0, __uuidof(ID3D11Texture2D), reinterpret_cast(&pBackbuffer) ); 236 | if (FAILED( hr )) 237 | return false; 238 | 239 | // Create render target view 240 | hr = pDevice->CreateRenderTargetView( pBackbuffer, nullptr, &pRenderTargetView ); 241 | pBackbuffer->Release(); 242 | if (FAILED( hr )) 243 | return false; 244 | 245 | // Make sure our render target is set. 246 | pContext->OMSetRenderTargets( 1, &pRenderTargetView, nullptr ); 247 | } 248 | 249 | // initialize shaders 250 | ID3D10Blob* pBlob = nullptr; 251 | 252 | // create vertex shader 253 | if (!CompileShader( szShadez, "VS", "vs_5_0", &pBlob )) 254 | return false; 255 | 256 | hr = pDevice->CreateVertexShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), nullptr, &pVertexShader ); 257 | if (FAILED( hr )) 258 | return false; 259 | 260 | // Define/create the input layout for the vertex shader 261 | D3D11_INPUT_ELEMENT_DESC layout[2] = { 262 | {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, 263 | {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0} 264 | }; 265 | UINT numElements = ARRAYSIZE( layout ); 266 | 267 | hr = pDevice->CreateInputLayout( layout, numElements, pBlob->GetBufferPointer(), pBlob->GetBufferSize(), &pVertexLayout ); 268 | if (FAILED( hr )) 269 | return false; 270 | 271 | safe_release( pBlob ); 272 | 273 | // create pixel shader 274 | if (!CompileShader( szShadez, "PS", "ps_5_0", &pBlob )) 275 | return false; 276 | 277 | hr = pDevice->CreatePixelShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), nullptr, &pPixelShader ); 278 | if (FAILED( hr )) 279 | return false; 280 | 281 | UINT numViewports = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; 282 | float fWidth = 0; 283 | float fHeight = 0; 284 | 285 | // Apparently this isn't universal. Works on some games 286 | pContext->RSGetViewports( &numViewports, pViewports ); 287 | 288 | // 289 | if (!numViewports || !pViewports[MAINVP].Width) 290 | { 291 | // This should be retrieved dynamically 292 | //HWND hWnd0 = FindWindowA( "W2ViewportClass", nullptr ); 293 | HWND hWnd = FindMainWindow( GetCurrentProcessId() ); 294 | RECT rc{ 0 }; 295 | if (!GetClientRect( hWnd, &rc )) 296 | return false; 297 | 298 | //fWidth = 1600.0f; 299 | //fHeight = 900.0f; 300 | fWidth = (float)rc.right; 301 | fHeight = (float)rc.bottom; 302 | 303 | // Setup viewport 304 | pViewports[MAINVP].Width = (float)fWidth; 305 | pViewports[MAINVP].Height = (float)fHeight; 306 | pViewports[MAINVP].MinDepth = 0.0f; 307 | pViewports[MAINVP].MaxDepth = 1.0f; 308 | 309 | // Set viewport to context 310 | pContext->RSSetViewports( 1, pViewports ); 311 | } 312 | else 313 | { 314 | fWidth = (float)pViewports[MAINVP].Width; 315 | fHeight = (float)pViewports[MAINVP].Height; 316 | } 317 | // Create the constant buffer 318 | D3D11_BUFFER_DESC bd{ 0 }; 319 | bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; 320 | bd.ByteWidth = sizeof( ConstantBuffer ); 321 | bd.Usage = D3D11_USAGE_DEFAULT; 322 | 323 | // Setup orthographic projection 324 | mOrtho = XMMatrixOrthographicLH( fWidth, fHeight, 0.0f, 1.0f ); 325 | ConstantBuffer cb; 326 | cb.mProjection = mOrtho; 327 | 328 | D3D11_SUBRESOURCE_DATA sr{ 0 }; 329 | sr.pSysMem = &cb; 330 | hr = pDevice->CreateBuffer( &bd, &sr, &pConstantBuffer ); 331 | if (FAILED( hr )) 332 | return false; 333 | 334 | // Create a triangle to render 335 | // Create a vertex buffer, start by setting up a description. 336 | ZeroMemory( &bd, sizeof( bd ) ); 337 | bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; 338 | bd.Usage = D3D11_USAGE_DEFAULT; 339 | bd.ByteWidth = 3 * sizeof( Vertex ); 340 | bd.StructureByteStride = sizeof( Vertex ); 341 | 342 | // left and top edge of window 343 | float left = fWidth / -2; 344 | float top = fHeight / 2; 345 | 346 | // Width and height of triangle 347 | float w = 50; 348 | float h = 50; 349 | 350 | // Center position of triangle, this should center it in the screen. 351 | float fPosX = -1 * left; 352 | float fPosY = top; 353 | 354 | // Setup vertices of triangle 355 | Vertex pVerts[3] = { 356 | { XMFLOAT3( left + fPosX, top - fPosY + h / 2, 1.0f ), XMFLOAT4( 1.0f, 0.0f, 0.0f, 1.0f ) }, 357 | { XMFLOAT3( left + fPosX + w / 2, top - fPosY - h / 2, 1.0f ), XMFLOAT4( 0.0f, 0.0f, 1.0f, 1.0f ) }, 358 | { XMFLOAT3( left + fPosX - w / 2, top - fPosY - h / 2, 1.0f ), XMFLOAT4( 0.0f, 1.0f, 0.0f, 1.0f ) }, 359 | }; 360 | 361 | // create the buffer. 362 | ZeroMemory( &sr, sizeof( sr ) ); 363 | sr.pSysMem = &pVerts; 364 | hr = pDevice->CreateBuffer( &bd, &sr, &pVertexBuffer ); 365 | if (FAILED( hr )) 366 | return false; 367 | 368 | // Create an index buffer 369 | ZeroMemory( &bd, sizeof( bd ) ); 370 | ZeroMemory( &sr, sizeof( sr ) ); 371 | 372 | UINT pIndices[3] = { 0, 1, 2 }; 373 | bd.BindFlags = D3D11_BIND_INDEX_BUFFER; 374 | bd.Usage = D3D11_USAGE_DEFAULT; 375 | bd.ByteWidth = sizeof( UINT ) * 3; 376 | bd.StructureByteStride = sizeof( UINT ); 377 | 378 | sr.pSysMem = &pIndices; 379 | hr = pDevice->CreateBuffer( &bd, &sr, &pIndexBuffer ); 380 | if (FAILED( hr )) 381 | return false; 382 | 383 | return true; 384 | } 385 | 386 | void CleanupD3D() 387 | { 388 | safe_release( pVertexBuffer ); 389 | safe_release( pIndexBuffer ); 390 | safe_release( pConstantBuffer ); 391 | safe_release( pPixelShader ); 392 | safe_release( pVertexShader ); 393 | safe_release( pVertexLayout ); 394 | } 395 | 396 | void Render() 397 | { 398 | // Make sure our render target is set. 399 | pContext->OMSetRenderTargets( 1, &pRenderTargetView, nullptr ); 400 | 401 | // Update view 402 | ConstantBuffer cb; 403 | cb.mProjection = XMMatrixTranspose( mOrtho ); 404 | pContext->UpdateSubresource( pConstantBuffer, 0, nullptr, &cb, 0, 0 ); 405 | pContext->VSSetConstantBuffers( 0, 1, &pConstantBuffer ); 406 | 407 | // Make sure the input assembler knows how to process our verts/indices 408 | UINT stride = sizeof( Vertex ); 409 | UINT offset = 0; 410 | pContext->IASetVertexBuffers( 0, 1, &pVertexBuffer, &stride, &offset ); 411 | pContext->IASetInputLayout( pVertexLayout ); 412 | pContext->IASetIndexBuffer( pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 ); 413 | pContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); 414 | 415 | // Set the shaders we need to render our triangle 416 | pContext->VSSetShader( pVertexShader, nullptr, 0 ); 417 | pContext->PSSetShader( pPixelShader, nullptr, 0 ); 418 | 419 | // Set viewport to context 420 | pContext->RSSetViewports( 1, pViewports ); 421 | 422 | // Draw our triangle 423 | pContext->DrawIndexed( 3, 0, 0 ); 424 | } 425 | 426 | HRESULT __stdcall hkPresent( IDXGISwapChain * pThis, UINT SyncInterval, UINT Flags ) 427 | { 428 | pSwapchain = pThis; 429 | 430 | if (!pDevice) 431 | { 432 | if (!InitD3DHook( pThis )) 433 | return false; 434 | } 435 | 436 | Render(); 437 | return ogPresentTramp( pThis, SyncInterval, Flags ); 438 | } 439 | 440 | HWND FindMainWindow( DWORD dwPID ) 441 | { 442 | HandleData handleData{ 0 }; 443 | handleData.pid = dwPID; 444 | EnumWindows( EnumWindowsCallback, (LPARAM)&handleData ); 445 | return handleData.hWnd; 446 | } 447 | 448 | BOOL CALLBACK EnumWindowsCallback(HWND hWnd, LPARAM lParam) 449 | { 450 | HandleData& data = *(HandleData*)lParam; 451 | DWORD pid = 0; 452 | GetWindowThreadProcessId( hWnd, &pid ); 453 | if (pid == data.pid && GetWindow( hWnd, GW_OWNER ) == HWND( 0 ) && IsWindowVisible( hWnd )) 454 | { 455 | data.hWnd = hWnd; 456 | return FALSE; 457 | } 458 | 459 | return TRUE; 460 | } --------------------------------------------------------------------------------