├── .gitattributes ├── .gitignore ├── EnjoyTheRing0.sln ├── EnjoyTheRing0 ├── DriversUtils.c ├── DriversUtils.h ├── EnjoyTheRing0.vcxproj ├── EnjoyTheRing0.vcxproj.filters ├── FilesUtils.c ├── FilesUtils.h ├── IOCTLDispatcher.c ├── IOCTLDispatcher.h ├── IpiWrapper.c ├── IpiWrapper.h ├── LinkedLists.c ├── LinkedLists.h ├── Main.c ├── MemoryAccessController.c ├── MemoryAccessController.h ├── MemoryUtils.c ├── MemoryUtils.h ├── NativeFunctions.c ├── NativeFunctions.h ├── NativeFunctions │ ├── IO.inc │ ├── Interrupts.inc │ ├── MSR.inc │ ├── Main.asm │ ├── NativeFunctions.prt │ ├── NativeFunctions64.obj │ ├── NativeFunctions86.obj │ └── SystemRegisters.inc ├── PCI.c ├── PCI.h ├── ProcessesUtils.c ├── ProcessesUtils.h ├── Protection.c ├── Protection.h ├── RegistryUtils.c ├── RegistryUtils.h ├── ShellCode.c ├── ShellCode.h ├── StringsUtils.c ├── StringsUtils.h ├── Synchronization.c └── Synchronization.h ├── README.md └── WinDbg Workspace.WEW /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.tmp_proj 63 | *.log 64 | *.vspscc 65 | *.vssscc 66 | .builds 67 | *.pidb 68 | *.svclog 69 | *.scc 70 | 71 | # Chutzpah Test files 72 | _Chutzpah* 73 | 74 | # Visual C++ cache files 75 | ipch/ 76 | *.aps 77 | *.ncb 78 | *.opendb 79 | *.opensdf 80 | *.sdf 81 | *.cachefile 82 | *.VC.db 83 | *.VC.VC.opendb 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | # TODO: Comment the next line if you want to checkin your web deploy settings 143 | # but database connection strings (with potential passwords) will be unencrypted 144 | *.pubxml 145 | *.publishproj 146 | 147 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 148 | # checkin your Azure Web App publish settings, but sensitive information contained 149 | # in these scripts will be unencrypted 150 | PublishScripts/ 151 | 152 | # NuGet Packages 153 | *.nupkg 154 | # The packages folder can be ignored because of Package Restore 155 | **/packages/* 156 | # except build/, which is used as an MSBuild target. 157 | !**/packages/build/ 158 | # Uncomment if necessary however generally it will be regenerated when needed 159 | #!**/packages/repositories.config 160 | # NuGet v3's project.json files produces more ignoreable files 161 | *.nuget.props 162 | *.nuget.targets 163 | 164 | # Microsoft Azure Build Output 165 | csx/ 166 | *.build.csdef 167 | 168 | # Microsoft Azure Emulator 169 | ecf/ 170 | rcf/ 171 | 172 | # Windows Store app package directories and files 173 | AppPackages/ 174 | BundleArtifacts/ 175 | Package.StoreAssociation.xml 176 | _pkginfo.txt 177 | 178 | # Visual Studio cache files 179 | # files ending in .cache can be ignored 180 | *.[Cc]ache 181 | # but keep track of directories ending in .cache 182 | !*.[Cc]ache/ 183 | 184 | # Others 185 | ClientBin/ 186 | ~$* 187 | *~ 188 | *.dbmdl 189 | *.dbproj.schemaview 190 | *.pfx 191 | *.publishsettings 192 | node_modules/ 193 | orleans.codegen.cs 194 | 195 | # Since there are multiple workflows, uncomment next line to ignore bower_components 196 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 197 | #bower_components/ 198 | 199 | # RIA/Silverlight projects 200 | Generated_Code/ 201 | 202 | # Backup & report files from converting an old project file 203 | # to a newer Visual Studio version. Backup files are not needed, 204 | # because we have git ;-) 205 | _UpgradeReport_Files/ 206 | Backup*/ 207 | UpgradeLog*.XML 208 | UpgradeLog*.htm 209 | 210 | # SQL Server files 211 | *.mdf 212 | *.ldf 213 | 214 | # Business Intelligence projects 215 | *.rdl.data 216 | *.bim.layout 217 | *.bim_*.settings 218 | 219 | # Microsoft Fakes 220 | FakesAssemblies/ 221 | 222 | # GhostDoc plugin setting file 223 | *.GhostDoc.xml 224 | 225 | # Node.js Tools for Visual Studio 226 | .ntvs_analysis.dat 227 | 228 | # Visual Studio 6 build log 229 | *.plg 230 | 231 | # Visual Studio 6 workspace options file 232 | *.opt 233 | 234 | # Visual Studio LightSwitch build output 235 | **/*.HTMLClient/GeneratedArtifacts 236 | **/*.DesktopClient/GeneratedArtifacts 237 | **/*.DesktopClient/ModelManifest.xml 238 | **/*.Server/GeneratedArtifacts 239 | **/*.Server/ModelManifest.xml 240 | _Pvt_Extensions 241 | 242 | # Paket dependency manager 243 | .paket/paket.exe 244 | paket-files/ 245 | 246 | # FAKE - F# Make 247 | .fake/ 248 | 249 | # JetBrains Rider 250 | .idea/ 251 | *.sln.iml 252 | 253 | # ========================= 254 | # Operating System Files 255 | # ========================= 256 | 257 | # OSX 258 | # ========================= 259 | 260 | .DS_Store 261 | .AppleDouble 262 | .LSOverride 263 | 264 | # Thumbnails 265 | ._* 266 | 267 | # Files that might appear in the root of a volume 268 | .DocumentRevisions-V100 269 | .fseventsd 270 | .Spotlight-V100 271 | .TemporaryItems 272 | .Trashes 273 | .VolumeIcon.icns 274 | 275 | # Directories potentially created on remote AFP share 276 | .AppleDB 277 | .AppleDesktop 278 | Network Trash Folder 279 | Temporary Items 280 | .apdisk 281 | 282 | # Windows 283 | # ========================= 284 | 285 | # Windows image file caches 286 | Thumbs.db 287 | ehthumbs.db 288 | 289 | # Folder config file 290 | Desktop.ini 291 | 292 | # Recycle Bin used on file shares 293 | $RECYCLE.BIN/ 294 | 295 | # Windows Installer files 296 | *.cab 297 | *.msi 298 | *.msm 299 | *.msp 300 | 301 | # Windows shortcuts 302 | *.lnk 303 | -------------------------------------------------------------------------------- /EnjoyTheRing0.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EnjoyTheRing0", "EnjoyTheRing0\EnjoyTheRing0.vcxproj", "{498FAD0B-8904-4318-86A1-C226355DA5BE}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {498FAD0B-8904-4318-86A1-C226355DA5BE}.Debug|x64.ActiveCfg = Debug|x64 17 | {498FAD0B-8904-4318-86A1-C226355DA5BE}.Debug|x64.Build.0 = Debug|x64 18 | {498FAD0B-8904-4318-86A1-C226355DA5BE}.Debug|x64.Deploy.0 = Debug|x64 19 | {498FAD0B-8904-4318-86A1-C226355DA5BE}.Debug|x86.ActiveCfg = Debug|Win32 20 | {498FAD0B-8904-4318-86A1-C226355DA5BE}.Debug|x86.Build.0 = Debug|Win32 21 | {498FAD0B-8904-4318-86A1-C226355DA5BE}.Debug|x86.Deploy.0 = Debug|Win32 22 | {498FAD0B-8904-4318-86A1-C226355DA5BE}.Release|x64.ActiveCfg = Release|x64 23 | {498FAD0B-8904-4318-86A1-C226355DA5BE}.Release|x64.Build.0 = Release|x64 24 | {498FAD0B-8904-4318-86A1-C226355DA5BE}.Release|x64.Deploy.0 = Release|x64 25 | {498FAD0B-8904-4318-86A1-C226355DA5BE}.Release|x86.ActiveCfg = Release|Win32 26 | {498FAD0B-8904-4318-86A1-C226355DA5BE}.Release|x86.Build.0 = Release|Win32 27 | {498FAD0B-8904-4318-86A1-C226355DA5BE}.Release|x86.Deploy.0 = Release|Win32 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | EndGlobal 33 | -------------------------------------------------------------------------------- /EnjoyTheRing0/DriversUtils.c: -------------------------------------------------------------------------------- 1 | #include "DriversUtils.h" 2 | 3 | LPWSTR DriversRegistryPath = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"; 4 | 5 | NTSTATUS LoadDriver(LPWSTR DriverPath, LPWSTR DriverName) { 6 | HANDLE hKey; 7 | NTSTATUS Status; 8 | 9 | Status = CreateKey(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\", &hKey); 10 | if (!NT_SUCCESS(Status)) return Status; 11 | 12 | SetKeyDword(hKey, L"Type", 0x00000001); // Type = Driver 13 | SetKeyDword(hKey, L"Start", 0x00000003); // Start = DemandStart 14 | SetKeyDword(hKey, L"ErrorControl", 0x00000001); // ErrorControl = Normal 15 | 16 | SetKeyString(hKey, L"DisplayName", DriverName); 17 | 18 | LPWSTR NtPath; 19 | ConcatenateStringsW(L"\\??\\", DriverPath, &NtPath); 20 | SetKeyExpandString(hKey, L"ImagePath", NtPath); 21 | 22 | LPWSTR RegistryPath; 23 | ConcatenateStringsW(DriversRegistryPath, DriverName, &RegistryPath); 24 | UNICODE_STRING ServicePath; 25 | RtlInitUnicodeString(&ServicePath, RegistryPath); 26 | Status = ZwLoadDriver(&ServicePath); 27 | 28 | FreeString(RegistryPath); 29 | FreeString(NtPath); 30 | CloseKey(hKey); 31 | 32 | return Status; 33 | } 34 | 35 | NTSTATUS UnloadDriver(LPWSTR DriverName) { 36 | LPWSTR RegistryPath; 37 | ConcatenateStringsW(DriversRegistryPath, DriverName, &RegistryPath); 38 | UNICODE_STRING ServicePath; 39 | RtlInitUnicodeString(&ServicePath, RegistryPath); 40 | NTSTATUS Status = ZwUnloadDriver(&ServicePath); 41 | FreeString(RegistryPath); 42 | return Status; 43 | } -------------------------------------------------------------------------------- /EnjoyTheRing0/DriversUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RegistryUtils.h" 4 | 5 | NTSTATUS LoadDriver(LPWSTR DriverPath, LPWSTR DriverName); 6 | NTSTATUS UnloadDriver(LPWSTR DriverName); -------------------------------------------------------------------------------- /EnjoyTheRing0/EnjoyTheRing0.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 | {498FAD0B-8904-4318-86A1-C226355DA5BE} 23 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 24 | v4.5 25 | 12.0 26 | Debug 27 | Win32 28 | EnjoyTheRing0 29 | 10.0.10586.0 30 | 31 | 32 | 33 | Windows7 34 | true 35 | WindowsKernelModeDriver10.0 36 | Driver 37 | WDM 38 | Desktop 39 | 40 | 41 | Windows7 42 | false 43 | WindowsKernelModeDriver10.0 44 | Driver 45 | WDM 46 | true 47 | Desktop 48 | 49 | 50 | Windows7 51 | true 52 | WindowsKernelModeDriver10.0 53 | Driver 54 | WDM 55 | Desktop 56 | 57 | 58 | Windows7 59 | false 60 | WindowsKernelModeDriver10.0 61 | Driver 62 | WDM 63 | true 64 | Desktop 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | DbgengKernelDebugger 76 | true 77 | false 78 | 79 | 80 | DbgengKernelDebugger 81 | true 82 | false 83 | 84 | 85 | DbgengKernelDebugger 86 | false 87 | true 88 | 89 | 90 | DbgengKernelDebugger 91 | true 92 | false 93 | 94 | 95 | 96 | false 97 | Level4 98 | 99 | 100 | /INTEGRITYCHECK %(AdditionalOptions) 101 | 102 | 103 | 104 | 105 | false 106 | true 107 | Level4 108 | 109 | 110 | /INTEGRITYCHECK %(AdditionalOptions) 111 | 112 | 113 | 114 | 115 | Level3 116 | 117 | 118 | 119 | 120 | false 121 | AnySuitable 122 | true 123 | Speed 124 | true 125 | true 126 | true 127 | 128 | 129 | /INTEGRITYCHECK %(AdditionalOptions) 130 | UseLinkTimeCodeGeneration 131 | 132 | 133 | 134 | 135 | Level3 136 | 137 | 138 | 139 | 140 | false 141 | AnySuitable 142 | true 143 | Speed 144 | true 145 | true 146 | true 147 | 148 | 149 | /INTEGRITYCHECK %(AdditionalOptions) 150 | 151 | 152 | 153 | 154 | Level4 155 | 156 | 157 | 158 | 159 | false 160 | AnySuitable 161 | true 162 | Speed 163 | true 164 | true 165 | true 166 | false 167 | Full 168 | 169 | 170 | /INTEGRITYCHECK %(AdditionalOptions) 171 | UseLinkTimeCodeGeneration 172 | No 173 | false 174 | 175 | 176 | 177 | 178 | Level4 179 | 180 | 181 | 182 | 183 | false 184 | AnySuitable 185 | true 186 | Speed 187 | true 188 | true 189 | true 190 | false 191 | true 192 | 193 | 194 | /INTEGRITYCHECK %(AdditionalOptions) 195 | 196 | 197 | UseLinkTimeCodeGeneration 198 | No 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | true 239 | true 240 | 241 | 242 | true 243 | true 244 | 245 | 246 | 247 | 248 | 249 | -------------------------------------------------------------------------------- /EnjoyTheRing0/EnjoyTheRing0.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Object Files 6 | 7 | 8 | Object Files 9 | 10 | 11 | 12 | 13 | Source Files 14 | 15 | 16 | Source Files 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 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | Source Files 56 | 57 | 58 | Source Files 59 | 60 | 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 | Header Files 82 | 83 | 84 | Header Files 85 | 86 | 87 | Header Files 88 | 89 | 90 | Header Files 91 | 92 | 93 | Header Files 94 | 95 | 96 | Header Files 97 | 98 | 99 | Header Files 100 | 101 | 102 | Header Files 103 | 104 | 105 | Header Files 106 | 107 | 108 | 109 | 110 | {1a91f49f-e456-4e1f-b220-744c04053ef9} 111 | 112 | 113 | {49bbd3cf-bbd6-4ecf-acc9-ac29b17805fa} 114 | 115 | 116 | {987f089c-c8da-4291-87c6-dc166427a306} 117 | 118 | 119 | -------------------------------------------------------------------------------- /EnjoyTheRing0/FilesUtils.c: -------------------------------------------------------------------------------- 1 | #include "FilesUtils.h" 2 | 3 | FORCEINLINE SIZE_T GetNtPath(LPWSTR Path, OUT LPWSTR* NtPath) { 4 | return ConcatenateStringsW(L"\\??\\", Path, NtPath); 5 | } 6 | 7 | FORCEINLINE VOID FreeNtPath(LPWSTR NtPath) { 8 | FreeString(NtPath); 9 | } 10 | 11 | FORCEINLINE SIZE_T InitUnicodeNtPath(LPWSTR Path, OUT PUNICODE_STRING NativePath, OUT LPWSTR* NtPath) { 12 | SIZE_T Length = GetNtPath(Path, NtPath); 13 | RtlInitUnicodeString(NativePath, *NtPath); 14 | return Length; 15 | } 16 | 17 | FORCEINLINE VOID FreeUnicodeNtPath(LPWSTR NtPath) { 18 | FreeString(NtPath); 19 | } 20 | 21 | 22 | 23 | NTSTATUS CreateFile(OUT PHANDLE hFile, LPWSTR FilePath, ACCESS_MASK AccessMask, ULONG FileAttributes, ULONG ShareAccess, ULONG DispositionFlags, ULONG CreateOptions) { 24 | NTSTATUS Status; 25 | UNICODE_STRING NativePath; 26 | LPWSTR NtPathBuffer; 27 | OBJECT_ATTRIBUTES ObjectAttributes; 28 | IO_STATUS_BLOCK IoStatusBlock; 29 | LARGE_INTEGER AllocationSize; 30 | 31 | AllocationSize.QuadPart = 0; 32 | 33 | // Инициализируем ObjectAttributes: 34 | InitUnicodeNtPath(FilePath, &NativePath, &NtPathBuffer); 35 | InitializeObjectAttributes(&ObjectAttributes, &NativePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); 36 | 37 | // Создаём (открываем) файл: 38 | Status = ZwCreateFile( 39 | hFile, // Сюда будет записан хэндл 40 | AccessMask, // GENERIC_READ, GENERIC_WRITE и т.д. 41 | &ObjectAttributes, // Указатель на структуру с информацией о файле (путь и т.д.) 42 | &IoStatusBlock, // Указатель на структуру, куда будет записана информация о статусе открытия файла 43 | &AllocationSize, // Следует ли выделять память под файл 44 | FileAttributes, // Атрибуты файла (FILE_ATTRIBUTE_NORMAL и т.д.) 45 | ShareAccess, // Флаги разделяемого доступа 46 | DispositionFlags, // Следует ли создавать файл, если он существует, и похожие флаги 47 | CreateOptions, // Флаги синхронных операций над файлом 48 | NULL, 49 | 0 50 | ); 51 | 52 | FreeUnicodeNtPath(NtPathBuffer); 53 | 54 | return Status; 55 | } 56 | 57 | NTSTATUS CreateEmptyFile(OUT PHANDLE hFile, LPWSTR FilePath) { 58 | return CreateFile( 59 | hFile, 60 | FilePath, 61 | FULL_ACCESS, 62 | FILE_ATTRIBUTE_NORMAL, 63 | FULL_SHARED_ACCESS, 64 | FILE_OVERWRITE_IF, 65 | FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT 66 | ); 67 | } 68 | 69 | NTSTATUS OpenFile(OUT PHANDLE hFile, LPWSTR FilePath, BOOL CreateIfNotExists) { 70 | return CreateFile( 71 | hFile, 72 | FilePath, 73 | FULL_ACCESS, 74 | FILE_ATTRIBUTE_NORMAL, 75 | FULL_SHARED_ACCESS, 76 | CreateIfNotExists ? FILE_OPEN_IF : FILE_OPEN, 77 | FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT 78 | ); 79 | } 80 | 81 | NTSTATUS AppendFile(OUT PHANDLE hFile, LPWSTR FilePath, BOOL CreateIfNotExists) { 82 | return CreateFile( 83 | hFile, 84 | FilePath, 85 | FILE_APPEND_DATA, 86 | FILE_ATTRIBUTE_NORMAL, 87 | FULL_SHARED_ACCESS, 88 | CreateIfNotExists ? FILE_OPEN_IF : FILE_OPEN, 89 | FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT 90 | ); 91 | } 92 | 93 | NTSTATUS CreateDirectory(LPWSTR DirPath) { 94 | HANDLE hDir = 0; 95 | NTSTATUS Status = CreateFile(&hDir, DirPath, SYNCHRONIZE, FILE_ATTRIBUTE_DIRECTORY, NON_SHARED_ACCESS, FILE_CREATE, FILE_DIRECTORY_FILE); 96 | if (SUCCESS_FILE_OPERATION(Status, hDir)) CloseFile(hDir); 97 | return Status; 98 | } 99 | 100 | 101 | BOOL FileObjectExists(LPWSTR Path, BOOL IsDirectory) { 102 | HANDLE hObject; 103 | 104 | NTSTATUS Status; 105 | if (IsDirectory) { 106 | Status = CreateFile(&hObject, Path, SYNCHRONIZE, FILE_ATTRIBUTE_DIRECTORY, FULL_SHARED_ACCESS, FILE_OPEN, FILE_DIRECTORY_FILE); 107 | } else { 108 | Status = CreateFile(&hObject, Path, SYNCHRONIZE, FILE_ATTRIBUTE_NORMAL, FULL_SHARED_ACCESS, FILE_OPEN, FILE_NON_DIRECTORY_FILE); 109 | } 110 | 111 | BOOL ExistingStatus = SUCCESS_FILE_OPERATION(Status, hObject); 112 | if (ExistingStatus) CloseFile(hObject); 113 | 114 | return ExistingStatus; 115 | } 116 | 117 | BOOL FileExists(LPWSTR FilePath) { 118 | return FileObjectExists(FilePath, FALSE); 119 | } 120 | 121 | BOOL DirectoryExists(LPWSTR DirectoryPath) { 122 | return FileObjectExists(DirectoryPath, TRUE); 123 | } 124 | 125 | 126 | 127 | LONGLONG GetFileSize(LPWSTR FilePath) { 128 | HANDLE hFile; 129 | NTSTATUS CreationStatus = CreateFile(&hFile, FilePath, SYNCHRONIZE, FILE_ATTRIBUTE_NORMAL, FULL_SHARED_ACCESS, FILE_OPEN, FILE_NON_DIRECTORY_FILE); 130 | if (!SUCCESS_FILE_OPERATION(CreationStatus, hFile)) return 0; 131 | 132 | IO_STATUS_BLOCK IoStatusBlock; 133 | FILE_STANDARD_INFORMATION FileInfo; 134 | 135 | NTSTATUS Status = ZwQueryInformationFile(hFile, &IoStatusBlock, &FileInfo, sizeof(FileInfo), FileStandardInformation); 136 | CloseFile(hFile); 137 | 138 | return NT_SUCCESS(Status) ? FileInfo.EndOfFile.QuadPart : 0; 139 | } 140 | 141 | 142 | 143 | NTSTATUS MoveFileObject(LPWSTR OldFilePath, LPWSTR NewFilePath, BOOLEAN ReplaceIfExists, BOOL IsDirectory) { 144 | HANDLE hFile; 145 | NTSTATUS CreationStatus; 146 | 147 | if (IsDirectory) { 148 | CreationStatus = CreateFile(&hFile, OldFilePath, DELETE, FILE_ATTRIBUTE_DIRECTORY, NON_SHARED_ACCESS, FILE_OPEN, FILE_DIRECTORY_FILE); 149 | } else { 150 | CreationStatus = CreateFile(&hFile, OldFilePath, DELETE, FILE_ATTRIBUTE_NORMAL, NON_SHARED_ACCESS, FILE_OPEN, FILE_NON_DIRECTORY_FILE); 151 | } 152 | if (!SUCCESS_FILE_OPERATION(CreationStatus, hFile)) return CreationStatus; 153 | 154 | // Формируем Nt-путь к новому файлу: 155 | LPWSTR NewFileNativePath; 156 | ULONG FileNameLength = (ULONG)GetNtPath(NewFilePath, &NewFileNativePath); 157 | ULONG FileNameLengthInBytes = FileNameLength * sizeof(WCHAR); // Размер строки в байтах без учёта нуль-терминатора 158 | 159 | ULONG FileRenameInformationSize = sizeof(FILE_RENAME_INFORMATION) + FileNameLengthInBytes; // Размер структуры в байтах с учётом нуль-терминированной строки 160 | 161 | PFILE_RENAME_INFORMATION pFileRenameInformation = GetMem(FileRenameInformationSize); 162 | pFileRenameInformation->ReplaceIfExists = ReplaceIfExists; 163 | pFileRenameInformation->RootDirectory = NULL; 164 | pFileRenameInformation->FileNameLength = FileNameLengthInBytes; // Размер нового имени в БАЙТАХ без нуль-терминатора (!) 165 | SafeStrCpyW(pFileRenameInformation->FileName, FileNameLengthInBytes + sizeof(WCHAR), NewFileNativePath); 166 | 167 | IO_STATUS_BLOCK IoStatusBlock; 168 | NTSTATUS Status = ZwSetInformationFile(hFile, &IoStatusBlock, pFileRenameInformation, FileRenameInformationSize, FileRenameInformation); 169 | 170 | FreeString(NewFileNativePath); 171 | FreeMem(pFileRenameInformation); 172 | CloseFile(hFile); 173 | 174 | return Status; 175 | } 176 | 177 | NTSTATUS MoveFile(LPWSTR OldFileName, LPWSTR NewFileName, BOOLEAN ReplaceIfExists) { 178 | return MoveFileObject(OldFileName, NewFileName, ReplaceIfExists, FALSE); 179 | } 180 | 181 | NTSTATUS MoveDirectory(LPWSTR OldDirectoryName, LPWSTR NewDirectoryName, BOOLEAN ReplaceIfExists) { 182 | return MoveFileObject(OldDirectoryName, NewDirectoryName, ReplaceIfExists, TRUE); 183 | } 184 | 185 | NTSTATUS RenameFile(LPWSTR OldFileName, LPWSTR NewFileName, BOOLEAN ReplaceIfExists) { 186 | return MoveFileObject(OldFileName, NewFileName, ReplaceIfExists, FALSE); 187 | } 188 | 189 | NTSTATUS RenameDirectory(LPWSTR OldDirectoryName, LPWSTR NewDirectoryName) { 190 | return MoveFileObject(OldDirectoryName, NewDirectoryName, FALSE, TRUE); 191 | } 192 | 193 | 194 | 195 | NTSTATUS DeleteFileObject(LPWSTR Path) { 196 | OBJECT_ATTRIBUTES ObjectAttributes; 197 | UNICODE_STRING NativePath; 198 | LPWSTR NtPath; 199 | 200 | InitUnicodeNtPath(Path, &NativePath, &NtPath); 201 | InitializeObjectAttributes(&ObjectAttributes, &NativePath, OBJ_CASE_INSENSITIVE, NULL, NULL); 202 | NTSTATUS Status = ZwDeleteFile(&ObjectAttributes); 203 | FreeUnicodeNtPath(NtPath); 204 | 205 | return Status; 206 | } 207 | 208 | NTSTATUS DeleteFile(LPWSTR FilePath) { 209 | return DeleteFileObject(FilePath); 210 | } 211 | 212 | NTSTATUS DeleteDirectory(LPWSTR DirectoryPath) { 213 | return DeleteFileObject(DirectoryPath); 214 | } 215 | 216 | 217 | 218 | NTSTATUS ReadFile(HANDLE hFile, PVOID Buffer, ULONG Size, IN OPTIONAL PLARGE_INTEGER Offset, OUT OPTIONAL PULONG BytesRead) { 219 | IO_STATUS_BLOCK IoStatusBlock; 220 | NTSTATUS Status = ZwReadFile(hFile, NULL, NULL, NULL, &IoStatusBlock, Buffer, Size, Offset, NULL); 221 | if (BytesRead != NULL) *BytesRead = (ULONG)IoStatusBlock.Information; 222 | return Status; 223 | } 224 | 225 | NTSTATUS WriteFile(HANDLE hFile, PVOID Buffer, ULONG Size, IN OPTIONAL PLARGE_INTEGER Offset, OUT OPTIONAL PULONG BytesWritten) { 226 | IO_STATUS_BLOCK IoStatusBlock; 227 | NTSTATUS Status = ZwWriteFile(hFile, 0, NULL, NULL, &IoStatusBlock, Buffer, Size, Offset, NULL); 228 | if (BytesWritten != NULL) *BytesWritten = (ULONG)IoStatusBlock.Information; 229 | return Status; 230 | } 231 | 232 | 233 | 234 | NTSTATUS CopyFile(LPWSTR SrcFile, LPWSTR DestFile) { 235 | HANDLE hSrcFile, hDestFile; 236 | NTSTATUS SrcOpeningStatus = OpenFile(&hSrcFile, SrcFile, FALSE); 237 | if (!SUCCESS_FILE_OPERATION(SrcOpeningStatus, hSrcFile)) return SrcOpeningStatus; 238 | 239 | NTSTATUS DestCreationStatus = CreateEmptyFile(&hDestFile, DestFile); 240 | if (!SUCCESS_FILE_OPERATION(DestCreationStatus, hDestFile)) { 241 | CloseFile(hSrcFile); 242 | return DestCreationStatus; 243 | } 244 | 245 | const ULONG BufferSize = 524288; 246 | PVOID Buffer = GetMem(BufferSize); 247 | 248 | ULONG BytesRead, BytesWritten; 249 | 250 | do { 251 | ReadFile(hSrcFile, Buffer, BufferSize, NULL, &BytesRead); 252 | WriteFile(hDestFile, Buffer, BytesRead, NULL, &BytesWritten); 253 | } while (BytesRead > 0); 254 | 255 | FreeMem(Buffer); 256 | 257 | CloseFile(hSrcFile); 258 | CloseFile(hDestFile); 259 | 260 | return STATUS_SUCCESS; 261 | } 262 | -------------------------------------------------------------------------------- /EnjoyTheRing0/FilesUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MemoryUtils.h" 4 | #include "StringsUtils.h" 5 | 6 | // Сокращённые флаги доступа: 7 | #define FULL_ACCESS GENERIC_ALL 8 | #define FULL_SHARED_ACCESS FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE 9 | #define NON_SHARED_ACCESS 0 // Исключительные права на файл (нет разделяемого доступа) 10 | 11 | // Макрос для определения успешности выполнения CreateFile: 12 | #define SUCCESS_FILE_OPERATION(Status, Handle) (NT_SUCCESS((NTSTATUS)Status) && ((HANDLE)Handle != 0)) 13 | 14 | // Создание или открытие файла или папки с настраиваемыми параметрами доступа: 15 | NTSTATUS CreateFile( 16 | OUT PHANDLE hFile, 17 | LPWSTR FilePath, 18 | ACCESS_MASK AccessMask, 19 | ULONG FileAttributes, 20 | ULONG ShareAccess, 21 | ULONG DispositionFlags, 22 | ULONG CreateOptions 23 | ); 24 | 25 | // Создание или открытие файлов с частоиспользуемыми параметрами (+ подготовка файлов для записи\чтения с флагом FILE_SYNCHRONOUS_IO_NONALERT): 26 | NTSTATUS CreateEmptyFile(OUT PHANDLE hFile, LPWSTR FilePath); 27 | NTSTATUS OpenFile (OUT PHANDLE hFile, LPWSTR FilePath, BOOL CreateIfNotExists); 28 | NTSTATUS AppendFile (OUT PHANDLE hFile, LPWSTR FilePath, BOOL CreateIfNotExists); 29 | 30 | NTSTATUS CreateDirectory(LPWSTR DirPath); 31 | 32 | #define CloseFile(hFile) ZwClose(hFile) 33 | 34 | // Переименование или перемещение файлов и папок (переименование и перемещение - одна и та же операция): 35 | NTSTATUS MoveFileObject (LPWSTR OldFilePath , LPWSTR NewFilePath , BOOLEAN ReplaceIfExists, BOOL IsDirectory); 36 | NTSTATUS MoveFile (LPWSTR OldFilePath , LPWSTR NewFilePath , BOOLEAN ReplaceIfExists); 37 | NTSTATUS MoveDirectory (LPWSTR OldDirectoryName, LPWSTR NewDirectoryName, BOOLEAN ReplaceIfExists); 38 | NTSTATUS RenameFile (LPWSTR OldFilePath , LPWSTR NewFilePath , BOOLEAN ReplaceIfExists); 39 | NTSTATUS RenameDirectory(LPWSTR OldDirectoryName, LPWSTR NewDirectoryName); 40 | 41 | // Удаление: 42 | NTSTATUS DeleteFileObject(LPWSTR Path); 43 | NTSTATUS DeleteFile (LPWSTR FilePath); 44 | NTSTATUS DeleteDirectory (LPWSTR DirectoryPath); 45 | 46 | // Проверка на существование: 47 | BOOL FileObjectExists(LPWSTR Path, BOOL IsDirectory); 48 | BOOL FileExists (LPWSTR FilePath); 49 | BOOL DirectoryExists (LPWSTR DirectoryPath); 50 | 51 | LONGLONG GetFileSize(LPWSTR FilePath); 52 | 53 | // Чтение и запись в файлы, в CreateOptions нужно дополнительно передать FILE_SYNCHRONOUS_IO_NONALERT: 54 | NTSTATUS ReadFile (HANDLE hFile, PVOID Buffer, ULONG Size, IN OPTIONAL PLARGE_INTEGER Offset, OUT OPTIONAL PULONG BytesRead); 55 | NTSTATUS WriteFile(HANDLE hFile, PVOID Buffer, ULONG Size, IN OPTIONAL PLARGE_INTEGER Offset, OUT OPTIONAL PULONG BytesWritten); 56 | 57 | // Копирование файла: 58 | NTSTATUS CopyFile(LPWSTR SrcFile, LPWSTR DestFile); -------------------------------------------------------------------------------- /EnjoyTheRing0/IOCTLDispatcher.c: -------------------------------------------------------------------------------- 1 | #include "IOCTLDispatcher.h" 2 | 3 | VOID OnDriverLoad() { 4 | #ifdef PROTECTION_SUPPORT 5 | RegisterProtection(); 6 | #endif 7 | } 8 | 9 | VOID OnHandleCreate() { 10 | if (HandlesCount < 0x7FFFFFFF) InterlockedIncrement(&HandlesCount); 11 | } 12 | 13 | VOID OnHandleClose() { 14 | if (HandlesCount > 0) InterlockedDecrement(&HandlesCount); 15 | #ifdef PROTECTION_SUPPORT 16 | RemoveProtectedProcess(ANY_PROCESS, GetCurrentProcessId()); 17 | #endif 18 | } 19 | 20 | VOID OnDriverUnload() { 21 | #ifdef PROTECTION_SUPPORT 22 | ClearProtectedProcessesList(); 23 | UnregisterProtection(); 24 | #endif 25 | } 26 | 27 | NTSTATUS FASTCALL DispatchIOCTL(IN PIOCTL_INFO RequestInfo, OUT PULONG ResponseLength) 28 | { 29 | NTSTATUS Status = STATUS_SUCCESS; 30 | 31 | #define INPUT(Type) ((Type)(RequestInfo->InputBuffer)) 32 | #define OUTPUT(Type) ((Type)(RequestInfo->OutputBuffer)) 33 | #define SET_RESPONSE_LENGTH(Length) if (ResponseLength) {*ResponseLength = (Length);} 34 | 35 | #ifdef _X86_ 36 | #pragma warning(push) 37 | #pragma warning(disable: 4305) 38 | #endif 39 | 40 | switch (RequestInfo->ControlCode) { 41 | 42 | // DriverFunctions: 43 | 44 | case GET_HANDLES_COUNT: 45 | *OUTPUT(PULONG) = HandlesCount; 46 | SET_RESPONSE_LENGTH(sizeof(ULONG)); 47 | break; 48 | 49 | // NativeFunctions: 50 | 51 | case START_BEEPER: 52 | __outbyte(0x61, __inbyte(0x61) | 3); 53 | break; 54 | 55 | case STOP_BEEPER: 56 | __outbyte(0x61, __inbyte(0x61) & 252); 57 | break; 58 | 59 | case SET_BEEPER_REGIME: 60 | __outbyte(0x43, 0xB6); 61 | break; 62 | 63 | case SET_BEEPER_OUT: 64 | __outbyte(0x61, __inbyte(0x61) | 2); 65 | break; 66 | 67 | case SET_BEEPER_IN: 68 | __outbyte(0x61, __inbyte(0x61) & 253); 69 | break; 70 | 71 | case SET_BEEPER_DIVIDER: 72 | SetBeeperDivider(*INPUT(PWORD)); 73 | break; 74 | 75 | case SET_BEEPER_FREQUENCY: 76 | SetBeeperFrequency(*INPUT(PWORD)); 77 | break; 78 | 79 | case READ_IO_PORT_BYTE: 80 | *OUTPUT(PBYTE) = __inbyte(*INPUT(PWORD)); 81 | SET_RESPONSE_LENGTH(sizeof(BYTE)); 82 | break; 83 | 84 | case READ_IO_PORT_WORD: 85 | *OUTPUT(PWORD) = __inword(*INPUT(PWORD)); 86 | SET_RESPONSE_LENGTH(sizeof(WORD)); 87 | break; 88 | 89 | case READ_IO_PORT_DWORD: 90 | *OUTPUT(PDWORD32) = __indword(*INPUT(PWORD)); 91 | SET_RESPONSE_LENGTH(sizeof(DWORD)); 92 | break; 93 | 94 | case WRITE_IO_PORT_BYTE: 95 | __outbyte( 96 | INPUT(PWRITE_IO_PORT_BYTE_INPUT)->PortNumber, 97 | INPUT(PWRITE_IO_PORT_BYTE_INPUT)->Data 98 | ); 99 | break; 100 | 101 | case WRITE_IO_PORT_WORD: 102 | __outword( 103 | INPUT(PWRITE_IO_PORT_WORD_INPUT)->PortNumber, 104 | INPUT(PWRITE_IO_PORT_WORD_INPUT)->Data 105 | ); 106 | break; 107 | 108 | case WRITE_IO_PORT_DWORD: 109 | __outdword( 110 | INPUT(PWRITE_IO_PORT_DWORD_INPUT)->PortNumber, 111 | INPUT(PWRITE_IO_PORT_DWORD_INPUT)->Data 112 | ); 113 | break; 114 | 115 | case RDPMC: 116 | *OUTPUT(PULONGLONG) = __readpmc(*INPUT(PULONG)); 117 | SET_RESPONSE_LENGTH(sizeof(ULONGLONG)); 118 | break; 119 | 120 | case RDMSR: 121 | *OUTPUT(PULONGLONG) = __readmsr(*INPUT(PULONG)); 122 | SET_RESPONSE_LENGTH(sizeof(ULONGLONG)); 123 | break; 124 | 125 | case WRMSR: 126 | __writemsr(INPUT(PWRMSR_INPUT)->Index, INPUT(PWRMSR_INPUT)->Data); 127 | break; 128 | 129 | case HALT: 130 | __halt(); 131 | break; 132 | 133 | // MemoryUtils: 134 | 135 | case ALLOC_KERNEL_MEMORY: 136 | *OUTPUT(PUINT64) = (SIZE_T)GetMem(*INPUT(PSIZE_T)); 137 | SET_RESPONSE_LENGTH(sizeof(UINT64)); 138 | break; 139 | 140 | case FREE_KERNEL_MEMORY: 141 | FreeMem((PVOID)*INPUT(PUINT64)); 142 | break; 143 | 144 | case MOVE_MEMORY: 145 | RtlMoveMemory( 146 | (PVOID)INPUT(PMOVE_MEMORY_INPUT)->Destination, 147 | (PVOID)INPUT(PMOVE_MEMORY_INPUT)->Source, 148 | (SIZE_T)INPUT(PMOVE_MEMORY_INPUT)->Size 149 | ); 150 | break; 151 | 152 | case COPY_MEMORY: 153 | RtlCopyMemory( 154 | (PVOID)INPUT(PCOPY_MEMORY_INPUT)->Destination, 155 | (PVOID)INPUT(PCOPY_MEMORY_INPUT)->Source, 156 | (SIZE_T)INPUT(PCOPY_MEMORY_INPUT)->Size 157 | ); 158 | break; 159 | 160 | case ZERO_MEMORY: 161 | RtlZeroMemory( 162 | (PVOID)INPUT(PZERO_MEMORY_INPUT)->Destination, 163 | (SIZE_T)INPUT(PZERO_MEMORY_INPUT)->Size 164 | ); 165 | break; 166 | 167 | case FILL_MEMORY: 168 | RtlFillMemory( 169 | (PVOID)INPUT(PFILL_MEMORY_INPUT)->Destination, 170 | (SIZE_T)INPUT(PFILL_MEMORY_INPUT)->Size, 171 | (BYTE)INPUT(PFILL_MEMORY_INPUT)->FillingByte 172 | ); 173 | break; 174 | 175 | case EQUAL_MEMORY: 176 | *OUTPUT(PBOOL) = RtlEqualMemory( 177 | (PVOID)INPUT(PEQUAL_MEMORY_INPUT)->Destination, 178 | (PVOID)INPUT(PEQUAL_MEMORY_INPUT)->Source, 179 | (SIZE_T)INPUT(PEQUAL_MEMORY_INPUT)->Size 180 | ); 181 | SET_RESPONSE_LENGTH(sizeof(BOOL)); 182 | break; 183 | 184 | case ALLOC_PHYSICAL_MEMORY: 185 | *OUTPUT(PUINT64) = (SIZE_T)AllocPhysicalMemory( 186 | INPUT(PALLOC_PHYSICAL_MEMORY_INPUT)->PhysicalAddress, 187 | (SIZE_T)INPUT(PALLOC_PHYSICAL_MEMORY_INPUT)->Size 188 | ); 189 | SET_RESPONSE_LENGTH(sizeof(UINT64)); 190 | break; 191 | 192 | case FREE_PHYSICAL_MEMORY: 193 | FreePhysicalMemory((PVOID)*INPUT(PUINT64)); 194 | break; 195 | 196 | case GET_PHYSICAL_ADDRESS: 197 | *OUTPUT(PPHYSICAL_ADDRESS) = GetPhysicalAddressInProcess( 198 | (HANDLE)INPUT(PGET_PHYSICAL_ADDRESS_INPUT)->ProcessID, 199 | (PVOID)INPUT(PGET_PHYSICAL_ADDRESS_INPUT)->VirtualAddress 200 | ); 201 | SET_RESPONSE_LENGTH(sizeof(PHYSICAL_ADDRESS)); 202 | break; 203 | 204 | case READ_PHYSICAL_MEMORY: 205 | *OUTPUT(PBOOL) = ReadPhysicalMemory( 206 | INPUT(PREAD_PHYSICAL_MEMORY_INPUT)->PhysicalAddress, 207 | (PVOID)INPUT(PREAD_PHYSICAL_MEMORY_INPUT)->Buffer, 208 | INPUT(PREAD_PHYSICAL_MEMORY_INPUT)->BufferSize 209 | ); 210 | SET_RESPONSE_LENGTH(sizeof(BOOL)); 211 | break; 212 | 213 | case WRITE_PHYSICAL_MEMORY: 214 | *OUTPUT(PBOOL) = WritePhysicalMemory( 215 | INPUT(PWRITE_PHYSICAL_MEMORY_INPUT)->PhysicalAddress, 216 | (PVOID)INPUT(PWRITE_PHYSICAL_MEMORY_INPUT)->Buffer, 217 | INPUT(PWRITE_PHYSICAL_MEMORY_INPUT)->BufferSize 218 | ); 219 | SET_RESPONSE_LENGTH(sizeof(BOOL)); 220 | break; 221 | 222 | case READ_DMI_MEMORY: 223 | if (IsUsermodeMemoryWriteable((PVOID)*INPUT(PUINT64), DMI_SIZE, NON_ALIGNED)) { 224 | if (ReadDmiMemory((PVOID)*INPUT(PUINT64), DMI_SIZE)) { 225 | SET_RESPONSE_LENGTH(DMI_SIZE); 226 | } else { 227 | Status = STATUS_UNSUCCESSFUL; 228 | } 229 | } else { 230 | Status = STATUS_INFO_LENGTH_MISMATCH; 231 | } 232 | *OUTPUT(PNTSTATUS) = Status; 233 | break; 234 | 235 | // ShellCode: 236 | 237 | case EXECUTE_SHELL_CODE: 238 | *OUTPUT(PSHELL_STATUS) = ExecuteShell( 239 | (PVOID)INPUT(PEXECUTE_SHELL_CODE_INPUT)->EntryPoint, 240 | (PVOID)INPUT(PEXECUTE_SHELL_CODE_INPUT)->CodeBlock, 241 | (PVOID)INPUT(PEXECUTE_SHELL_CODE_INPUT)->InputData, 242 | (PVOID)INPUT(PEXECUTE_SHELL_CODE_INPUT)->OutputData, 243 | (PVOID)INPUT(PEXECUTE_SHELL_CODE_INPUT)->Result 244 | ); 245 | SET_RESPONSE_LENGTH(sizeof(SHELL_STATUS)); 246 | break; 247 | 248 | // ProcessesUtils: 249 | 250 | case ALLOC_VIRTUAL_MEMORY: 251 | OUTPUT(PALLOC_VIRTUAL_MEMORY_OUTPUT)->Status = VirtualAllocInProcess( 252 | (HANDLE)INPUT(PALLOC_VIRTUAL_MEMORY_INPUT)->ProcessId, 253 | (SIZE_T)INPUT(PALLOC_VIRTUAL_MEMORY_INPUT)->Size, 254 | (PVOID*)&OUTPUT(PALLOC_VIRTUAL_MEMORY_OUTPUT)->VirtualAddress 255 | ); 256 | SET_RESPONSE_LENGTH(sizeof(ALLOC_VIRTUAL_MEMORY_OUTPUT)); 257 | break; 258 | 259 | case FREE_VIRTUAL_MEMORY: 260 | *OUTPUT(PNTSTATUS) = VirtualFreeInProcess( 261 | (HANDLE)INPUT(PFREE_VIRTUAL_MEMORY_INPUT)->ProcessId, 262 | (PVOID)INPUT(PFREE_VIRTUAL_MEMORY_INPUT)->VirtualAddress 263 | ); 264 | SET_RESPONSE_LENGTH(sizeof(NTSTATUS)); 265 | break; 266 | 267 | case MAP_VIRTUAL_MEMORY: 268 | OUTPUT(PMAP_VIRTUAL_MEMORY_OUTPUT)->MappedMemory = MapVirtualMemory( 269 | (HANDLE)INPUT(PMAP_VIRTUAL_MEMORY_INPUT)->ProcessId, 270 | INPUT(PMAP_VIRTUAL_MEMORY_INPUT)->VirtualAddress, 271 | INPUT(PMAP_VIRTUAL_MEMORY_INPUT)->MapToVirtualAddress, 272 | INPUT(PMAP_VIRTUAL_MEMORY_INPUT)->Size, 273 | UserMode, 274 | (PMDL*)&(OUTPUT(PMAP_VIRTUAL_MEMORY_OUTPUT)->Mdl) 275 | ); 276 | SET_RESPONSE_LENGTH(sizeof(MAP_VIRTUAL_MEMORY_OUTPUT)); 277 | break; 278 | 279 | case UNMAP_VIRTUAL_MEMORY: 280 | UnmapVirtualMemory( 281 | INPUT(PUNMAP_VIRTUAL_MEMORY_INPUT)->Mdl, 282 | INPUT(PUNMAP_VIRTUAL_MEMORY_INPUT)->MappedMemory 283 | ); 284 | break; 285 | 286 | case READ_PROCESS_MEMORY: 287 | *OUTPUT(PBOOL) = ReadProcessMemory( 288 | (HANDLE)INPUT(PREAD_PROCESS_MEMORY_INPUT)->ProcessId, 289 | (PVOID)INPUT(PREAD_PROCESS_MEMORY_INPUT)->VirtualAddress, 290 | (PVOID)INPUT(PREAD_PROCESS_MEMORY_INPUT)->Buffer, 291 | INPUT(PREAD_PROCESS_MEMORY_INPUT)->BytesToRead, 292 | TRUE, 293 | (MEMORY_ACCESS_TYPE)INPUT(PREAD_PROCESS_MEMORY_INPUT)->AccessType 294 | ); 295 | SET_RESPONSE_LENGTH(sizeof(BOOL)); 296 | break; 297 | 298 | case WRITE_PROCESS_MEMORY: 299 | *OUTPUT(PBOOL) = WriteProcessMemory( 300 | (HANDLE)INPUT(PWRITE_PROCESS_MEMORY_INPUT)->ProcessId, 301 | (PVOID)INPUT(PWRITE_PROCESS_MEMORY_INPUT)->VirtualAddress, 302 | (PVOID)INPUT(PWRITE_PROCESS_MEMORY_INPUT)->Buffer, 303 | INPUT(PWRITE_PROCESS_MEMORY_INPUT)->BytesToWrite, 304 | TRUE, 305 | (MEMORY_ACCESS_TYPE)INPUT(PWRITE_PROCESS_MEMORY_INPUT)->AccessType 306 | ); 307 | SET_RESPONSE_LENGTH(sizeof(BOOL)); 308 | break; 309 | 310 | case RAISE_IOPL_BY_TF: 311 | #ifdef _AMD64_ 312 | RaiseIOPLByTrapFrame(); 313 | #else 314 | Status = STATUS_NOT_IMPLEMENTED; 315 | #endif 316 | break; 317 | 318 | case RESET_IOPL_BY_TF: 319 | #ifdef _AMD64_ 320 | ResetIOPLByTrapFrame(); 321 | #else 322 | Status = STATUS_NOT_IMPLEMENTED; 323 | #endif 324 | break; 325 | 326 | case RAISE_IOPL_BY_TF_SCAN: 327 | RaiseIOPLByTrapFrameScan(); 328 | break; 329 | 330 | case RESET_IOPL_BY_TF_SCAN: 331 | ResetIOPLByTrapFrameScan(); 332 | break; 333 | 334 | case RAISE_IOPL_BY_TSS: 335 | #ifdef _X86_ 336 | RaiseIOPLByTSS(); 337 | #else 338 | Status = STATUS_NOT_IMPLEMENTED; 339 | #endif 340 | break; 341 | 342 | case RESET_IOPL_BY_TSS: 343 | #ifdef _x86_ 344 | ResetIOPLByTSS(); 345 | #else 346 | Status = STATUS_NOT_IMPLEMENTED; 347 | #endif 348 | break; 349 | 350 | case RAISE_IOPM: 351 | #ifdef _X86_ 352 | *OUTPUT(PNTSTATUS) = RaiseIOPM((HANDLE)*INPUT(PUINT64)); 353 | SET_RESPONSE_LENGTH(sizeof(NTSTATUS)); 354 | #else 355 | Status = STATUS_NOT_IMPLEMENTED; 356 | #endif 357 | break; 358 | 359 | case RESET_IOPM: 360 | #ifdef _X86_ 361 | *OUTPUT(PNTSTATUS) = ResetIOPM((HANDLE)*INPUT(PUINT64)); 362 | SET_RESPONSE_LENGTH(sizeof(NTSTATUS)); 363 | #else 364 | Status = STATUS_NOT_IMPLEMENTED; 365 | #endif 366 | break; 367 | 368 | case KILL_PROCESS: 369 | KillProcess((HANDLE)*INPUT(PUINT64)); 370 | break; 371 | 372 | // Protection: 373 | 374 | case ADD_PROTECTED_PROCESS: 375 | AddProtectedProcess( 376 | (HANDLE)INPUT(PADD_REMOVE_PROCESS_INPUT)->ProcessId, 377 | (HANDLE)INPUT(PADD_REMOVE_PROCESS_INPUT)->DefenderId 378 | ); 379 | break; 380 | 381 | case REMOVE_PROTECTED_PROCESS: 382 | RemoveProtectedProcess( 383 | (HANDLE)INPUT(PADD_REMOVE_PROCESS_INPUT)->ProcessId, 384 | (HANDLE)INPUT(PADD_REMOVE_PROCESS_INPUT)->DefenderId 385 | ); 386 | break; 387 | 388 | case IS_PROCESS_PROTECTED: 389 | *OUTPUT(PBOOL) = IsProcessProtected((HANDLE)*INPUT(PUINT64), ANY_PROCESS) == PROCESS_PROTECTED; 390 | SET_RESPONSE_LENGTH(sizeof(BOOL)); 391 | break; 392 | 393 | case PRINT_PROTECTED_PROCESSES: 394 | PrintProtectedProcessesList(); 395 | break; 396 | 397 | // PCI: 398 | 399 | case READ_PCI_CONFIG: 400 | OUTPUT(PREAD_PCI_CONFIG_OUTPUT)->Status = ReadPciConfig( 401 | INPUT(PREAD_PCI_CONFIG_INPUT)->PciAddress, 402 | INPUT(PREAD_PCI_CONFIG_INPUT)->PciOffset, 403 | (PVOID)INPUT(PREAD_PCI_CONFIG_INPUT)->Buffer, 404 | INPUT(PREAD_PCI_CONFIG_INPUT)->BufferSize, 405 | &OUTPUT(PREAD_PCI_CONFIG_OUTPUT)->BytesRead 406 | ); 407 | SET_RESPONSE_LENGTH(sizeof(READ_PCI_CONFIG_OUTPUT)); 408 | break; 409 | 410 | case WRITE_PCI_CONFIG: 411 | OUTPUT(PWRITE_PCI_CONFIG_OUTPUT)->Status = WritePciConfig( 412 | INPUT(PWRITE_PCI_CONFIG_INPUT)->PciAddress, 413 | INPUT(PWRITE_PCI_CONFIG_INPUT)->PciOffset, 414 | (PVOID)INPUT(PWRITE_PCI_CONFIG_INPUT)->Buffer, 415 | INPUT(PWRITE_PCI_CONFIG_INPUT)->BufferSize, 416 | &OUTPUT(PWRITE_PCI_CONFIG_OUTPUT)->BytesWritten 417 | ); 418 | SET_RESPONSE_LENGTH(sizeof(WRITE_PCI_CONFIG_OUTPUT)); 419 | break; 420 | 421 | // Other: 422 | 423 | case STALL_EXECUTION_PROCESSOR: 424 | KeStallExecutionProcessor(*INPUT(PULONG)); 425 | break; 426 | 427 | case BUG_CHECK: 428 | KeBugCheck(*INPUT(PULONG)); 429 | break; 430 | 431 | case BUG_CHECK_EX: 432 | KeBugCheckEx( 433 | INPUT(PBUG_CHECK_EX_INPUT)->BugCheckCode, 434 | INPUT(PBUG_CHECK_EX_INPUT)->BugCheckParameter1, 435 | INPUT(PBUG_CHECK_EX_INPUT)->BugCheckParameter2, 436 | INPUT(PBUG_CHECK_EX_INPUT)->BugCheckParameter3, 437 | INPUT(PBUG_CHECK_EX_INPUT)->BugCheckParameter4 438 | ); 439 | break; 440 | 441 | default: 442 | Status = STATUS_NOT_IMPLEMENTED; 443 | break; 444 | } 445 | 446 | return Status; 447 | 448 | #ifdef _X86_ 449 | #pragma warning(pop) 450 | #endif 451 | 452 | #undef INPUT 453 | #undef OUTPUT 454 | 455 | #undef SET_RESPONSE_LENGTH 456 | 457 | } -------------------------------------------------------------------------------- /EnjoyTheRing0/IOCTLDispatcher.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ProcessesUtils.h" 4 | #include "NativeFunctions.h" 5 | #include "ShellCode.h" 6 | #include "Protection.h" 7 | #include "PCI.h" 8 | 9 | #define PROTECTION_SUPPORT 10 | 11 | // Обработчики событий драйвера: 12 | VOID OnDriverLoad(); 13 | VOID OnHandleCreate(); 14 | VOID OnHandleClose(); 15 | VOID OnDriverUnload(); 16 | 17 | // Количество открытых дескрипторов драйвера: 18 | static volatile LONG HandlesCount = 0; 19 | 20 | // Информация о запросе: 21 | typedef struct _IOCTL_INFO { 22 | PVOID InputBuffer; 23 | PVOID OutputBuffer; 24 | ULONG InputBufferSize; 25 | ULONG OutputBufferSize; 26 | ULONG ControlCode; 27 | } IOCTL_INFO, *PIOCTL_INFO; 28 | 29 | // Диспетчер запросов: 30 | NTSTATUS FASTCALL DispatchIOCTL(IN PIOCTL_INFO RequestInfo, OUT PULONG ResponseLength); 31 | 32 | #define IOCTL(Code) (CTL_CODE(0x8000, Code, METHOD_NEITHER, FILE_ANY_ACCESS)) 33 | 34 | // NativeFunctions: 35 | 36 | typedef struct _WRITE_IO_PORT_BYTE_INPUT { 37 | WORD PortNumber; 38 | BYTE Data; 39 | } WRITE_IO_PORT_BYTE_INPUT, *PWRITE_IO_PORT_BYTE_INPUT; 40 | 41 | typedef struct _WRITE_IO_PORT_WORD_INPUT { 42 | WORD PortNumber; 43 | WORD Data; 44 | } WRITE_IO_PORT_WORD_INPUT, *PWRITE_IO_PORT_WORD_INPUT; 45 | 46 | typedef struct _WRITE_IO_PORT_DWORD_INPUT { 47 | WORD PortNumber; 48 | DWORD Data; 49 | } WRITE_IO_PORT_DWORD_INPUT, *PWRITE_IO_PORT_DWORD_INPUT; 50 | 51 | typedef struct _WRMSR_INPUT { 52 | ULONG Index; 53 | ULONGLONG Data; 54 | } WRMSR_INPUT, *PWRMSR_INPUT; 55 | 56 | // MemoryUtils: 57 | 58 | typedef struct _MOVE_MEMORY_INPUT { 59 | PVOID64 Destination; 60 | PVOID64 Source; 61 | UINT64 Size; 62 | } MOVE_MEMORY_INPUT, *PMOVE_MEMORY_INPUT; 63 | 64 | typedef struct _COPY_MEMORY_INPUT { 65 | PVOID64 Destination; 66 | PVOID64 Source; 67 | UINT64 Size; 68 | } COPY_MEMORY_INPUT, *PCOPY_MEMORY_INPUT; 69 | 70 | typedef struct _ZERO_MEMORY_INPUT { 71 | PVOID64 Destination; 72 | UINT64 Size; 73 | } ZERO_MEMORY_INPUT, *PZERO_MEMORY_INPUT; 74 | 75 | typedef struct _FILL_MEMORY_INPUT { 76 | PVOID64 Destination; 77 | UINT64 Size; 78 | BYTE FillingByte; 79 | } FILL_MEMORY_INPUT, *PFILL_MEMORY_INPUT; 80 | 81 | typedef struct _EQUAL_MEMORY_INPUT { 82 | PVOID64 Destination; 83 | PVOID64 Source; 84 | UINT64 Size; 85 | } EQUAL_MEMORY_INPUT, *PEQUAL_MEMORY_INPUT; 86 | 87 | typedef struct _ALLOC_PHYSICAL_MEMORY_INPUT { 88 | PHYSICAL_ADDRESS PhysicalAddress; 89 | UINT64 Size; 90 | } ALLOC_PHYSICAL_MEMORY_INPUT, *PALLOC_PHYSICAL_MEMORY_INPUT; 91 | 92 | typedef struct _GET_PHYSICAL_ADDRESS_INPUT { 93 | UINT64 ProcessID; 94 | PVOID64 VirtualAddress; 95 | } GET_PHYSICAL_ADDRESS_INPUT, *PGET_PHYSICAL_ADDRESS_INPUT; 96 | 97 | typedef struct _READ_PHYSICAL_MEMORY_INPUT { 98 | PHYSICAL_ADDRESS PhysicalAddress; 99 | PVOID64 Buffer; 100 | ULONG BufferSize; 101 | } READ_PHYSICAL_MEMORY_INPUT, *PREAD_PHYSICAL_MEMORY_INPUT; 102 | 103 | typedef struct _WRITE_PHYSICAL_MEMORY_INPUT { 104 | PHYSICAL_ADDRESS PhysicalAddress; 105 | PVOID64 Buffer; 106 | ULONG BufferSize; 107 | } WRITE_PHYSICAL_MEMORY_INPUT, *PWRITE_PHYSICAL_MEMORY_INPUT; 108 | 109 | // ShellCode: 110 | 111 | typedef struct _EXECUTE_SHELL_CODE_INPUT { 112 | IN PVOID64 EntryPoint; 113 | IN PVOID64 CodeBlock; 114 | IN OPTIONAL PVOID64 InputData; 115 | IN OPTIONAL PVOID64 OutputData; 116 | IN OPTIONAL PVOID64 Result; 117 | } EXECUTE_SHELL_CODE_INPUT, *PEXECUTE_SHELL_CODE_INPUT; 118 | 119 | // ProcessesUtils: 120 | 121 | typedef struct _ALLOC_VIRTUAL_MEMORY_INPUT { 122 | UINT64 ProcessId; 123 | UINT64 Size; 124 | } ALLOC_VIRTUAL_MEMORY_INPUT, *PALLOC_VIRTUAL_MEMORY_INPUT; 125 | 126 | typedef struct _ALLOC_VIRTUAL_MEMORY_OUTPUT { 127 | PVOID64 VirtualAddress; 128 | NTSTATUS Status; 129 | } ALLOC_VIRTUAL_MEMORY_OUTPUT, *PALLOC_VIRTUAL_MEMORY_OUTPUT; 130 | 131 | typedef struct _FREE_VIRTUAL_MEMORY_INPUT { 132 | UINT64 ProcessId; 133 | PVOID64 VirtualAddress; 134 | } FREE_VIRTUAL_MEMORY_INPUT, *PFREE_VIRTUAL_MEMORY_INPUT; 135 | 136 | typedef struct _MAP_VIRTUAL_MEMORY_INPUT { 137 | UINT64 ProcessId; 138 | PVOID64 VirtualAddress; 139 | PVOID64 MapToVirtualAddress; 140 | ULONG Size; 141 | } MAP_VIRTUAL_MEMORY_INPUT, *PMAP_VIRTUAL_MEMORY_INPUT; 142 | 143 | typedef struct _MAP_VIRTUAL_MEMORY_OUTPUT { 144 | PVOID64 Mdl; 145 | PVOID64 MappedMemory; 146 | } MAP_VIRTUAL_MEMORY_OUTPUT, *PMAP_VIRTUAL_MEMORY_OUTPUT; 147 | 148 | typedef struct _UNMAP_VIRTUAL_MEMORY_INPUT { 149 | PVOID64 Mdl; 150 | PVOID64 MappedMemory; 151 | } UNMAP_VIRTUAL_MEMORY_INPUT, *PUNMAP_VIRTUAL_MEMORY_INPUT; 152 | 153 | typedef struct _READ_PROCESS_MEMORY_INPUT { 154 | UINT64 ProcessId; 155 | PVOID64 VirtualAddress; 156 | PVOID64 Buffer; 157 | ULONG BytesToRead; 158 | BYTE AccessType; 159 | } READ_PROCESS_MEMORY_INPUT, *PREAD_PROCESS_MEMORY_INPUT; 160 | 161 | typedef struct _WRITE_PROCESS_MEMORY_INPUT { 162 | UINT64 ProcessId; 163 | PVOID64 VirtualAddress; 164 | PVOID64 Buffer; 165 | ULONG BytesToWrite; 166 | BYTE AccessType; 167 | } WRITE_PROCESS_MEMORY_INPUT, *PWRITE_PROCESS_MEMORY_INPUT; 168 | 169 | // Protection: 170 | 171 | typedef struct _ADD_REMOVE_PROCESS_INPUT { 172 | UINT64 ProcessId; 173 | UINT64 DefenderId; 174 | } ADD_REMOVE_PROCESS_INPUT, *PADD_REMOVE_PROCESS_INPUT; 175 | 176 | // PCI: 177 | 178 | typedef struct _READ_PCI_CONFIG_INPUT { 179 | ULONG PciAddress; 180 | ULONG PciOffset; 181 | PVOID64 Buffer; 182 | ULONG BufferSize; 183 | } READ_PCI_CONFIG_INPUT, *PREAD_PCI_CONFIG_INPUT; 184 | 185 | typedef struct _READ_PCI_CONFIG_OUTPUT { 186 | NTSTATUS Status; 187 | ULONG BytesRead; 188 | } READ_PCI_CONFIG_OUTPUT, *PREAD_PCI_CONFIG_OUTPUT; 189 | 190 | typedef struct _WRITE_PCI_CONFIG_INPUT { 191 | ULONG PciAddress; 192 | ULONG PciOffset; 193 | PVOID64 Buffer; 194 | ULONG BufferSize; 195 | } WRITE_PCI_CONFIG_INPUT, *PWRITE_PCI_CONFIG_INPUT; 196 | 197 | typedef struct _WRITE_PCI_CONFIG_OUTPUT { 198 | NTSTATUS Status; 199 | ULONG BytesWritten; 200 | } WRITE_PCI_CONFIG_OUTPUT, *PWRITE_PCI_CONFIG_OUTPUT; 201 | 202 | // Other: 203 | 204 | typedef struct _BUG_CHECK_EX_INPUT { 205 | ULONG BugCheckCode; 206 | ULONG BugCheckParameter1; 207 | ULONG BugCheckParameter2; 208 | ULONG BugCheckParameter3; 209 | ULONG BugCheckParameter4; 210 | } BUG_CHECK_EX_INPUT, *PBUG_CHECK_EX_INPUT; 211 | 212 | // DriverFunctions: 213 | 214 | #define GET_HANDLES_COUNT IOCTL(0x800) 215 | 216 | // NativeFunctions: 217 | 218 | #define START_BEEPER IOCTL(0x801) 219 | #define STOP_BEEPER IOCTL(0x802) 220 | #define SET_BEEPER_REGIME IOCTL(0x803) 221 | #define SET_BEEPER_OUT IOCTL(0x804) 222 | #define SET_BEEPER_IN IOCTL(0x805) 223 | #define SET_BEEPER_DIVIDER IOCTL(0x806) 224 | #define SET_BEEPER_FREQUENCY IOCTL(0x807) 225 | 226 | #define READ_IO_PORT_BYTE IOCTL(0x808) 227 | #define READ_IO_PORT_WORD IOCTL(0x809) 228 | #define READ_IO_PORT_DWORD IOCTL(0x80A) 229 | 230 | #define WRITE_IO_PORT_BYTE IOCTL(0x80B) 231 | #define WRITE_IO_PORT_WORD IOCTL(0x80C) 232 | #define WRITE_IO_PORT_DWORD IOCTL(0x80D) 233 | 234 | #define RDPMC IOCTL(0x80E) 235 | #define RDMSR IOCTL(0x80F) 236 | #define WRMSR IOCTL(0x810) 237 | 238 | #define HALT IOCTL(0x811) 239 | 240 | // MemoryUtils: 241 | 242 | #define ALLOC_KERNEL_MEMORY IOCTL(0x812) 243 | #define FREE_KERNEL_MEMORY IOCTL(0x813) 244 | 245 | #define MOVE_MEMORY IOCTL(0x814) 246 | #define COPY_MEMORY IOCTL(0x815) 247 | #define ZERO_MEMORY IOCTL(0x816) 248 | #define FILL_MEMORY IOCTL(0x817) 249 | #define EQUAL_MEMORY IOCTL(0x818) 250 | 251 | #define ALLOC_PHYSICAL_MEMORY IOCTL(0x819) 252 | #define FREE_PHYSICAL_MEMORY IOCTL(0x81A) 253 | #define GET_PHYSICAL_ADDRESS IOCTL(0x81B) 254 | #define READ_PHYSICAL_MEMORY IOCTL(0x81C) 255 | #define WRITE_PHYSICAL_MEMORY IOCTL(0x81D) 256 | 257 | #define READ_DMI_MEMORY IOCTL(0x81E) 258 | 259 | // ShellCode: 260 | 261 | #define EXECUTE_SHELL_CODE IOCTL(0x81F) 262 | 263 | // ProcessesUtils: 264 | 265 | #define ALLOC_VIRTUAL_MEMORY IOCTL(0x820) 266 | #define FREE_VIRTUAL_MEMORY IOCTL(0x821) 267 | 268 | #define MAP_VIRTUAL_MEMORY IOCTL(0x822) 269 | #define UNMAP_VIRTUAL_MEMORY IOCTL(0x823) 270 | 271 | #define READ_PROCESS_MEMORY IOCTL(0x824) 272 | #define WRITE_PROCESS_MEMORY IOCTL(0x825) 273 | 274 | #define RAISE_IOPL_BY_TF IOCTL(0x826) 275 | #define RESET_IOPL_BY_TF IOCTL(0x827) 276 | 277 | #define RAISE_IOPL_BY_TF_SCAN IOCTL(0x828) 278 | #define RESET_IOPL_BY_TF_SCAN IOCTL(0x829) 279 | 280 | #define RAISE_IOPL_BY_TSS IOCTL(0x82A) 281 | #define RESET_IOPL_BY_TSS IOCTL(0x82B) 282 | 283 | #define RAISE_IOPM IOCTL(0x82C) 284 | #define RESET_IOPM IOCTL(0x82D) 285 | 286 | #define KILL_PROCESS IOCTL(0x82E) 287 | 288 | // Protection: 289 | 290 | #define ADD_PROTECTED_PROCESS IOCTL(0x82F) 291 | #define REMOVE_PROTECTED_PROCESS IOCTL(0x830) 292 | #define IS_PROCESS_PROTECTED IOCTL(0x831) 293 | #define PRINT_PROTECTED_PROCESSES IOCTL(0x832) 294 | 295 | // PCI: 296 | 297 | #define READ_PCI_CONFIG IOCTL(0x833) 298 | #define WRITE_PCI_CONFIG IOCTL(0x834) 299 | 300 | // Other: 301 | 302 | #define STALL_EXECUTION_PROCESSOR IOCTL(0x835) 303 | 304 | #define BUG_CHECK IOCTL(0x836) 305 | #define BUG_CHECK_EX IOCTL(0x837) -------------------------------------------------------------------------------- /EnjoyTheRing0/IpiWrapper.c: -------------------------------------------------------------------------------- 1 | #include "IpiWrapper.h" 2 | 3 | // Указатель на функцию/эмулятор интерпроцессорного прерывания: 4 | typedef VOID (NTAPI *_IpiCaller)(PVOID Function, PVOID Argument); 5 | _IpiCaller IpiCaller = (_IpiCaller)NULL; 6 | 7 | 8 | typedef VOID (NTAPI *_IpiProc)(IN PVOID Argument); 9 | 10 | #pragma warning(push) 11 | #pragma warning(disable: 4055) 12 | 13 | VOID NTAPI EmulateIpi(PVOID Function, PVOID Argument) { 14 | KAFFINITY FullProcessorsAffinity = (KAFFINITY)0; 15 | 16 | ULONG ProcessorsCount = KeNumberProcessors; 17 | for (ULONG i = 0; i < ProcessorsCount; i++) { 18 | KAFFINITY CurrentAffinity = (KAFFINITY)(1 << i); 19 | KeSetSystemAffinityThread(CurrentAffinity); 20 | 21 | ((_IpiProc)Function)(Argument); 22 | FullProcessorsAffinity |= CurrentAffinity; 23 | } 24 | 25 | KeSetSystemAffinityThread(FullProcessorsAffinity); 26 | } 27 | 28 | VOID FASTCALL CallIpi(PVOID Function, PVOID Argument) { 29 | if (IpiCaller) { 30 | IpiCaller(Function, Argument); 31 | return; 32 | } 33 | 34 | IpiCaller = (_IpiCaller)GetKernelProcAddress(L"KeIpiGenericCall"); 35 | if (IpiCaller) { 36 | IpiCaller(Function, Argument); 37 | return; 38 | } 39 | 40 | IpiCaller = EmulateIpi; 41 | IpiCaller(Function, Argument); 42 | } 43 | 44 | #pragma warning(pop) -------------------------------------------------------------------------------- /EnjoyTheRing0/IpiWrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ProcessesUtils.h" 4 | 5 | // Вызов KeIpiGenericCall там, где доступно, и эмуляция - где недоступно: 6 | VOID FASTCALL CallIpi(PVOID Function, PVOID Argument); -------------------------------------------------------------------------------- /EnjoyTheRing0/LinkedLists.c: -------------------------------------------------------------------------------- 1 | #include "LinkedLists.h" 2 | 3 | VOID FASTCALL InitializeLinkedList(ULONG DataSize, OUT PLINKED_LIST LinkedList, BOOL IsUserThread) { 4 | InitializeMutex(&LinkedList->Mutex, IsUserThread); 5 | 6 | LinkedList->EntrySize = DataSize + sizeof(LINKED_LIST_ENTRY); 7 | LinkedList->EntriesCount = 0; 8 | LinkedList->LastEntry = NULL; 9 | LinkedList->FirstEntry = NULL; 10 | } 11 | 12 | 13 | BOOL FASTCALL AddLinkedListEntry(IN PLINKED_LIST LinkedList) { 14 | AcquireLock(&LinkedList->Mutex); 15 | 16 | // Если элементов ещё нет: 17 | if (LinkedList->FirstEntry == NULL) { 18 | LinkedList->FirstEntry = GetMem(LinkedList->EntrySize); 19 | LinkedList->LastEntry = LinkedList->FirstEntry; 20 | if (LinkedList->FirstEntry == NULL) goto ReturnFalse; 21 | 22 | LinkedList->FirstEntry->PrevEntry = NULL; 23 | LinkedList->FirstEntry->NextEntry = NULL; 24 | 25 | goto ReturnTrue; 26 | } 27 | 28 | // Если есть - добавляем в конец: 29 | PLINKED_LIST_ENTRY NextEntry = GetMem(LinkedList->EntrySize); 30 | if (NextEntry == NULL) goto ReturnFalse; 31 | 32 | LinkedList->LastEntry->NextEntry = NextEntry; 33 | NextEntry->PrevEntry = LinkedList->LastEntry; 34 | NextEntry->NextEntry = NULL; 35 | LinkedList->LastEntry = NextEntry; 36 | 37 | ReturnTrue: 38 | LinkedList->EntriesCount++; 39 | ReleaseLock(&LinkedList->Mutex); 40 | return TRUE; 41 | 42 | ReturnFalse: 43 | ReleaseLock(&LinkedList->Mutex); 44 | return FALSE; 45 | } 46 | 47 | VOID FASTCALL RemoveLinkedListEntry(IN PLINKED_LIST LinkedList, IN PLINKED_LIST_ENTRY Entry) { 48 | if ((LinkedList == NULL) || (Entry == NULL)) return; 49 | 50 | AcquireLock(&LinkedList->Mutex); 51 | 52 | // Если элемент - единственный: 53 | if ((Entry->PrevEntry == NULL) && (Entry->NextEntry == NULL)) { 54 | LinkedList->FirstEntry = NULL; 55 | LinkedList->LastEntry = NULL; 56 | goto Exit; 57 | } 58 | 59 | // Если элемент - первый в списке: 60 | if (Entry->PrevEntry == NULL) { 61 | ((PLINKED_LIST_ENTRY)Entry->NextEntry)->PrevEntry = NULL; 62 | LinkedList->FirstEntry = Entry->NextEntry; 63 | } else { 64 | ((PLINKED_LIST_ENTRY)Entry->PrevEntry)->NextEntry = Entry->NextEntry; 65 | 66 | // Если элемент был последним в списке: 67 | if (Entry->NextEntry == NULL) { 68 | LinkedList->LastEntry = Entry->PrevEntry; 69 | } else { 70 | ((PLINKED_LIST_ENTRY)Entry->NextEntry)->PrevEntry = Entry->PrevEntry; 71 | } 72 | } 73 | 74 | Exit: 75 | FreeMem(Entry); 76 | LinkedList->EntriesCount--; 77 | ReleaseLock(&LinkedList->Mutex); 78 | } 79 | 80 | VOID FASTCALL ClearLinkedList(IN PLINKED_LIST LinkedList) { 81 | if (LinkedList == NULL) return; 82 | if (LinkedList->EntriesCount == 0) return; 83 | 84 | AcquireLock(&LinkedList->Mutex); 85 | 86 | PLINKED_LIST_ENTRY CurrentEntry = LinkedList->FirstEntry; 87 | while (CurrentEntry) { 88 | PLINKED_LIST_ENTRY NextEntry = CurrentEntry->NextEntry; 89 | FreeMem(CurrentEntry); 90 | CurrentEntry = NextEntry; 91 | } 92 | 93 | LinkedList->FirstEntry = NULL; 94 | LinkedList->LastEntry = NULL; 95 | LinkedList->EntriesCount = 0; 96 | 97 | ReleaseLock(&LinkedList->Mutex); 98 | } 99 | 100 | VOID FASTCALL ForEachLinkedListElement(IN PLINKED_LIST LinkedList, IN _LinkedListCallback Callback, IN PVOID CallbackArgument) { 101 | if ((LinkedList == NULL) || (Callback == NULL)) return; 102 | if (LinkedList->EntriesCount == 0) return; 103 | 104 | AcquireLock(&LinkedList->Mutex); 105 | 106 | PLINKED_LIST_ENTRY Entry = LinkedList->FirstEntry; 107 | while (Entry) { 108 | PLINKED_LIST_ENTRY NextEntry = Entry->NextEntry; 109 | LINKED_LIST_ACTION Action = Callback(&Entry->Data, CallbackArgument); 110 | 111 | switch (Action) { 112 | case LL_CONTINUE: goto Continue; 113 | case LL_BREAK: goto Exit; 114 | case LL_REMOVE: 115 | RemoveLinkedListEntry(LinkedList, Entry); 116 | goto Continue; 117 | case LL_REMOVE | LL_BREAK: 118 | RemoveLinkedListEntry(LinkedList, Entry); 119 | goto Exit; 120 | } 121 | 122 | Continue: 123 | Entry = NextEntry; 124 | } 125 | 126 | Exit: 127 | ReleaseLock(&LinkedList->Mutex); 128 | return; 129 | } -------------------------------------------------------------------------------- /EnjoyTheRing0/LinkedLists.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Synchronization.h" 4 | 5 | #pragma warning(push) 6 | #pragma warning(disable: 4200) 7 | typedef struct _LINKED_LIST_ENTRY { 8 | volatile PVOID PrevEntry; 9 | volatile PVOID NextEntry; 10 | BYTE Data[]; 11 | } LINKED_LIST_ENTRY, *PLINKED_LIST_ENTRY; 12 | #pragma warning(pop) 13 | 14 | typedef struct _LINKED_LIST { 15 | MUTEX Mutex; 16 | volatile SIZE_T EntrySize; 17 | volatile SIZE_T EntriesCount; 18 | volatile PLINKED_LIST_ENTRY FirstEntry; 19 | volatile PLINKED_LIST_ENTRY LastEntry; 20 | } LINKED_LIST, *PLINKED_LIST; 21 | 22 | #define GetLLDataPtr(Entry) (&((Entry)->Data)) 23 | 24 | typedef enum _LINKED_LIST_ACTION { 25 | LL_CONTINUE, 26 | LL_BREAK, 27 | LL_REMOVE 28 | } LINKED_LIST_ACTION; 29 | 30 | typedef LINKED_LIST_ACTION (FASTCALL *_LinkedListCallback)(IN PVOID Element, IN PVOID Argument); 31 | 32 | VOID FASTCALL InitializeLinkedList(ULONG DataSize, OUT PLINKED_LIST LinkedList, BOOL IsUserThread); 33 | BOOL FASTCALL AddLinkedListEntry(IN PLINKED_LIST LinkedList); 34 | VOID FASTCALL RemoveLinkedListEntry(IN PLINKED_LIST LinkedList, IN PLINKED_LIST_ENTRY Entry); 35 | VOID FASTCALL ClearLinkedList(IN PLINKED_LIST LinkedList); 36 | VOID FASTCALL ForEachLinkedListElement(IN PLINKED_LIST LinkedList, IN _LinkedListCallback Callback, IN PVOID CallbackArgument); -------------------------------------------------------------------------------- /EnjoyTheRing0/Main.c: -------------------------------------------------------------------------------- 1 | /* 2 | Подробности: 3 | - В.П.Солдатов "Программирование драйверов Windows: http://drp.su/ru/driver_dev/ 4 | */ 5 | 6 | #include "IOCTLDispatcher.h" 7 | 8 | // Имена устройства и символьной ссылки: 9 | static PCWSTR DeviceNameStr = L"\\Device\\EnjoyTheRing0"; 10 | static PCWSTR DeviceLinkStr = L"\\??\\EnjoyTheRing0"; 11 | 12 | // Драйверные функции: 13 | NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath); 14 | VOID DriverUnload (IN PDRIVER_OBJECT DriverObject); 15 | NTSTATUS DriverCreate (IN PDEVICE_OBJECT DeviceObject, IN PIRP IORequestPacket); 16 | NTSTATUS DriverCleanup (IN PDEVICE_OBJECT DeviceObject, IN PIRP IORequestPacket); 17 | NTSTATUS DriverClose (IN PDEVICE_OBJECT DeviceObject, IN PIRP IORequestPacket); 18 | NTSTATUS DriverControl (IN PDEVICE_OBJECT DeviceObject, IN PIRP IORequestPacket); 19 | 20 | #pragma alloc_text("INIT", DriverEntry) 21 | 22 | // Загрузка драйвера в систему: 23 | NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) 24 | { 25 | UNREFERENCED_PARAMETER(RegistryPath); 26 | 27 | NTSTATUS Status; 28 | 29 | // Назначаем события: 30 | DriverObject->DriverUnload = DriverUnload; 31 | DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverCreate; 32 | DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DriverCleanup; 33 | DriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverClose; 34 | DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverControl; 35 | 36 | // Создаём устройство, ассоциирующееся с драйвером: 37 | UNICODE_STRING DeviceName; 38 | PDEVICE_OBJECT DeviceObject; 39 | RtlInitUnicodeString(&DeviceName, DeviceNameStr); 40 | Status = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject); 41 | 42 | if (!NT_SUCCESS(Status)) { 43 | DbgPrint("[ETR0]: IoCreateDevice Error!\r\n"); 44 | return Status; 45 | } 46 | 47 | // Создаём ссылку на устройство: 48 | UNICODE_STRING DeviceLink; 49 | RtlInitUnicodeString(&DeviceLink, DeviceLinkStr); 50 | Status = IoCreateSymbolicLink(&DeviceLink, &DeviceName); 51 | 52 | if (!NT_SUCCESS(Status)) { 53 | DbgPrint("[ETR0]: IoCreateSymbolicLink Error!\r\n"); 54 | IoDeleteDevice(DeviceObject); 55 | return Status; 56 | } 57 | 58 | DbgPrint("[ETR0]: Successfully loaded!\r\n"); 59 | 60 | OnDriverLoad(); 61 | 62 | return STATUS_SUCCESS; 63 | } 64 | 65 | 66 | // Событие обработки IOCTL: 67 | NTSTATUS DriverControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP IORequestPacket) 68 | { 69 | UNREFERENCED_PARAMETER(DeviceObject); 70 | 71 | // Получаем указатель на стек запросов и код (IOCTL) полученного запроса: 72 | PIO_STACK_LOCATION IRPStack = IoGetCurrentIrpStackLocation(IORequestPacket); 73 | 74 | // Собираем в структуру информацию о запросе: 75 | IOCTL_INFO RequestInfo; 76 | RequestInfo.ControlCode = IRPStack->Parameters.DeviceIoControl.IoControlCode; 77 | RequestInfo.InputBuffer = IRPStack->Parameters.DeviceIoControl.Type3InputBuffer; 78 | RequestInfo.OutputBuffer = IORequestPacket->UserBuffer; 79 | RequestInfo.InputBufferSize = IRPStack->Parameters.DeviceIoControl.InputBufferLength; 80 | RequestInfo.OutputBufferSize = IRPStack->Parameters.DeviceIoControl.OutputBufferLength; 81 | 82 | // Определяем возвращаемое количество байт: 83 | ULONG ResponseLength = 0; 84 | 85 | // Обрабатываем IRP: 86 | NTSTATUS Status; 87 | __try { 88 | Status = DispatchIOCTL(&RequestInfo, &ResponseLength); 89 | } __except (EXCEPTION_EXECUTE_HANDLER) { 90 | Status = STATUS_UNSUCCESSFUL; 91 | DbgPrint("[ETR0]: Exception catched!\r\n"); 92 | } 93 | 94 | // Завершение запроса: 95 | IORequestPacket->IoStatus.Status = Status; 96 | IORequestPacket->IoStatus.Information = ResponseLength; 97 | IoCompleteRequest(IORequestPacket, IO_NO_INCREMENT); 98 | 99 | return Status; 100 | } 101 | 102 | // Событие создания драйвера (открытия устройства через CreateFile): 103 | NTSTATUS DriverCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP IORequestPacket) 104 | { 105 | UNREFERENCED_PARAMETER(DeviceObject); 106 | 107 | OnHandleCreate(); 108 | 109 | IORequestPacket->IoStatus.Status = STATUS_SUCCESS; 110 | IORequestPacket->IoStatus.Information = 0; 111 | IoCompleteRequest(IORequestPacket, IO_NO_INCREMENT); 112 | return STATUS_SUCCESS; 113 | } 114 | 115 | // Событие очистки ресурсов драйвера: 116 | NTSTATUS DriverCleanup(IN PDEVICE_OBJECT DeviceObject, IN PIRP IORequestPacket) 117 | { 118 | UNREFERENCED_PARAMETER(DeviceObject); 119 | 120 | IORequestPacket->IoStatus.Status = STATUS_SUCCESS; 121 | IORequestPacket->IoStatus.Information = 0; 122 | IoCompleteRequest(IORequestPacket, IO_NO_INCREMENT); 123 | return STATUS_SUCCESS; 124 | } 125 | 126 | // Событие закрытия драйвера (закрытия устройства через CloseHandle): 127 | NTSTATUS DriverClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP IORequestPacket) 128 | { 129 | UNREFERENCED_PARAMETER(DeviceObject); 130 | 131 | OnHandleClose(); 132 | 133 | IORequestPacket->IoStatus.Status = STATUS_SUCCESS; 134 | IORequestPacket->IoStatus.Information = 0; 135 | IoCompleteRequest(IORequestPacket, IO_NO_INCREMENT); 136 | 137 | return STATUS_SUCCESS; 138 | } 139 | 140 | // Выгрузка драйвера: 141 | VOID DriverUnload(IN PDRIVER_OBJECT DriverObject) 142 | { 143 | OnDriverUnload(); 144 | 145 | UNICODE_STRING DeviceLink; 146 | RtlInitUnicodeString(&DeviceLink, DeviceLinkStr); 147 | 148 | IoDeleteSymbolicLink(&DeviceLink); 149 | IoDeleteDevice(DriverObject->DeviceObject); 150 | 151 | DbgPrint("[ETR0]: Successfully unloaded!\r\n"); 152 | 153 | return; 154 | } -------------------------------------------------------------------------------- /EnjoyTheRing0/MemoryAccessController.c: -------------------------------------------------------------------------------- 1 | #include "MemoryAccessController.h" 2 | 3 | static LONG WriteProtectionDisablesCount = 0; 4 | static LONG SmepSmapDisablesCount = 0; 5 | 6 | ULONG_PTR NTAPI GlobalDisableWPCallback(IN ULONG_PTR Argument) { 7 | UNREFERENCED_PARAMETER(Argument); 8 | DisableWriteProtection(); 9 | return (ULONG_PTR)NULL; 10 | } 11 | 12 | ULONG_PTR NTAPI GlobalEnableWPCallback(IN ULONG_PTR Argument) { 13 | UNREFERENCED_PARAMETER(Argument); 14 | EnableWriteProtection(); 15 | return (ULONG_PTR)NULL; 16 | } 17 | 18 | ULONG_PTR NTAPI GlobalDisableSmepSmapCallback(IN ULONG_PTR Argument) { 19 | UNREFERENCED_PARAMETER(Argument); 20 | if (IsSMEPPresent()) DisableSMEP(); 21 | if (IsSMAPPresent()) DisableSMAP(); 22 | return (ULONG_PTR)NULL; 23 | } 24 | 25 | ULONG_PTR NTAPI GlobalEnableSmepSmapCallback(IN ULONG_PTR Argument) { 26 | UNREFERENCED_PARAMETER(Argument); 27 | if (IsSMEPPresent()) EnableSMEP(); 28 | if (IsSMAPPresent()) EnableSMAP(); 29 | return (ULONG_PTR)NULL; 30 | } 31 | 32 | #pragma warning(push) 33 | #pragma warning(disable: 4152) 34 | 35 | VOID GlobalDisableWriteProtection() { 36 | CallIpi(&GlobalDisableWPCallback, NULL); 37 | InterlockedIncrement(&WriteProtectionDisablesCount); 38 | } 39 | 40 | VOID GlobalEnableWriteProtection() { 41 | if (WriteProtectionDisablesCount == 0) return; 42 | CallIpi(&GlobalEnableWPCallback, NULL); 43 | InterlockedDecrement(&WriteProtectionDisablesCount); 44 | } 45 | 46 | VOID GlobalDisableSmepSmap() { 47 | CallIpi(&GlobalDisableSmepSmapCallback, NULL); 48 | InterlockedIncrement(&SmepSmapDisablesCount); 49 | } 50 | 51 | VOID GlobalEnableSmepSmap() { 52 | if (SmepSmapDisablesCount == 0) return; 53 | CallIpi(&GlobalEnableSmepSmapCallback, NULL); 54 | InterlockedDecrement(&SmepSmapDisablesCount); 55 | } 56 | 57 | #pragma warning(pop) -------------------------------------------------------------------------------- /EnjoyTheRing0/MemoryAccessController.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | WriteProtection - Защита от записи в RX-регионы 5 | SMEP/SMAP - Защита от исполнения неисполняемых страниц (только Intel) 6 | */ 7 | 8 | #include "IpiWrapper.h" 9 | #include "NativeFunctions.h" 10 | 11 | VOID GlobalDisableWriteProtection(); 12 | VOID GlobalEnableWriteProtection(); 13 | VOID GlobalDisableSmepSmap(); 14 | VOID GlobalEnableSmepSmap(); 15 | -------------------------------------------------------------------------------- /EnjoyTheRing0/MemoryUtils.c: -------------------------------------------------------------------------------- 1 | #include "MemoryUtils.h" 2 | 3 | static const unsigned long MemoryTag = 'KBLI'; 4 | 5 | PVOID GetMem(SIZE_T Bytes) { 6 | if (Bytes == 0) return NULL; 7 | PVOID Memory = ExAllocatePoolWithTag(NonPagedPool, Bytes, MemoryTag); 8 | if (Memory) RtlSecureZeroMemory(Memory, Bytes); 9 | return Memory; 10 | } 11 | 12 | VOID FreeMem(PVOID Pointer) { 13 | if (Pointer) ExFreePoolWithTag(Pointer, MemoryTag); 14 | } 15 | 16 | 17 | 18 | PVOID AllocPhysicalMemory(PHYSICAL_ADDRESS PhysicalAddress, SIZE_T NumberOfBytes) { 19 | PhysicalAddress.QuadPart += (NumberOfBytes - 1); 20 | return MmAllocateContiguousMemory(NumberOfBytes, PhysicalAddress); 21 | } 22 | 23 | PVOID AllocCacheablePhysicalMemory(PHYSICAL_ADDRESS PhysicalAddress, SIZE_T NumberOfBytes, MEMORY_CACHING_TYPE CachingType) { 24 | PHYSICAL_ADDRESS HighestAddress; 25 | PHYSICAL_ADDRESS BoundaryAddressMultiple; 26 | HighestAddress.QuadPart = PhysicalAddress.QuadPart + (NumberOfBytes - 1); 27 | BoundaryAddressMultiple.QuadPart = 0; 28 | return MmAllocateContiguousMemorySpecifyCache(NumberOfBytes, PhysicalAddress, HighestAddress, BoundaryAddressMultiple, CachingType); 29 | } 30 | 31 | VOID FreePhysicalMemory(PVOID BaseAddress) { 32 | MmFreeContiguousMemory(BaseAddress); 33 | } 34 | 35 | PHYSICAL_ADDRESS GetPhysicalAddress(PVOID BaseVirtualAddress) { 36 | if (!MmIsAddressValid(BaseVirtualAddress)) { 37 | PHYSICAL_ADDRESS PhysicalAddress; 38 | PhysicalAddress.QuadPart = 0; 39 | return PhysicalAddress; 40 | } 41 | return MmGetPhysicalAddress(BaseVirtualAddress); 42 | } 43 | 44 | PVOID MapPhysicalMemory(PHYSICAL_ADDRESS PhysicalAddress, SIZE_T NumberOfBytes, MEMORY_CACHING_TYPE CachingType) { 45 | return MmMapIoSpace(PhysicalAddress, NumberOfBytes, CachingType); 46 | } 47 | 48 | #ifdef ENABLE_WIN10_EXTENSIONS 49 | PVOID MapPhysicalMemoryWithProtect(PHYSICAL_ADDRESS PhysicalAddress, SIZE_T NumberOfBytes, ULONG Protect) { 50 | return MmMapIoSpaceEx(PhysicalAddress, NumberOfBytes, Protect); 51 | } 52 | #endif 53 | 54 | BOOL ReadPhysicalMemory(PHYSICAL_ADDRESS PhysicalAddress, PVOID Buffer, SIZE_T BufferSize) { 55 | PVOID VirtualAddress = MmMapIoSpace(PhysicalAddress, BufferSize, MmNonCached); 56 | if (VirtualAddress == NULL) return FALSE; 57 | 58 | RtlCopyMemory(Buffer, VirtualAddress, BufferSize); 59 | 60 | MmUnmapIoSpace(VirtualAddress, BufferSize); 61 | return TRUE; 62 | } 63 | 64 | BOOL WritePhysicalMemory(PHYSICAL_ADDRESS PhysicalAddress, PVOID Buffer, SIZE_T BufferSize) { 65 | PVOID VirtualAddress = MmMapIoSpace(PhysicalAddress, BufferSize, MmNonCached); 66 | if (VirtualAddress == NULL) return FALSE; 67 | 68 | RtlCopyMemory(VirtualAddress, Buffer, BufferSize); 69 | 70 | MmUnmapIoSpace(VirtualAddress, BufferSize); 71 | return TRUE; 72 | } 73 | 74 | VOID UnmapPhysicalMemory(PVOID BaseVirtualAddress, SIZE_T NumberOfBytes) { 75 | MmUnmapIoSpace(BaseVirtualAddress, NumberOfBytes); 76 | } 77 | 78 | BOOL ReadDmiMemory(PVOID Buffer, SIZE_T BufferSize) { 79 | if (BufferSize < DMI_SIZE) return FALSE; 80 | 81 | PHYSICAL_ADDRESS DmiAddress; 82 | DmiAddress.QuadPart = 0xF0000; 83 | PVOID DmiMemory = MmMapIoSpace(DmiAddress, DMI_SIZE, MmNonCached); 84 | BOOL Status = DmiMemory != NULL; 85 | if (Status) { 86 | RtlCopyMemory(Buffer, DmiMemory, DMI_SIZE); 87 | MmUnmapIoSpace(DmiMemory, DMI_SIZE); 88 | } 89 | return Status; 90 | } 91 | 92 | BOOL SecureVirtualMemory(PVOID VirtualAddress, SIZE_T NumberOfBytes, ULONG ProbeMode, OUT PHANDLE SecureHandle) { 93 | if (SecureHandle == NULL) return FALSE; 94 | *SecureHandle = MmSecureVirtualMemory(VirtualAddress, NumberOfBytes, ProbeMode); 95 | return SecureHandle != NULL; 96 | } 97 | 98 | BOOL UnsecureVirtualMemory(HANDLE SecureHandle) { 99 | if (SecureHandle) MmUnsecureVirtualMemory(SecureHandle); 100 | return SecureHandle != NULL; 101 | } 102 | 103 | BOOL IsAddressValid(PVOID VirtualAddress) { 104 | return (BOOL)MmIsAddressValid(VirtualAddress); 105 | } 106 | 107 | BOOL IsUsermodeMemoryReadable(PVOID Address, SIZE_T NumberOfBytes, ULONG RequiredAlignment) { 108 | __try { 109 | ProbeForRead(Address, NumberOfBytes, RequiredAlignment); 110 | return TRUE; 111 | } __except (EXCEPTION_EXECUTE_HANDLER) { 112 | return FALSE; 113 | } 114 | } 115 | 116 | BOOL IsUsermodeMemoryWriteable(PVOID Address, SIZE_T NumberOfBytes, ULONG RequiredAlignment) { 117 | __try { 118 | ProbeForWrite(Address, NumberOfBytes, RequiredAlignment); 119 | return TRUE; 120 | } __except (EXCEPTION_EXECUTE_HANDLER) { 121 | return FALSE; 122 | } 123 | } 124 | 125 | #ifdef ENABLE_WIN10_EXTENSIONS 126 | NTSTATUS CopyMemoryEx(PVOID Destination, MM_COPY_ADDRESS Source, SIZE_T NumberOfBytes, ULONG Flags, OUT PSIZE_T BytesCopied) { 127 | return MmCopyMemory(Destination, Source, NumberOfBytes, Flags, BytesCopied); 128 | } 129 | #endif 130 | -------------------------------------------------------------------------------- /EnjoyTheRing0/MemoryUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | //#define ENABLE_WIN10_EXTENSIONS 9 | 10 | // Выделение и освобождение виртуальной NonPaged-памяти из пула: 11 | PVOID GetMem(SIZE_T Bytes); 12 | VOID FreeMem(PVOID Pointer); 13 | 14 | // Работа с памятью: 15 | #define CopyMemory(Destination, Source, Length) RtlCopyMemory(Destination, Source, Length) 16 | #define MoveMemory(Destination, Source, Length) RtlMoveMemory(Destination, Source, Length) 17 | #define ZeroMemory(Destination, Length) RtlZeroMemory(Destination, Length) 18 | #define FillMemory(Destination, Length, Fill) RtlFillMemory(Destination, Length, Fill) 19 | #define EqualMemory(Destination, Source, Length) RtlEqualMemory(Destination, Source, Length) 20 | 21 | // Выделение непрерывных участков физической памяти: 22 | PVOID AllocPhysicalMemory(PHYSICAL_ADDRESS PhysicalAddress, SIZE_T NumberOfBytes); 23 | PVOID AllocCacheablePhysicalMemory(PHYSICAL_ADDRESS PhysicalAddress, SIZE_T NumberOfBytes, MEMORY_CACHING_TYPE CachingType); 24 | VOID FreePhysicalMemory(PVOID BaseAddress); 25 | 26 | /* Работа с физической памятью: 27 | GetPhysicalAddress - получить физический адрес виртуальной памяти в контексте текущего процесса 28 | MapPhysicalMemory - отобразить физическую память на виртуальную с настройкой кэширования 29 | MapPhysicalMemoryWithProtect - отобразить физическую память на виртуальную с настройкой прав доступа 30 | ReadPhysicalMemory - прочитать блок физической памяти в ядерный буфер 31 | WritePhysicalMemory - записать содержимое ядерного буфера в физическую память 32 | UnmapPhysicalMemory - размапить физическую память 33 | */ 34 | PHYSICAL_ADDRESS GetPhysicalAddress (PVOID BaseVirtualAddress); 35 | PVOID MapPhysicalMemory (PHYSICAL_ADDRESS PhysicalAddress, SIZE_T NumberOfBytes, MEMORY_CACHING_TYPE CachingType); 36 | #ifdef ENABLE_WIN10_EXTENSIONS 37 | PVOID MapPhysicalMemoryWithProtect(PHYSICAL_ADDRESS PhysicalAddress, SIZE_T NumberOfBytes, ULONG Protect); 38 | #endif 39 | BOOL ReadPhysicalMemory (PHYSICAL_ADDRESS PhysicalAddress, PVOID Buffer, SIZE_T BufferSize); 40 | BOOL WritePhysicalMemory (PHYSICAL_ADDRESS PhysicalAddress, PVOID Buffer, SIZE_T BufferSize); 41 | VOID UnmapPhysicalMemory (PVOID BaseVirtualAddress, SIZE_T NumberOfBytes); 42 | 43 | // Чтение DMI - структуры SMBIOS: 44 | #define DMI_SIZE 65536 45 | BOOL ReadDmiMemory(PVOID Buffer, SIZE_T BufferSize); 46 | 47 | // "Защитить" память от урезания прав доступа или освобождения (ProbeMode - самый "ограничительный" приемлемый режим): 48 | BOOL SecureVirtualMemory(PVOID VirtualAddress, SIZE_T NumberOfBytes, ULONG ProbeMode, OUT PHANDLE SecureHandle); 49 | BOOL UnsecureVirtualMemory(HANDLE SecureHandle); 50 | 51 | // Проверка на валидность адреса: 52 | BOOL IsAddressValid(PVOID VirtualAddress); 53 | 54 | // Проверка на возможность чтения\записи юзермодной памяти и "выровненности" адреса: 55 | #define NON_ALIGNED 1 56 | BOOL IsUsermodeMemoryReadable (PVOID Address, SIZE_T NumberOfBytes, ULONG RequiredAlignment); 57 | BOOL IsUsermodeMemoryWriteable(PVOID Address, SIZE_T NumberOfBytes, ULONG RequiredAlignment); 58 | 59 | #ifdef ENABLE_WIN10_EXTENSIONS 60 | NTSTATUS CopyMemoryEx(PVOID Destination, MM_COPY_ADDRESS Source, SIZE_T NumberOfBytes, ULONG Flags, OUT PSIZE_T BytesCopied); 61 | #endif 62 | -------------------------------------------------------------------------------- /EnjoyTheRing0/NativeFunctions.c: -------------------------------------------------------------------------------- 1 | #include "MemoryUtils.h" 2 | #include "NativeFunctions.h" 3 | 4 | PTSS GetTSSPointer(OUT OPTIONAL PULONG TSSLimit) { 5 | TR TaskRegister; 6 | GDTR GDTRegister; 7 | 8 | IdtGdtTrOperation(STR, &TaskRegister); 9 | IdtGdtTrOperation(SGDT, &GDTRegister); 10 | 11 | PGDTENTRY TSSDescriptor = GDTRegister.Base + TaskRegister.SelectorIndex; 12 | 13 | if (TSSLimit) *TSSLimit = ExtractLimitFromGdtEntry(TSSDescriptor); 14 | return ExtractBaseFromGdtEntry(TSSDescriptor); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /EnjoyTheRing0/NativeFunctions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | // I/O: 8 | 9 | VOID __fastcall StartBeeper(); 10 | VOID __fastcall StopBeeper(); 11 | VOID __fastcall SetBeeperRegime(); 12 | VOID __fastcall SetBeeperOut(); 13 | VOID __fastcall SetBeeperIn(); 14 | VOID __fastcall SetBeeperDivider(WORD Divider); 15 | VOID __fastcall SetBeeperFrequency(WORD Frequency); 16 | 17 | VOID __fastcall WriteIoPortByte (WORD PortNumber, BYTE Data); 18 | VOID __fastcall WriteIoPortWord (WORD PortNumber, WORD Data); 19 | VOID __fastcall WriteIoPortDword(WORD PortNumber, DWORD Data); 20 | 21 | BYTE __fastcall ReadIoPortByte (WORD PortNumber); 22 | WORD __fastcall ReadIoPortWord (WORD PortNumber); 23 | DWORD __fastcall ReadIoPortDword(WORD PortNumber); 24 | 25 | // Interrupts: 26 | 27 | #pragma pack(push, 1) 28 | typedef struct _REGISTERS_STATE { 29 | #ifdef _AMD64_ 30 | DWORD64 RAX; 31 | DWORD64 RCX; 32 | DWORD64 RDX; 33 | #else 34 | DWORD32 EAX; 35 | DWORD32 ECX; 36 | DWORD32 EDX; 37 | #endif 38 | } REGISTERS_STATE, *PREGISTERS_STATE; 39 | #pragma pack(pop) 40 | 41 | VOID __fastcall _CLI(); 42 | VOID __fastcall _STI(); 43 | VOID __fastcall _HLT(); 44 | VOID __fastcall _INT(BYTE InterruptNumber, PREGISTERS_STATE RegistersState); 45 | 46 | // MSR: 47 | 48 | ULONGLONG __fastcall _RDPMC(ULONG Index); 49 | ULONGLONG __fastcall _RDMSR(ULONG Index); 50 | VOID __fastcall _WRMSR(ULONG Index, PULONGLONG Value); 51 | 52 | // SystemRegisters: 53 | 54 | /* 55 | CR0 - содержимое контрольных битов 56 | CR2, CR3 - для страничной трансляции 57 | CR4 - биты, определяющие системные возможности 58 | CR8 - изменяет приоритет внешних прерываний 59 | Остальные CR не используются, при попытке обращения будет сгенерировано #UD (Undefined Opcode) 60 | 61 | DR0..DR3 - линейные адреса брейкпоинтов 62 | DR4, DR5 - связаны с DR6 и DR7, если CR4.DE = 0 63 | DR6 - статусный отладочный регистр 64 | DR7 - контрольный отладочный регистр 65 | Остальные DR зарезервированы, при обращении будет сгенерировано #UD 66 | */ 67 | 68 | #define READ_CR (BYTE)0x20 69 | #define WRITE_CR (BYTE)0x22 70 | #define READ_DR (BYTE)0x21 71 | #define WRITE_DR (BYTE)0x23 72 | #define SYS_REG_OPERATION(Operation, RegisterNumber) ((WORD)(((BYTE)Operation << 8) | (BYTE)RegisterNumber)) 73 | 74 | #define READ_CR0 (WORD)SYS_REG_OPERATION(READ_CR, 0) 75 | #define READ_CR2 (WORD)SYS_REG_OPERATION(READ_CR, 2) 76 | #define READ_CR3 (WORD)SYS_REG_OPERATION(READ_CR, 3) 77 | #define READ_CR4 (WORD)SYS_REG_OPERATION(READ_CR, 4) 78 | #define READ_CR8 (WORD)SYS_REG_OPERATION(READ_CR, 8) 79 | 80 | #define WRITE_CR0 (WORD)SYS_REG_OPERATION(WRITE_CR, 0) 81 | #define WRITE_CR2 (WORD)SYS_REG_OPERATION(WRITE_CR, 2) 82 | #define WRITE_CR3 (WORD)SYS_REG_OPERATION(WRITE_CR, 3) 83 | #define WRITE_CR4 (WORD)SYS_REG_OPERATION(WRITE_CR, 4) 84 | #define WRITE_CR8 (WORD)SYS_REG_OPERATION(WRITE_CR, 8) 85 | 86 | #define READ_DR0 (WORD)SYS_REG_OPERATION(READ_DR, 0) 87 | #define READ_DR1 (WORD)SYS_REG_OPERATION(READ_DR, 1) 88 | #define READ_DR2 (WORD)SYS_REG_OPERATION(READ_DR, 2) 89 | #define READ_DR3 (WORD)SYS_REG_OPERATION(READ_DR, 3) 90 | #define READ_DR6 (WORD)SYS_REG_OPERATION(READ_DR, 6) 91 | #define READ_DR7 (WORD)SYS_REG_OPERATION(READ_DR, 7) 92 | 93 | #define WRITE_DR0 (WORD)SYS_REG_OPERATION(WRITE_DR, 0) 94 | #define WRITE_DR1 (WORD)SYS_REG_OPERATION(WRITE_DR, 1) 95 | #define WRITE_DR2 (WORD)SYS_REG_OPERATION(WRITE_DR, 2) 96 | #define WRITE_DR3 (WORD)SYS_REG_OPERATION(WRITE_DR, 3) 97 | #define WRITE_DR6 (WORD)SYS_REG_OPERATION(WRITE_DR, 6) 98 | #define WRITE_DR7 (WORD)SYS_REG_OPERATION(WRITE_DR, 7) 99 | 100 | VOID __fastcall DisableWriteProtection(); 101 | VOID __fastcall EnableWriteProtection(); 102 | BOOLEAN __fastcall IsSMEPPresent(); 103 | BOOLEAN __fastcall IsSMAPPresent(); 104 | VOID __fastcall DisableSMEP(); 105 | VOID __fastcall DisableSMAP(); 106 | VOID __fastcall EnableSMEP(); 107 | VOID __fastcall EnableSMAP(); 108 | SIZE_T __fastcall OperateCrDrRegister(WORD Action, OPTIONAL SIZE_T OptionalData); 109 | 110 | #pragma pack(push, 1) 111 | 112 | // AMD64 APMv2, стр. 334: 113 | #ifdef _X86_ 114 | #pragma warning(push) 115 | #pragma warning(disable: 4214) 116 | #pragma warning(disable: 4201) 117 | typedef struct _TSS { 118 | WORD Link; 119 | WORD Reserved1; 120 | ULONG ESP0; 121 | WORD SS0; 122 | WORD Reserved2; 123 | ULONG ESP1; 124 | WORD SS1; 125 | WORD Reserved3; 126 | ULONG ESP2; 127 | WORD SS2; 128 | WORD Reserved4; 129 | ULONG CR3; 130 | ULONG EIP; 131 | ULONG EFlags; 132 | ULONG EAX; 133 | ULONG ECX; 134 | ULONG EDX; 135 | ULONG EBX; 136 | ULONG ESP; 137 | ULONG EBP; 138 | ULONG ESI; 139 | ULONG EDI; 140 | WORD ES; 141 | WORD Reserved5; 142 | WORD CS; 143 | WORD Reserved6; 144 | WORD SS; 145 | WORD Reserved7; 146 | WORD DS; 147 | WORD Reserved8; 148 | WORD FS; 149 | WORD Reserved9; 150 | WORD GS; 151 | WORD Reserved10; 152 | WORD LDTSelector; 153 | WORD Reserved11; 154 | union { 155 | struct { 156 | unsigned short Trap : 1; 157 | unsigned short Reserved12 : 15; 158 | }; 159 | WORD wReserved12; 160 | }; 161 | WORD IOPBBaseAddress; 162 | } TSS, *PTSS; 163 | #pragma warning(pop) 164 | #else 165 | typedef struct _TSS { 166 | ULONG Reserved1; 167 | ULONG64 ESP0; 168 | ULONG64 ESP1; 169 | ULONG64 ESP2; 170 | ULONG64 Reserved2; 171 | ULONG64 IST1; 172 | ULONG64 IST2; 173 | ULONG64 IST3; 174 | ULONG64 IST4; 175 | ULONG64 IST5; 176 | ULONG64 IST6; 177 | ULONG64 IST7; 178 | ULONG64 Reserved3; 179 | WORD Reserved4; 180 | WORD IOPBBaseAddress; 181 | } TSS, *PTSS; 182 | #endif 183 | 184 | #define ExtractLimitFromGdtEntry(GdtEntry) ((ULONG)((GdtEntry->LimitHigh << 16) | (GdtEntry->LimitLow))) 185 | 186 | #ifdef _X86_ 187 | #define ExtractBaseFromGdtEntry(GdtEntry) ((PVOID)((GdtEntry->BaseAddressHigh << 24) | (GdtEntry->BaseAddressMiddle << 16) | (GdtEntry->BaseAddressLow))) 188 | // AMD64 APMv2, стр. 80: 189 | typedef struct _GDTENTRY { 190 | unsigned LimitLow : 16; 191 | unsigned BaseAddressLow : 16; 192 | unsigned BaseAddressMiddle : 8; 193 | unsigned Type : 4; 194 | unsigned System : 1; 195 | unsigned DPL : 2; 196 | unsigned Present : 1; 197 | unsigned LimitHigh : 4; 198 | unsigned Available : 1; 199 | unsigned Reserved : 1; 200 | unsigned DefaultOperandSize : 1; 201 | unsigned Granularity : 1; 202 | unsigned BaseAddressHigh : 8; 203 | } GDTENTRY, *PGDTENTRY; 204 | #else 205 | #define ExtractBaseFromGdtEntry(GdtEntry) ((PVOID)(((UINT64)GdtEntry->BaseAddressHighest << 32) | (GdtEntry->BaseAddressHigh << 24) | (GdtEntry->BaseAddressMiddle << 16) | (GdtEntry->BaseAddressLow))) 206 | // AMD64 APMv2, стр. 91: 207 | typedef struct _GDTENTRY { 208 | unsigned LimitLow : 16; 209 | unsigned BaseAddressLow : 16; 210 | unsigned BaseAddressMiddle : 8; 211 | unsigned Type : 4; 212 | unsigned System : 1; 213 | unsigned DPL : 2; 214 | unsigned Present : 1; 215 | unsigned LimitHigh : 4; 216 | unsigned Available : 1; 217 | unsigned Reserved1 : 2; 218 | unsigned Granularity : 1; 219 | unsigned BaseAddressHigh : 8; 220 | unsigned BaseAddressHighest : 32; 221 | unsigned Reserved2 : 8; 222 | unsigned SystemOrTypeZeroBit8 : 1; 223 | unsigned SystemOrTypeZeroBit9 : 1; 224 | unsigned SystemOrTypeZeroBit10 : 1; 225 | unsigned SystemOrTypeZeroBit11 : 1; 226 | unsigned SystemOrTypeZeroBit12 : 1; 227 | unsigned Reserved3 : 3; 228 | unsigned Reserved4 : 16; 229 | } GDTENTRY, *PGDTENTRY; 230 | #endif 231 | 232 | typedef struct _GDTR { 233 | WORD Limit; 234 | PGDTENTRY Base; 235 | } GDTR, *PGDTR; 236 | 237 | typedef struct _IDTR { 238 | WORD Limit; 239 | PVOID Base; 240 | } IDTR, *PIDTR; 241 | 242 | 243 | #pragma warning(push) 244 | #pragma warning(disable: 4214) 245 | #pragma warning(disable: 4201) 246 | typedef struct _TR { 247 | union { 248 | struct { 249 | unsigned short RPL : 2; 250 | unsigned short TableIndicator : 1; 251 | unsigned short SelectorIndex : 13; // Индекс в GDT (TSS Ptr = GDTR:Base + TR:SelectorIndex) 252 | }; 253 | WORD Selector; 254 | }; 255 | } TR, *PTR; 256 | #pragma warning(pop) 257 | 258 | #pragma pack(pop) 259 | 260 | #define SIDT 0x900A010F 261 | #define SGDT 0x9002010F 262 | #define STR 0x900A000F 263 | 264 | #define LIDT 0x901A010F 265 | #define LGDT 0x9012010F 266 | #define LTR 0x901A000F 267 | 268 | ULONG __fastcall IdtGdtTrOperation(DWORD32 Operation, PVOID Data); 269 | 270 | PTSS GetTSSPointer(OUT OPTIONAL PULONG TSSLimit); -------------------------------------------------------------------------------- /EnjoyTheRing0/NativeFunctions/IO.inc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoShiMin/EnjoyTheRing0/ea426c4ce56e5cf406732a572dc8db8b3c5e6626/EnjoyTheRing0/NativeFunctions/IO.inc -------------------------------------------------------------------------------- /EnjoyTheRing0/NativeFunctions/Interrupts.inc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoShiMin/EnjoyTheRing0/ea426c4ce56e5cf406732a572dc8db8b3c5e6626/EnjoyTheRing0/NativeFunctions/Interrupts.inc -------------------------------------------------------------------------------- /EnjoyTheRing0/NativeFunctions/MSR.inc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoShiMin/EnjoyTheRing0/ea426c4ce56e5cf406732a572dc8db8b3c5e6626/EnjoyTheRing0/NativeFunctions/MSR.inc -------------------------------------------------------------------------------- /EnjoyTheRing0/NativeFunctions/Main.asm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoShiMin/EnjoyTheRing0/ea426c4ce56e5cf406732a572dc8db8b3c5e6626/EnjoyTheRing0/NativeFunctions/Main.asm -------------------------------------------------------------------------------- /EnjoyTheRing0/NativeFunctions/NativeFunctions.prt: -------------------------------------------------------------------------------- 1 | ; FASM Editor 2 | 3 | include "Main.asm" 4 | 5 | if 2 * 2 = 5 6 | [options] 7 | countAsm=1 8 | countInc=4 9 | [asm] 10 | asm1="Main.asm" 11 | [inc] 12 | inc1="IO.inc" 13 | inc2="Interrupts.inc" 14 | inc3="MSR.inc" 15 | inc4="SystemRegisters.inc" 16 | end if 17 | -------------------------------------------------------------------------------- /EnjoyTheRing0/NativeFunctions/NativeFunctions64.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoShiMin/EnjoyTheRing0/ea426c4ce56e5cf406732a572dc8db8b3c5e6626/EnjoyTheRing0/NativeFunctions/NativeFunctions64.obj -------------------------------------------------------------------------------- /EnjoyTheRing0/NativeFunctions/NativeFunctions86.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoShiMin/EnjoyTheRing0/ea426c4ce56e5cf406732a572dc8db8b3c5e6626/EnjoyTheRing0/NativeFunctions/NativeFunctions86.obj -------------------------------------------------------------------------------- /EnjoyTheRing0/NativeFunctions/SystemRegisters.inc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoShiMin/EnjoyTheRing0/ea426c4ce56e5cf406732a572dc8db8b3c5e6626/EnjoyTheRing0/NativeFunctions/SystemRegisters.inc -------------------------------------------------------------------------------- /EnjoyTheRing0/PCI.c: -------------------------------------------------------------------------------- 1 | #include "PCI.h" 2 | 3 | #define PCI_BUS_NOT_EXIST 0 // Шины не существует 4 | #define PCI_NO_DEVICE_AT_SLOT 2 // Нет устройства в указанном слоте 5 | 6 | NTSTATUS ReadPciConfig( 7 | ULONG PciAddress, 8 | ULONG PciOffset, 9 | PVOID Buffer, 10 | ULONG BufferSize, 11 | OPTIONAL PULONG BytesRead 12 | ) { 13 | if (BytesRead) *BytesRead = 0; 14 | 15 | PCI_SLOT_NUMBER SlotNumber; 16 | SlotNumber.u.AsULONG = 0; 17 | SlotNumber.u.bits.DeviceNumber = PciGetDeviceNumber(PciAddress); 18 | SlotNumber.u.bits.FunctionNumber = PciGetFunctionNumber(PciAddress); 19 | 20 | ULONG BusNumber = PciGetBusNumber(PciAddress); 21 | ULONG Status = HalGetBusDataByOffset(PCIConfiguration, BusNumber, SlotNumber.u.AsULONG, Buffer, PciOffset, BufferSize); 22 | 23 | switch (Status) { 24 | case PCI_BUS_NOT_EXIST: return PCI_ERROR_BUS_NOT_EXIST; 25 | case PCI_NO_DEVICE_AT_SLOT: return PCI_ERROR_DEVICE_NOT_PRESENT_AT_SLOT; 26 | default: 27 | if (BytesRead) *BytesRead = Status; 28 | return STATUS_SUCCESS; 29 | } 30 | } 31 | 32 | NTSTATUS WritePciConfig(ULONG PciAddress, 33 | ULONG PciOffset, 34 | PVOID Buffer, 35 | ULONG BufferSize, 36 | OPTIONAL PULONG BytesWritten 37 | ) { 38 | if (BytesWritten) *BytesWritten = 0; 39 | 40 | PCI_SLOT_NUMBER SlotNumber; 41 | SlotNumber.u.AsULONG = 0; 42 | SlotNumber.u.bits.DeviceNumber = PciGetDeviceNumber(PciAddress); 43 | SlotNumber.u.bits.FunctionNumber = PciGetFunctionNumber(PciAddress); 44 | 45 | ULONG BusNumber = PciGetBusNumber(PciAddress); 46 | ULONG Status = HalSetBusDataByOffset(PCIConfiguration, BusNumber, SlotNumber.u.AsULONG, Buffer, PciOffset, BufferSize); 47 | 48 | if (Status == 0) return PCI_ERROR_BUS_DATA_TYPE; 49 | 50 | if (BytesWritten) *BytesWritten = Status; 51 | return Status == BufferSize ? STATUS_SUCCESS : STATUS_PARTIAL_COPY; 52 | } -------------------------------------------------------------------------------- /EnjoyTheRing0/PCI.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Номера шины, устройства и функции в адрес PCI-устройства: 6 | #define PciGetAddress(Bus, Device, Function) (((Bus & 0xFF) << 8) | ((Device & 0x1F) << 3) | (Function & 7)) 7 | 8 | // Получить номер шины из адреса PCI-устройства: 9 | #define PciGetBusNumber(Address) ((Address >> 8) & 0xFF) 10 | 11 | // Получить номер устройства из адреса PCI-устройства: 12 | #define PciGetDeviceNumber(Address) ((Address >> 3) & 0x1F) 13 | 14 | // Получить номер функции из адреса PCI-устройства: 15 | #define PciGetFunctionNumber(Address) (Address & 7) 16 | 17 | // Коды ошибок при работе с PCI: 18 | #define PCI_ERROR_BUS_NOT_EXIST 0xE0000001L 19 | #define PCI_ERROR_DEVICE_NOT_PRESENT_AT_SLOT 0xE0000002L 20 | #define PCI_ERROR_BUS_DATA_TYPE 0xE0000003L 21 | 22 | NTSTATUS ReadPciConfig( 23 | ULONG PciAddress, 24 | ULONG PciOffset, 25 | PVOID Buffer, 26 | ULONG BufferSize, 27 | OPTIONAL PULONG BytesRead 28 | ); 29 | 30 | NTSTATUS WritePciConfig( 31 | ULONG PciAddress, 32 | ULONG PciOffset, 33 | PVOID Buffer, 34 | ULONG BufferSize, 35 | OPTIONAL PULONG BytesWritten 36 | ); -------------------------------------------------------------------------------- /EnjoyTheRing0/ProcessesUtils.c: -------------------------------------------------------------------------------- 1 | #include "ProcessesUtils.h" 2 | 3 | 4 | typedef NTSTATUS NTKERNELAPI (NTAPI *_PsGetContextThread)(IN PETHREAD Thread, IN OUT PCONTEXT Context, IN KPROCESSOR_MODE PreviousMode); 5 | typedef NTSTATUS NTKERNELAPI (NTAPI *_PsSetContextThread)(IN PETHREAD Thread, IN PCONTEXT Context, IN KPROCESSOR_MODE PreviousMode); 6 | 7 | typedef NTSTATUS NTKERNELAPI (NTAPI *_PsSuspendProcess)(IN PEPROCESS Process); 8 | typedef NTSTATUS NTKERNELAPI (NTAPI *_PsResumeProcess)(IN PEPROCESS Process); 9 | 10 | typedef NTSTATUS NTKERNELAPI (NTAPI *_ObRegisterCallbacks)(IN POB_CALLBACK_REGISTRATION CallBackRegistration, OUT PVOID *RegistrationHandle); 11 | typedef VOID NTKERNELAPI (NTAPI *_ObUnRegisterCallbacks)(IN PVOID RegistrationHandle); 12 | 13 | typedef NTSTATUS NTKERNELAPI (NTAPI *_ZwQueryInformationProcess)( 14 | HANDLE hProcess, 15 | PROCESSINFOCLASS ProcessInformationClass, 16 | PVOID ProcessInformation, 17 | ULONG ProcessInformationLength, 18 | PULONG ReturnLength 19 | ); 20 | 21 | typedef NTSTATUS NTKERNELAPI (NTAPI *_ZwSetInformationProcess)( 22 | HANDLE hProcess, 23 | PROCESSINFOCLASS ProcessInformationClass, 24 | PVOID ProcessInformation, 25 | ULONG ProcessInformationLength 26 | ); 27 | 28 | 29 | 30 | PVOID GetKernelProcAddress(LPWSTR ProcedureName) { 31 | UNICODE_STRING SystemRoutineName; 32 | RtlInitUnicodeString(&SystemRoutineName, ProcedureName); 33 | return MmGetSystemRoutineAddress(&SystemRoutineName); 34 | } 35 | 36 | 37 | 38 | PEPROCESS GetPEPROCESS(HANDLE ProcessId) { 39 | PEPROCESS Process; 40 | return NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &Process)) ? Process : NULL; 41 | } 42 | 43 | PETHREAD GetPETHREAD(HANDLE ThreadId) { 44 | PETHREAD Thread; 45 | return NT_SUCCESS(PsLookupThreadByThreadId(ThreadId, &Thread)) ? Thread : NULL; 46 | } 47 | 48 | 49 | 50 | BOOL AttachToProcess(HANDLE ProcessId, OUT PKAPC_STATE ApcState) { 51 | if (ApcState == NULL) return FALSE; 52 | PEPROCESS Process; 53 | if NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &Process)) { 54 | KeStackAttachProcess(Process, ApcState); 55 | ObDereferenceObject(Process); 56 | return TRUE; 57 | } 58 | return FALSE; 59 | } 60 | 61 | BOOL DetachFromProcess(IN PKAPC_STATE ApcState) { 62 | if (ApcState == NULL) return FALSE; 63 | KeUnstackDetachProcess(ApcState); 64 | return TRUE; 65 | } 66 | 67 | 68 | 69 | NTSTATUS OpenProcess(HANDLE ProcessId, OUT PHANDLE hProcess) { 70 | if (ProcessId == PsGetCurrentProcessId()) { 71 | *hProcess = ZwCurrentProcess(); 72 | return STATUS_SUCCESS; 73 | } 74 | 75 | CLIENT_ID ClientId; 76 | ClientId.UniqueProcess = ProcessId; 77 | ClientId.UniqueThread = 0; 78 | 79 | OBJECT_ATTRIBUTES ObjectAttributes; 80 | InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); 81 | 82 | return ZwOpenProcess(hProcess, PROCESS_ALL_ACCESS, &ObjectAttributes, &ClientId); 83 | } 84 | 85 | NTSTATUS TerminateProcess(HANDLE hProcess, NTSTATUS ExitStatus) { 86 | return ZwTerminateProcess(hProcess, ExitStatus); 87 | } 88 | 89 | NTSTATUS KillProcess(HANDLE ProcessId) { 90 | HANDLE hProcess = 0; 91 | NTSTATUS Status = STATUS_SUCCESS; 92 | Status = OpenProcess(ProcessId, &hProcess); 93 | if NT_SUCCESS(Status) { 94 | Status = TerminateProcess(hProcess, STATUS_SUCCESS); 95 | CloseProcess(hProcess); 96 | } 97 | return Status; 98 | } 99 | 100 | NTSTATUS CreateSystemThread(OUT PHANDLE hThread, PKSTART_ROUTINE ThreadProc, PVOID Arguments) { 101 | OBJECT_ATTRIBUTES ObjectAttributes; 102 | InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); 103 | return PsCreateSystemThread(hThread, GENERIC_ALL, &ObjectAttributes, NULL, NULL, ThreadProc, Arguments); 104 | } 105 | 106 | NTSTATUS ExitSystemThread(NTSTATUS ExitStatus) { 107 | return PsTerminateSystemThread(ExitStatus); 108 | } 109 | 110 | 111 | 112 | NTSTATUS VirtualAlloc(HANDLE hProcess, SIZE_T Size, IN OUT PVOID *VirtualAddress) { 113 | return ZwAllocateVirtualMemory(hProcess, VirtualAddress, 0, &Size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 114 | }; 115 | 116 | NTSTATUS VirtualFree(HANDLE hProcess, PVOID VirtualAddress) { 117 | SIZE_T RegionSize = 0; 118 | return ZwFreeVirtualMemory(hProcess, &VirtualAddress, &RegionSize, MEM_RELEASE); 119 | } 120 | 121 | 122 | 123 | NTSTATUS VirtualAllocInProcess(HANDLE ProcessId, SIZE_T Size, IN OUT PVOID *VirtualAddress) { 124 | HANDLE hProcess; 125 | NTSTATUS Status = OpenProcess(ProcessId, &hProcess); 126 | return NT_SUCCESS(Status) ? VirtualAlloc(hProcess, Size, VirtualAddress) : Status; 127 | } 128 | 129 | NTSTATUS VirtualFreeInProcess(HANDLE ProcessId, PVOID VirtualAddress) { 130 | HANDLE hProcess; 131 | NTSTATUS Status = OpenProcess(ProcessId, &hProcess); 132 | return NT_SUCCESS(Status) ? VirtualFree(hProcess, VirtualAddress) : Status; 133 | } 134 | 135 | 136 | 137 | PHYSICAL_ADDRESS GetPhysicalAddressInProcess(HANDLE ProcessId, PVOID BaseVirtualAddress) { 138 | KAPC_STATE ApcState; 139 | PHYSICAL_ADDRESS PhysicalAddress; 140 | if (AttachToProcess(ProcessId, &ApcState)) { 141 | PhysicalAddress = GetPhysicalAddress(BaseVirtualAddress); 142 | DetachFromProcess(&ApcState); 143 | } else { 144 | PhysicalAddress.QuadPart = 0; 145 | } 146 | 147 | return PhysicalAddress; 148 | } 149 | 150 | 151 | 152 | PVOID MapVirtualMemory( 153 | HANDLE ProcessId, 154 | PVOID VirtualAddress, 155 | OPTIONAL PVOID MapToVirtualAddress, 156 | ULONG Size, 157 | KPROCESSOR_MODE ProcessorMode, 158 | OUT PMDL* pMdl 159 | ) { 160 | 161 | #define UnlockFreeAndNilMdl(Mdl) MmUnlockPages((Mdl)); IoFreeMdl((Mdl)); (Mdl) = NULL; 162 | 163 | if (pMdl == NULL) return NULL; 164 | 165 | PVOID MappedAddress = NULL; 166 | PMDL Mdl = NULL; 167 | Mdl = IoAllocateMdl(VirtualAddress, Size, FALSE, FALSE, NULL); 168 | if (Mdl) { 169 | PEPROCESS Process; 170 | if NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &Process)) { 171 | __try { 172 | MmProbeAndLockProcessPages(Mdl, Process, KernelMode, IoReadAccess); 173 | 174 | __try { 175 | MappedAddress = MmMapLockedPagesSpecifyCache(Mdl, ProcessorMode, MmNonCached, MapToVirtualAddress, FALSE, NormalPagePriority); 176 | } __except (EXCEPTION_EXECUTE_HANDLER) { 177 | UnlockFreeAndNilMdl(Mdl); 178 | } 179 | 180 | // Если исключение не было сгенерировано, но адрес мы не получили: 181 | if ((MappedAddress == NULL) && (Mdl != NULL)) { 182 | UnlockFreeAndNilMdl(Mdl); 183 | } 184 | 185 | } __except (EXCEPTION_EXECUTE_HANDLER) { 186 | IoFreeMdl(Mdl); 187 | } 188 | 189 | ObDereferenceObject(Process); 190 | } 191 | } 192 | 193 | *pMdl = Mdl; 194 | return MappedAddress; 195 | 196 | #undef UnlockFreeAndNilMdl 197 | 198 | } 199 | 200 | VOID UnmapVirtualMemory(PMDL Mdl, PVOID MappedMemory) { 201 | if ((Mdl == NULL) || (MappedMemory == NULL)) return; 202 | MmUnmapLockedPages(MappedMemory, Mdl); 203 | MmUnlockPages(Mdl); 204 | IoFreeMdl(Mdl); 205 | } 206 | 207 | 208 | 209 | typedef enum _PROCESS_MEMORY_OPERATION { 210 | MemoryRead, 211 | MemoryWrite, 212 | } PROCESS_MEMORY_OPERATION; 213 | 214 | 215 | typedef struct _MEMORY_OPERATION_INFO { 216 | HANDLE ProcessId; 217 | PVOID VirtualAddress; 218 | PVOID Buffer; 219 | ULONG BufferSize; 220 | BOOL IsUsermodeBuffer; 221 | MEMORY_ACCESS_TYPE AccessType; 222 | } MEMORY_OPERATION_INFO, *PMEMORY_OPERATION_INFO; 223 | 224 | BOOL FASTCALL OperateMemoryThroughMdlAccess(PMEMORY_OPERATION_INFO OperationInfo, PROCESS_MEMORY_OPERATION MemoryOperation) { 225 | PMDL Mdl; 226 | PVOID MappedMemory = MapVirtualMemory(OperationInfo->ProcessId, OperationInfo->VirtualAddress, NULL, (ULONG)OperationInfo->BufferSize, KernelMode, &Mdl); 227 | if (MappedMemory && Mdl) { 228 | BOOL Status = TRUE; 229 | __try { 230 | switch (MemoryOperation) { 231 | case MemoryRead : RtlCopyMemory(OperationInfo->Buffer, MappedMemory, OperationInfo->BufferSize); break; 232 | case MemoryWrite: RtlCopyMemory(MappedMemory, OperationInfo->Buffer, OperationInfo->BufferSize); break; 233 | } 234 | } __except (EXCEPTION_EXECUTE_HANDLER) { 235 | Status = FALSE; 236 | } 237 | UnmapVirtualMemory(Mdl, MappedMemory); 238 | return Status; 239 | } 240 | return FALSE; 241 | } 242 | 243 | BOOL FASTCALL OperateMemoryThroughCombinedAccess(PMEMORY_OPERATION_INFO OperationInfo, PROCESS_MEMORY_OPERATION MemoryOperation) { 244 | BOOL Status = FALSE; 245 | PMDL Mdl; 246 | PVOID MappedMemory = MapVirtualMemory(OperationInfo->ProcessId, OperationInfo->VirtualAddress, NULL, OperationInfo->BufferSize, KernelMode, &Mdl); 247 | if (MappedMemory && Mdl) { 248 | // Получаем физический адрес отображения: 249 | PHYSICAL_ADDRESS PhysicalAddress = MmGetPhysicalAddress(MappedMemory); 250 | PVOID PhysicalMappedMemory = MmMapIoSpace(PhysicalAddress, OperationInfo->BufferSize, MmNonCached); 251 | if (PhysicalMappedMemory) { 252 | Status = TRUE; 253 | __try { 254 | switch (MemoryOperation) { 255 | case MemoryRead : RtlCopyMemory(OperationInfo->Buffer, PhysicalMappedMemory, OperationInfo->BufferSize); break; 256 | case MemoryWrite: RtlCopyMemory(PhysicalMappedMemory, OperationInfo->Buffer, OperationInfo->BufferSize); break; 257 | } 258 | } __except (EXCEPTION_EXECUTE_HANDLER) { 259 | Status = FALSE; 260 | } 261 | MmUnmapIoSpace(PhysicalMappedMemory, OperationInfo->BufferSize); 262 | } 263 | UnmapVirtualMemory(Mdl, MappedMemory); 264 | } 265 | 266 | return Status; 267 | } 268 | 269 | BOOL FASTCALL OperateMemoryThroughPhysicalAccess(PMEMORY_OPERATION_INFO OperationInfo, PROCESS_MEMORY_OPERATION MemoryOperation) { 270 | PHYSICAL_ADDRESS PhysicalAddress = GetPhysicalAddressInProcess(OperationInfo->ProcessId, OperationInfo->VirtualAddress); 271 | if (PhysicalAddress.QuadPart == 0) return FALSE; 272 | 273 | PVOID MappedMemory = MmMapIoSpace(PhysicalAddress, OperationInfo->BufferSize, MmNonCached); 274 | if (MappedMemory == NULL) return FALSE; 275 | 276 | BOOL Status = TRUE; 277 | __try { 278 | switch (MemoryOperation) { 279 | case MemoryRead: RtlCopyMemory(OperationInfo->Buffer, MappedMemory, OperationInfo->BufferSize); break; 280 | case MemoryWrite: RtlCopyMemory(MappedMemory, OperationInfo->Buffer, OperationInfo->BufferSize); break; 281 | } 282 | } __except (EXCEPTION_EXECUTE_HANDLER) { 283 | Status = FALSE; 284 | } 285 | 286 | MmUnmapIoSpace(MappedMemory, OperationInfo->BufferSize); 287 | 288 | return Status; 289 | } 290 | 291 | BOOL FASTCALL OperateProcessMemory(PMEMORY_OPERATION_INFO OperationInfo, PROCESS_MEMORY_OPERATION MemoryOperation) { 292 | if (OperationInfo == NULL) return FALSE; 293 | 294 | // Если передали юзермодный буфер - проверяем его на чтение\запись: 295 | if (OperationInfo->IsUsermodeBuffer) { 296 | if (!MmIsAddressValid(OperationInfo->Buffer)) return FALSE; 297 | BOOL UsermodeBufferReady = FALSE; 298 | switch (MemoryOperation) { 299 | case MemoryRead: 300 | UsermodeBufferReady = IsUsermodeMemoryWriteable(OperationInfo->Buffer, OperationInfo->BufferSize, 1); 301 | break; 302 | 303 | case MemoryWrite: 304 | UsermodeBufferReady = IsUsermodeMemoryReadable(OperationInfo->Buffer, OperationInfo->BufferSize, 1); 305 | break; 306 | } 307 | if (!UsermodeBufferReady) return FALSE; 308 | } 309 | 310 | BOOL Status; 311 | switch (OperationInfo->AccessType) { 312 | case MdlAccess: 313 | Status = OperateMemoryThroughMdlAccess(OperationInfo, MemoryOperation); 314 | break; 315 | 316 | case MdlWithPhysicalAccess: 317 | Status = OperateMemoryThroughCombinedAccess(OperationInfo, MemoryOperation); 318 | break; 319 | 320 | case DirectPhysicalAccess: 321 | Status = OperateMemoryThroughPhysicalAccess(OperationInfo, MemoryOperation); 322 | break; 323 | 324 | default: 325 | Status = FALSE; 326 | break; 327 | } 328 | 329 | return Status; 330 | } 331 | 332 | BOOL ReadProcessMemory(HANDLE ProcessId, PVOID VirtualAddress, PVOID Buffer, ULONG BufferSize, BOOL IsUsermodeBuffer, MEMORY_ACCESS_TYPE AccessType) { 333 | MEMORY_OPERATION_INFO OperationInfo; 334 | OperationInfo.ProcessId = ProcessId; 335 | OperationInfo.VirtualAddress = VirtualAddress; 336 | OperationInfo.Buffer = Buffer; 337 | OperationInfo.BufferSize = BufferSize; 338 | OperationInfo.IsUsermodeBuffer = IsUsermodeBuffer; 339 | OperationInfo.AccessType = AccessType; 340 | return OperateProcessMemory(&OperationInfo, MemoryRead); 341 | } 342 | 343 | BOOL WriteProcessMemory(HANDLE ProcessId, PVOID VirtualAddress, PVOID Buffer, ULONG BufferSize, BOOL IsUsermodeBuffer, MEMORY_ACCESS_TYPE AccessType) { 344 | MEMORY_OPERATION_INFO OperationInfo; 345 | OperationInfo.ProcessId = ProcessId; 346 | OperationInfo.VirtualAddress = VirtualAddress; 347 | OperationInfo.Buffer = Buffer; 348 | OperationInfo.BufferSize = BufferSize; 349 | OperationInfo.IsUsermodeBuffer = IsUsermodeBuffer; 350 | OperationInfo.AccessType = AccessType; 351 | return OperateProcessMemory(&OperationInfo, MemoryWrite); 352 | } 353 | 354 | #pragma warning(push) 355 | #pragma warning(disable: 4055) 356 | 357 | NTSTATUS GetThreadContext(IN PETHREAD Thread, IN OUT PCONTEXT Context, IN KPROCESSOR_MODE PreviousMode) { 358 | _PsGetContextThread PsGetContextThread = (_PsGetContextThread)GetKernelProcAddress(L"PsGetContextThread"); 359 | if (PsGetContextThread == NULL) return STATUS_NOT_IMPLEMENTED; 360 | return PsGetContextThread(Thread, Context, PreviousMode); 361 | } 362 | 363 | NTSTATUS SetThreadContext(IN PETHREAD Thread, IN PCONTEXT Context, IN KPROCESSOR_MODE PreviousMode) { 364 | _PsSetContextThread PsSetContextThread = (_PsSetContextThread)GetKernelProcAddress(L"PsSetContextThread"); 365 | if (PsSetContextThread == NULL) return STATUS_NOT_IMPLEMENTED; 366 | return PsSetContextThread(Thread, Context, PreviousMode); 367 | } 368 | 369 | 370 | NTSTATUS SetInformationProcess( 371 | HANDLE hProcess, 372 | PROCESSINFOCLASS ProcessInformationClass, 373 | PVOID ProcessInformation, 374 | ULONG ProcessInformationLength 375 | ) { 376 | _ZwSetInformationProcess ZwSetInformationProcess = (_ZwSetInformationProcess)GetKernelProcAddress(L"ZwSetInformationProcess"); 377 | if (ZwSetInformationProcess == NULL) return STATUS_NOT_IMPLEMENTED; 378 | return ZwSetInformationProcess(hProcess, ProcessInformationClass, ProcessInformation, ProcessInformationLength); 379 | } 380 | 381 | NTSTATUS QueryInformationProcess( 382 | HANDLE hProcess, 383 | PROCESSINFOCLASS ProcessInformationClass, 384 | PVOID ProcessInformation, 385 | ULONG ProcessInformationLength, 386 | PULONG ReturnLength 387 | ) { 388 | _ZwQueryInformationProcess ZwQueryInformationProcess = (_ZwQueryInformationProcess)GetKernelProcAddress(L"ZwQueryInformationProcess"); 389 | if (ZwQueryInformationProcess == NULL) return STATUS_NOT_IMPLEMENTED; 390 | return ZwQueryInformationProcess(hProcess, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength); 391 | } 392 | 393 | NTSTATUS SuspendProcess(IN PEPROCESS Process) { 394 | if (Process == NULL) return STATUS_INVALID_PARAMETER; 395 | _PsSuspendProcess PsSuspendProcess = (_PsSuspendProcess)GetKernelProcAddress(L"PsSuspendProcess"); 396 | if (PsSuspendProcess == NULL) return STATUS_NOT_IMPLEMENTED; 397 | return PsSuspendProcess(Process); 398 | } 399 | 400 | NTSTATUS ResumeProcess(IN PEPROCESS Process) { 401 | if (Process == NULL) return STATUS_INVALID_PARAMETER; 402 | _PsResumeProcess PsResumeProcess = (_PsResumeProcess)GetKernelProcAddress(L"PsResumeProcess"); 403 | if (PsResumeProcess == NULL) return STATUS_NOT_IMPLEMENTED; 404 | return PsResumeProcess(Process); 405 | } 406 | 407 | NTSTATUS RegisterCallbacks(IN POB_CALLBACK_REGISTRATION CallBackRegistration, OUT PVOID *RegistrationHandle) { 408 | _ObRegisterCallbacks ObRegisterCallbacks = (_ObRegisterCallbacks)GetKernelProcAddress(L"ObRegisterCallbacks"); 409 | if (ObRegisterCallbacks == NULL) return STATUS_NOT_IMPLEMENTED; 410 | return ObRegisterCallbacks(CallBackRegistration, RegistrationHandle); 411 | } 412 | 413 | VOID UnRegisterCallbacks(IN PVOID RegistrationHandle) { 414 | _ObUnRegisterCallbacks ObUnRegisterCallbacks = (_ObUnRegisterCallbacks)GetKernelProcAddress(L"ObUnRegisterCallbacks"); 415 | if (ObUnRegisterCallbacks == NULL) return; 416 | ObUnRegisterCallbacks(RegistrationHandle); 417 | } 418 | #pragma warning(pop) 419 | 420 | #ifdef _AMD64_ 421 | PKTRAP_FRAME GetTrapFrame() { 422 | /* x86: 423 | TrapFrame = (PKTRAP_FRAME)((PBYTE)Thread->InitialStack - 424 | ALIGN_UP(sizeof(KTRAP_FRAME), KTRAP_FRAME_ALIGN) - 425 | sizeof(FX_SAVE_AREA)); 426 | */ 427 | return (PKTRAP_FRAME)((PBYTE)IoGetInitialStack() - sizeof(KTRAP_FRAME)); 428 | } 429 | 430 | VOID RaiseIOPLByTrapFrame() { 431 | PKTRAP_FRAME TrapFrame = GetTrapFrame(); 432 | TrapFrame->EFlags |= IOPL_ACCESS_MASK; 433 | } 434 | 435 | VOID ResetIOPLByTrapFrame() { 436 | PKTRAP_FRAME TrapFrame = GetTrapFrame(); 437 | TrapFrame->EFlags &= ~IOPL_ACCESS_MASK; 438 | } 439 | #endif 440 | 441 | 442 | #ifdef _X86_ 443 | typedef NTSTATUS NTKERNELAPI (NTAPI *_Ke386QueryIoAccessMap) (DWORD dwFlag, PVOID pIOPM); 444 | typedef NTSTATUS NTKERNELAPI (NTAPI *_Ke386SetIoAccessMap) (DWORD dwFlag, PVOID pIOPM); 445 | typedef NTSTATUS NTKERNELAPI (NTAPI *_Ke386IoSetAccessProcess) (PEPROCESS Process, DWORD dwFlag); 446 | 447 | // Размер IOPM = 65536 портов / 8 бит: 448 | #define IOPM_SIZE 8192 449 | #define NTVDM_IOPM_OFFSET 0x88 450 | 451 | #define QUERY_DISALLOWING_IOPM 0 452 | #define COPY_IOPM 1 453 | 454 | #define ENABLE_IOPM 1 455 | #define DISABLE_IOPM 0 456 | 457 | 458 | NTSTATUS RaiseIOPM(OPTIONAL HANDLE ProcessId) { 459 | PEPROCESS Process = ProcessId ? GetPEPROCESS(ProcessId) : PsGetCurrentProcess(); 460 | if (Process == NULL) return STATUS_INVALID_PARAMETER; 461 | 462 | #pragma warning(push) 463 | #pragma warning(disable: 4055) 464 | _Ke386SetIoAccessMap Ke386SetAccessMap = (_Ke386SetIoAccessMap)GetKernelProcAddress(L"Ke386SetIoAccessMap"); 465 | _Ke386IoSetAccessProcess Ke386IoSetAccessProcess = (_Ke386IoSetAccessProcess)GetKernelProcAddress(L"Ke386IoSetAccessProcess"); 466 | #pragma warning(pop) 467 | 468 | if (Ke386SetAccessMap && Ke386IoSetAccessProcess) { 469 | PVOID IOPM = GetMem(IOPM_SIZE); 470 | 471 | NTSTATUS Status; 472 | Status = Ke386SetAccessMap(COPY_IOPM, IOPM); 473 | if NT_SUCCESS(Status) Status = Ke386IoSetAccessProcess(Process, ENABLE_IOPM); 474 | 475 | FreeMem(IOPM); 476 | if (ProcessId) ObDereferenceObject(Process); 477 | 478 | return Status; 479 | } 480 | 481 | if (ProcessId) ObDereferenceObject(Process); 482 | return STATUS_NOT_IMPLEMENTED; 483 | } 484 | 485 | NTSTATUS ResetIOPM(OPTIONAL HANDLE ProcessId) { 486 | PEPROCESS Process = ProcessId ? GetPEPROCESS(ProcessId) : PsGetCurrentProcess(); 487 | if (Process == NULL) return STATUS_INVALID_PARAMETER; 488 | 489 | #pragma warning(push) 490 | #pragma warning(disable: 4055) 491 | _Ke386QueryIoAccessMap Ke386QueryAccessMap = (_Ke386QueryIoAccessMap)GetKernelProcAddress(L"Ke386QueryIoAccessMap"); 492 | _Ke386SetIoAccessMap Ke386SetAccessMap = (_Ke386SetIoAccessMap)GetKernelProcAddress(L"Ke386SetIoAccessMap"); 493 | _Ke386IoSetAccessProcess Ke386IoSetAccessProcess = (_Ke386IoSetAccessProcess)GetKernelProcAddress(L"Ke386IoSetAccessProcess"); 494 | #pragma warning(pop) 495 | 496 | if (Ke386QueryAccessMap && Ke386SetAccessMap && Ke386IoSetAccessProcess) { 497 | PVOID IOPM = GetMem(IOPM_SIZE); 498 | RtlFillMemory(IOPM, IOPM_SIZE, 0xFF); 499 | 500 | NTSTATUS Status; 501 | Status = Ke386QueryAccessMap(QUERY_DISALLOWING_IOPM, IOPM); 502 | if NT_SUCCESS(Status) { 503 | Status = Ke386SetAccessMap(COPY_IOPM, IOPM); 504 | if NT_SUCCESS(Status) Status = Ke386IoSetAccessProcess(Process, DISABLE_IOPM); 505 | } 506 | 507 | FreeMem(IOPM); 508 | if (ProcessId) ObDereferenceObject(Process); 509 | 510 | return Status; 511 | } 512 | 513 | if (ProcessId) ObDereferenceObject(Process); 514 | return STATUS_NOT_IMPLEMENTED; 515 | } 516 | #endif 517 | 518 | PULONG ScanEFlags() { 519 | // Выделяем юзермодную память для контекста: 520 | PCONTEXT Context = NULL; 521 | VirtualAlloc(ZwCurrentProcess(), sizeof(CONTEXT), &Context); 522 | 523 | // Получаем контекст: 524 | RtlZeroMemory(Context, sizeof(CONTEXT)); 525 | Context->ContextFlags = CONTEXT_CONTROL; 526 | 527 | PETHREAD CurrentThread = PsGetCurrentThread(); 528 | 529 | // Получаем оригинальное значение EFlags: 530 | NTSTATUS Status = GetThreadContext(CurrentThread, Context, UserMode); 531 | ULONG EFlagsValue = Context->EFlags; 532 | ULONG MaskedEFlags = MaskEFlagsReservedBits(EFlagsValue); 533 | 534 | PULONG EFlagsPtr = NULL; 535 | 536 | if NT_SUCCESS(Status) { 537 | // Получаем пределы стека: 538 | PULONG LowLimit, HighLimit; 539 | IoGetStackLimits((PULONG_PTR)&LowLimit, (PULONG_PTR)&HighLimit); 540 | 541 | // Проходимся по стеку и ищем нужное значение: 542 | #pragma warning(suppress: 4213) 543 | for (EFlagsPtr = (PULONG)((PBYTE)IoGetInitialStack() - sizeof(EFlagsValue)); EFlagsPtr >= LowLimit; ((PBYTE)EFlagsPtr)--) { 544 | if (MaskEFlagsReservedBits(*EFlagsPtr) == MaskedEFlags) { 545 | // Меняем CF в EFlags: 546 | Context->EFlags = (Context->EFlags & 1) == 1 ? Context->EFlags ^ 1 : Context->EFlags | 1; 547 | SetThreadContext(CurrentThread, Context, UserMode); 548 | 549 | // Если найденное значение поменялось - значит нашли верно: 550 | if (MaskEFlagsReservedBits(*EFlagsPtr) == MaskEFlagsReservedBits(Context->EFlags)) break; 551 | 552 | // Восстанавливаем оригинальный EFlags: 553 | Context->EFlags = EFlagsValue; 554 | SetThreadContext(CurrentThread, Context, UserMode); 555 | } 556 | } 557 | } 558 | 559 | // Восстанавливаем оригинальный EFlags: 560 | Context->EFlags = EFlagsValue; 561 | SetThreadContext(CurrentThread, Context, UserMode); 562 | 563 | // Освобождаем контекст: 564 | VirtualFree(ZwCurrentProcess(), Context); 565 | 566 | return EFlagsPtr; 567 | } 568 | 569 | VOID RaiseIOPLByTrapFrameScan() { 570 | PULONG EFlags = ScanEFlags(); 571 | if (EFlags) { 572 | *EFlags |= IOPL_ACCESS_MASK; 573 | } 574 | } 575 | 576 | VOID ResetIOPLByTrapFrameScan() { 577 | PULONG EFlags = ScanEFlags(); 578 | if (EFlags) { 579 | *EFlags &= ~IOPL_ACCESS_MASK; 580 | } 581 | } 582 | 583 | #ifdef _X86_ 584 | VOID RaiseIOPLByTSS() { 585 | PTSS TSS = GetTSSPointer(NULL); 586 | *(PULONG)(TSS->ESP0 - ESP0_EFLAGS_OFFSET) |= IOPL_ACCESS_MASK; 587 | } 588 | 589 | VOID ResetIOPLByTSS() { 590 | PTSS TSS = GetTSSPointer(NULL); 591 | *(PULONG)(TSS->ESP0 - ESP0_EFLAGS_OFFSET) &= ~IOPL_ACCESS_MASK; 592 | } 593 | #endif 594 | 595 | 596 | 597 | 598 | NTSTATUS RegisterHandlesOperationsNotifier(IN PHANDLES_NOTIFY_STRUCT HandlesNotifyStruct, OUT PVOID *RegistrationHandle) { 599 | // Определяем тип операции и задаём сами каллбэки: 600 | OB_OPERATION_REGISTRATION OperationRegistration; 601 | OperationRegistration.ObjectType = HandlesNotifyStruct->ObjectType; // PsProcessType / PsThreadType / ExDesktopObjectType 602 | OperationRegistration.Operations = HandlesNotifyStruct->Operations; // OB_OPERATION_HANDLE_CREATE || OB_OPERATION_HANDLE_DUPLICATE 603 | OperationRegistration.PostOperation = HandlesNotifyStruct->PostOperation; 604 | OperationRegistration.PreOperation = HandlesNotifyStruct->PreOperation; 605 | 606 | // Определяем "высоту" фильтра в стеке фильтров: 607 | UNICODE_STRING Altitude; 608 | RtlInitUnicodeString(&Altitude, L"389020"); // It's a magic! 609 | 610 | // Заполняем структуру регистрации каллбэка: 611 | OB_CALLBACK_REGISTRATION CallbackRegistration; 612 | CallbackRegistration.Altitude = Altitude; 613 | CallbackRegistration.OperationRegistration = &OperationRegistration; 614 | CallbackRegistration.OperationRegistrationCount = 1; 615 | CallbackRegistration.RegistrationContext = HandlesNotifyStruct->RegistrationContext; // Параметр, который будет передан в каллбэк 616 | CallbackRegistration.Version = OB_FLT_REGISTRATION_VERSION; 617 | 618 | // Регистрируем каллбэк: 619 | return RegisterCallbacks(&CallbackRegistration, RegistrationHandle); 620 | } 621 | 622 | VOID UnregisterHandlesOperationsNotifier(PVOID RegistrationHandle) { 623 | UnRegisterCallbacks(RegistrationHandle); 624 | } -------------------------------------------------------------------------------- /EnjoyTheRing0/ProcessesUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MemoryUtils.h" 4 | #include "NativeFunctions.h" 5 | 6 | // Константы операций для каллбэков: 7 | #define PROCESS_TERMINATE (0x0001) 8 | #define PROCESS_CREATE_THREAD (0x0002) 9 | #define PROCESS_SET_SESSIONID (0x0004) 10 | #define PROCESS_VM_OPERATION (0x0008) 11 | #define PROCESS_VM_READ (0x0010) 12 | #define PROCESS_VM_WRITE (0x0020) 13 | #define PROCESS_DUP_HANDLE (0x0040) 14 | #define PROCESS_CREATE_PROCESS (0x0080) 15 | #define PROCESS_SET_QUOTA (0x0100) 16 | #define PROCESS_SET_INFORMATION (0x0200) 17 | #define PROCESS_QUERY_INFORMATION (0x0400) 18 | #define PROCESS_SUSPEND_RESUME (0x0800) 19 | #define PROCESS_QUERY_LIMITED_INFORMATION (0x1000) 20 | 21 | #define THREAD_TERMINATE (0x0001) 22 | #define THREAD_SUSPEND_RESUME (0x0002) 23 | #define THREAD_GET_CONTEXT (0x0008) 24 | #define THREAD_SET_CONTEXT (0x0010) 25 | #define THREAD_SET_INFORMATION (0x0020) 26 | #define THREAD_QUERY_INFORMATION (0x0040) 27 | #define THREAD_SET_THREAD_TOKEN (0x0080) 28 | #define THREAD_IMPERSONATE (0x0100) 29 | #define THREAD_DIRECT_IMPERSONATION (0x0200) 30 | #define THREAD_SET_LIMITED_INFORMATION (0x0400) 31 | #define THREAD_QUERY_LIMITED_INFORMATION (0x0800) 32 | 33 | 34 | // Маска IOPL для RaiseIOPL*/ResetIOPL*: 35 | #define IOPL_ACCESS_MASK 0x3000 // 12й и 13й (начиная с нуля) биты в регистре EFLAGS 36 | 37 | #define ESP0_EFLAGS_OFFSET 12 // Смещение от дна стека в TSS->ESP0 (третье двойное слово) 38 | 39 | #define EFLAGS_RESERVED_BITS_MASK 0xFFC0802A 40 | #define MaskEFlagsReservedBits(EFlags) (EFlags | EFLAGS_RESERVED_BITS_MASK) 41 | 42 | // Получить адрес функции из ntoskrnl.exe/hal.dll: 43 | PVOID GetKernelProcAddress(LPWSTR ProcedureName); 44 | 45 | // Получение объектов процессов и потоков по их ID (делать DereferenceObject!): 46 | PEPROCESS GetPEPROCESS(HANDLE ProcessId); 47 | PETHREAD GetPETHREAD (HANDLE ThreadId); 48 | 49 | // Получение ID процессов и потоков по их объектам: 50 | #define GetProcessId(__PEPROCESS) PsGetProcessId(__PEPROCESS) 51 | #define GetThreadId(__PETHREAD) PsGetThreadId(__PETHREAD) 52 | 53 | // Информация о текущем процессе: 54 | #define GetCurrentProcessId() PsGetCurrentProcessId() 55 | #define GetCurrentProcess() ZwCurrentProcess() 56 | #define GetCurrentPEPROCESS() PsGetCurrentProcess() 57 | 58 | // Информация о текущем потоке: 59 | #define GetCurrentThreadId() PsGetCurrentThreadId() 60 | #define GetCurrentThread() ZwCurrentThread() 61 | #define GetCurrentPETHREAD() PsGetCurrentThread() 62 | 63 | // Получение объекта процесса по объекту потока в этом процессе: 64 | #define PETHREADtoPEPROCESS(Thread) IoThreadToProcess(Thread) 65 | #define PETHREAD2PEPROCESS PETHREADtoPEPROCESS 66 | #define T2P PETHREADtoPEPROCESS 67 | 68 | // Переключение в адресное пространство нужного процесса и обратно: 69 | BOOL AttachToProcess(HANDLE ProcessId, OUT PKAPC_STATE ApcState); 70 | BOOL DetachFromProcess(IN PKAPC_STATE ApcState); 71 | 72 | // Манипуляция контекстом потока: 73 | NTSTATUS GetThreadContext(IN PETHREAD Thread, IN OUT PCONTEXT Context, IN KPROCESSOR_MODE PreviousMode); 74 | NTSTATUS SetThreadContext(IN PETHREAD Thread, IN PCONTEXT Context , IN KPROCESSOR_MODE PreviousMode); 75 | 76 | // Информация о процессе: 77 | NTSTATUS SetInformationProcess( 78 | HANDLE hProcess, 79 | PROCESSINFOCLASS ProcessInformationClass, 80 | PVOID ProcessInformation, 81 | ULONG ProcessInformationLength 82 | ); 83 | 84 | NTSTATUS QueryInformationProcess( 85 | HANDLE hProcess, 86 | PROCESSINFOCLASS ProcessInformationClass, 87 | PVOID ProcessInformation, 88 | ULONG ProcessInformationLength, 89 | PULONG ReturnLength 90 | ); 91 | 92 | // Подъём IOPL: 93 | #ifdef _AMD64_ 94 | PKTRAP_FRAME GetTrapFrame(); 95 | VOID RaiseIOPLByTrapFrame(); 96 | VOID ResetIOPLByTrapFrame(); 97 | #endif 98 | VOID RaiseIOPLByTrapFrameScan(); 99 | VOID ResetIOPLByTrapFrameScan(); 100 | #ifdef _X86_ 101 | VOID RaiseIOPLByTSS(); 102 | VOID ResetIOPLByTSS(); 103 | #endif 104 | 105 | #ifdef _X86_ 106 | // Модификация IOPM: 107 | NTSTATUS RaiseIOPM(OPTIONAL HANDLE ProcessId); 108 | NTSTATUS ResetIOPM(OPTIONAL HANDLE ProcessId); 109 | #endif 110 | 111 | // Заморозка/разморозка процесса: 112 | NTSTATUS SuspendProcess(IN PEPROCESS Process); 113 | NTSTATUS ResumeProcess(IN PEPROCESS Process); 114 | 115 | // Открытие и завершение процесса: 116 | NTSTATUS OpenProcess(HANDLE ProcessId, OUT PHANDLE hProcess); 117 | NTSTATUS TerminateProcess(HANDLE hProcess, NTSTATUS ExitStatus); 118 | NTSTATUS KillProcess(HANDLE ProcessId); 119 | 120 | // Создание системных потоков (нельзя передавать юзермодные функции): 121 | NTSTATUS CreateSystemThread(OUT PHANDLE hThread, PKSTART_ROUTINE ThreadProc, PVOID Arguments); 122 | NTSTATUS ExitSystemThread(NTSTATUS ExitStatus); 123 | 124 | // Выделение и освобождение виртуальной памяти в контексте процесса: 125 | NTSTATUS VirtualAlloc(HANDLE hProcess, SIZE_T Size, IN OUT PVOID *VirtualAddress); 126 | NTSTATUS VirtualFree (HANDLE hProcess, PVOID VirtualAddress); 127 | NTSTATUS VirtualAllocInProcess(HANDLE ProcessId, SIZE_T Size, IN OUT PVOID *VirtualAddress); 128 | NTSTATUS VirtualFreeInProcess (HANDLE ProcessId, PVOID VirtualAddress); 129 | 130 | // Получить физический адрес памяти в определённом процессе: 131 | PHYSICAL_ADDRESS GetPhysicalAddressInProcess(HANDLE ProcessId, PVOID BaseVirtualAddress); 132 | 133 | // Отображение виртуальной памяти: 134 | PVOID MapVirtualMemory( 135 | HANDLE ProcessId, 136 | PVOID VirtualAddress, 137 | OPTIONAL PVOID MapToVirtualAddress, 138 | ULONG Size, 139 | KPROCESSOR_MODE ProcessorMode, 140 | OUT PMDL* pMdl 141 | ); 142 | VOID UnmapVirtualMemory(PMDL Mdl, PVOID MappedMemory); 143 | 144 | // Работа с памятью процессов: 145 | typedef enum _MEMORY_ACCESS_TYPE { 146 | MdlAccess, 147 | MdlWithPhysicalAccess, 148 | DirectPhysicalAccess 149 | } MEMORY_ACCESS_TYPE; 150 | 151 | BOOL ReadProcessMemory (HANDLE ProcessId, PVOID VirtualAddress, PVOID Buffer, ULONG BufferSize, BOOL IsUsermodeBuffer, MEMORY_ACCESS_TYPE AccessType); 152 | BOOL WriteProcessMemory(HANDLE ProcessId, PVOID VirtualAddress, PVOID Buffer, ULONG BufferSize, BOOL IsUsermodeBuffer, MEMORY_ACCESS_TYPE AccessType); 153 | 154 | // Закрытие хэндлов и уменьшение счётчика ссылок на объекты процессов и потоков: 155 | #define CloseProcess(hProcess) ZwClose(hProcess) 156 | #define CloseThread(hThread) ZwClose(hThread) 157 | #define DereferenceObject(Object) ObDereferenceObject(Object) 158 | 159 | 160 | /* Регистрация каллбэков-оповещений об операциях с хэндлами процессов и потоков: 161 | 162 | Для работы с каллбэками необходимо добавить флаг линкера /INTEGRITYCHECK 163 | Каллбэки устанавливать в DriverEntry! 164 | 165 | Шаблоны каллбэков: 166 | 167 | OB_PREOP_CALLBACK_STATUS ObjectPreCallback(IN PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation) { 168 | ... 169 | return OB_PREOP_SUCCESS; 170 | } 171 | 172 | VOID ObjectPostCallback(IN PVOID RegistrationContext, POB_POST_OPERATION_INFORMATION OperationInformation) { 173 | ... 174 | return; 175 | } 176 | */ 177 | 178 | typedef struct _HANDLES_NOTIFY_STRUCT { 179 | POBJECT_TYPE *ObjectType; // PsProcessType / PsThreadType / ExDesktopObjectType 180 | OB_OPERATION Operations; // OB_OPERATION_HANDLE_CREATE || OB_OPERATION_HANDLE_DUPLICATE 181 | POB_PRE_OPERATION_CALLBACK PreOperation; 182 | POB_POST_OPERATION_CALLBACK PostOperation; 183 | PVOID RegistrationContext; 184 | } HANDLES_NOTIFY_STRUCT, *PHANDLES_NOTIFY_STRUCT; 185 | 186 | NTSTATUS RegisterHandlesOperationsNotifier(IN PHANDLES_NOTIFY_STRUCT HandlesNotifyStruct, OUT PVOID *RegistrationHandle); 187 | VOID UnregisterHandlesOperationsNotifier(PVOID RegistrationHandle); -------------------------------------------------------------------------------- /EnjoyTheRing0/Protection.c: -------------------------------------------------------------------------------- 1 | #include "Protection.h" 2 | 3 | typedef struct _PROTECTED_PROCESS_ENTRY { 4 | HANDLE ProcessId; 5 | HANDLE DefenderId; 6 | } PROTECTED_PROCESS_ENTRY, *PPROTECTED_PROCESS_ENTRY; 7 | 8 | typedef struct _PROTECTION_INFO { 9 | BOOL IsInitialized; 10 | PVOID ProcessesCallbackHandle; 11 | PVOID ThreadsCallbackHandle; 12 | LINKED_LIST ProtectedProcesses; 13 | } PROTECTION_INFO, *PPROTECTION_INFO; 14 | 15 | static PROTECTION_INFO ProtectionInfo = { FALSE }; 16 | 17 | VOID FORCEINLINE FASTCALL SetRights(POB_PRE_OPERATION_INFORMATION OperationInformation, ACCESS_MASK Rights) { 18 | OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= Rights; 19 | OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= Rights; 20 | } 21 | 22 | OB_PREOP_CALLBACK_STATUS NTAPI PreOpenCallback(IN PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation) { 23 | UNREFERENCED_PARAMETER(RegistrationContext); 24 | 25 | if (ProtectionInfo.ProtectedProcesses.EntriesCount == 0) return OB_PREOP_SUCCESS; 26 | 27 | if (OperationInformation->ObjectType == *PsProcessType) { 28 | HANDLE ProcessId = GetProcessId((PEPROCESS)OperationInformation->Object); 29 | if (IsProcessProtected(ProcessId, ANY_PROCESS) != PROCESS_PROTECTED) return OB_PREOP_SUCCESS; 30 | SetRights(OperationInformation, (ACCESS_MASK)~DEFENCE_SUMMARY_PROCESSES_FLAGS); 31 | } 32 | 33 | if (OperationInformation->ObjectType == *PsThreadType) { 34 | HANDLE ProcessId = GetProcessId(PETHREAD2PEPROCESS((PETHREAD)OperationInformation->Object)); 35 | if (IsProcessProtected(ProcessId, ANY_PROCESS) != PROCESS_PROTECTED) return OB_PREOP_SUCCESS; 36 | SetRights(OperationInformation, (ACCESS_MASK)~DEFENCE_SUMMARY_THREADS_FLAGS); 37 | } 38 | 39 | return OB_PREOP_SUCCESS; 40 | } 41 | 42 | VOID NTAPI PostOpenCallback(IN PVOID RegistrationContext, POB_POST_OPERATION_INFORMATION OperationInformation) { 43 | UNREFERENCED_PARAMETER(RegistrationContext); 44 | UNREFERENCED_PARAMETER(OperationInformation); 45 | return; 46 | } 47 | 48 | BOOL RegisterProtection() { 49 | if (ProtectionInfo.IsInitialized) return TRUE; 50 | 51 | InitializeLinkedList(sizeof(PROTECTED_PROCESS_ENTRY), &ProtectionInfo.ProtectedProcesses, TRUE); 52 | 53 | NTSTATUS ProcessesCallbackStatus = STATUS_SUCCESS; 54 | NTSTATUS ThreadsCallbackStatus = STATUS_SUCCESS; 55 | 56 | // Каллбэк на процессы: 57 | if (ProtectionInfo.ProcessesCallbackHandle == NULL) { 58 | HANDLES_NOTIFY_STRUCT NotifyStruct; 59 | NotifyStruct.ObjectType = PsProcessType; 60 | NotifyStruct.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE; 61 | NotifyStruct.PostOperation = PostOpenCallback; 62 | NotifyStruct.PreOperation = PreOpenCallback; 63 | NotifyStruct.RegistrationContext = NULL; 64 | ProcessesCallbackStatus = RegisterHandlesOperationsNotifier(&NotifyStruct, &ProtectionInfo.ProcessesCallbackHandle); 65 | } 66 | 67 | // Каллбэк на потоки: 68 | if (ProtectionInfo.ThreadsCallbackHandle == NULL) { 69 | HANDLES_NOTIFY_STRUCT NotifyStruct; 70 | NotifyStruct.ObjectType = PsThreadType; 71 | NotifyStruct.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE; 72 | NotifyStruct.PostOperation = PostOpenCallback; 73 | NotifyStruct.PreOperation = PreOpenCallback; 74 | NotifyStruct.RegistrationContext = NULL; 75 | ThreadsCallbackStatus = RegisterHandlesOperationsNotifier(&NotifyStruct, &ProtectionInfo.ThreadsCallbackHandle); 76 | } 77 | 78 | ProtectionInfo.IsInitialized = ((ProcessesCallbackStatus | ThreadsCallbackStatus) == STATUS_SUCCESS); 79 | if (!ProtectionInfo.IsInitialized) { 80 | if (ProtectionInfo.ProcessesCallbackHandle != NULL) 81 | UnregisterHandlesOperationsNotifier(ProtectionInfo.ProcessesCallbackHandle); 82 | 83 | if (ProtectionInfo.ThreadsCallbackHandle != NULL) 84 | UnregisterHandlesOperationsNotifier(ProtectionInfo.ThreadsCallbackHandle); 85 | 86 | ProtectionInfo.ProcessesCallbackHandle = NULL; 87 | ProtectionInfo.ThreadsCallbackHandle = NULL; 88 | } 89 | return ProtectionInfo.IsInitialized; 90 | } 91 | 92 | VOID UnregisterProtection() { 93 | if (!ProtectionInfo.IsInitialized) return; 94 | 95 | if (ProtectionInfo.ProcessesCallbackHandle != NULL) 96 | UnregisterHandlesOperationsNotifier(ProtectionInfo.ProcessesCallbackHandle); 97 | 98 | if (ProtectionInfo.ThreadsCallbackHandle != NULL) 99 | UnregisterHandlesOperationsNotifier(ProtectionInfo.ThreadsCallbackHandle); 100 | 101 | ProtectionInfo.ProcessesCallbackHandle = NULL; 102 | ProtectionInfo.ThreadsCallbackHandle = NULL; 103 | 104 | ClearProtectedProcessesList(); 105 | 106 | ProtectionInfo.IsInitialized = FALSE; 107 | } 108 | 109 | 110 | 111 | 112 | 113 | VOID AddProtectedProcess(HANDLE ProcessId, HANDLE DefenderId) { 114 | if (!ProtectionInfo.IsInitialized) return; 115 | 116 | PPROTECTED_PROCESS_ENTRY Process; 117 | PROTECTION_STATUS ProtectionStatus = IsProcessProtected(ProcessId, DefenderId); 118 | 119 | switch (ProtectionStatus) { 120 | case PROCESS_NOT_PROTECTED: 121 | case DEFENDER_NOT_FOUND: 122 | AddLinkedListEntry(&ProtectionInfo.ProtectedProcesses); 123 | Process = (PPROTECTED_PROCESS_ENTRY)GetLLDataPtr(ProtectionInfo.ProtectedProcesses.LastEntry); 124 | Process->ProcessId = ProcessId; 125 | Process->DefenderId = DefenderId; 126 | } 127 | } 128 | 129 | 130 | 131 | typedef struct _REMOVE_PROCESS_INFO { 132 | HANDLE ProcessId; 133 | HANDLE DefenderId; 134 | } REMOVE_PROCESS_INFO, *PREMOVE_PROCESS_INFO; 135 | 136 | LINKED_LIST_ACTION FASTCALL RemoveProcessCallback(PPROTECTED_PROCESS_ENTRY Entry, PREMOVE_PROCESS_INFO ProcessInfo) { 137 | BOOL NeedToDelete = ((Entry->ProcessId == ProcessInfo->ProcessId) && (Entry->DefenderId == ProcessInfo->DefenderId)) || 138 | ((ProcessInfo->ProcessId == ANY_PROCESS) && (ProcessInfo->DefenderId == ANY_PROCESS)) || 139 | ((Entry->ProcessId == ProcessInfo->ProcessId) && (ProcessInfo->DefenderId == ANY_PROCESS)) || 140 | ((ProcessInfo->ProcessId == ANY_PROCESS) && (Entry->DefenderId == ProcessInfo->DefenderId)); 141 | 142 | return NeedToDelete ? LL_REMOVE : LL_CONTINUE; 143 | } 144 | 145 | VOID RemoveProtectedProcess(HANDLE ProcessId, HANDLE DefenderId) { 146 | if (!ProtectionInfo.IsInitialized) return; 147 | 148 | REMOVE_PROCESS_INFO ProcessInfo; 149 | ProcessInfo.ProcessId = ProcessId; 150 | ProcessInfo.DefenderId = DefenderId; 151 | ForEachLinkedListElement(&ProtectionInfo.ProtectedProcesses, &RemoveProcessCallback, &ProcessInfo); 152 | } 153 | 154 | 155 | 156 | typedef struct _FIND_PROCESS_INFO { 157 | HANDLE ProcessId; 158 | HANDLE DefenderId; 159 | BOOL ProcessFound; 160 | BOOL DefenderFound; 161 | } FIND_PROCESS_INFO, *PFIND_PROCESS_INFO; 162 | 163 | LINKED_LIST_ACTION FASTCALL FindProcessCallback(PPROTECTED_PROCESS_ENTRY Entry, PFIND_PROCESS_INFO ProcessInfo) { 164 | if (Entry->ProcessId == ProcessInfo->ProcessId) { 165 | ProcessInfo->ProcessFound = TRUE; 166 | if ((ProcessInfo->DefenderId == ANY_PROCESS) || (Entry->DefenderId == ProcessInfo->DefenderId)) { 167 | ProcessInfo->DefenderFound = TRUE; 168 | return LL_BREAK; 169 | } 170 | } 171 | return LL_CONTINUE; 172 | } 173 | 174 | 175 | PROTECTION_STATUS IsProcessProtected(HANDLE ProcessId, HANDLE DefenderId) { 176 | if (!ProtectionInfo.IsInitialized) return PROCESS_NOT_PROTECTED; 177 | 178 | // Перебираем все процессы: 179 | FIND_PROCESS_INFO ProcessInfo; 180 | ProcessInfo.ProcessId = ProcessId; 181 | ProcessInfo.DefenderId = DefenderId; 182 | ProcessInfo.ProcessFound = FALSE; 183 | ProcessInfo.DefenderFound = FALSE; 184 | ForEachLinkedListElement(&ProtectionInfo.ProtectedProcesses, &FindProcessCallback, &ProcessInfo); 185 | if (ProcessInfo.ProcessFound && ProcessInfo.DefenderFound) return PROCESS_PROTECTED; 186 | if (ProcessInfo.ProcessFound) return DEFENDER_NOT_FOUND; 187 | return PROCESS_NOT_PROTECTED; 188 | } 189 | 190 | 191 | 192 | VOID ClearProtectedProcessesList() { 193 | if (!ProtectionInfo.IsInitialized) return; 194 | ClearLinkedList(&ProtectionInfo.ProtectedProcesses); 195 | } 196 | 197 | 198 | 199 | LINKED_LIST_ACTION FASTCALL PrintProtectedProcessesCallback(PPROTECTED_PROCESS_ENTRY Entry, PVOID Argument) { 200 | UNREFERENCED_PARAMETER(Argument); 201 | DbgPrint(" - DefenderId: %d, ProcessId: %d\r\n", Entry->DefenderId, Entry->ProcessId); 202 | return LL_CONTINUE; 203 | } 204 | 205 | VOID PrintProtectedProcessesList() { 206 | if (!ProtectionInfo.IsInitialized) return; 207 | DbgPrint(":: Protected processes:\r\n"); 208 | ForEachLinkedListElement(&ProtectionInfo.ProtectedProcesses, &PrintProtectedProcessesCallback, NULL); 209 | DbgPrint(":: End of protected processes list\r\n"); 210 | } -------------------------------------------------------------------------------- /EnjoyTheRing0/Protection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ProcessesUtils.h" 4 | #include "LinkedLists.h" 5 | 6 | #define ANY_PROCESS (HANDLE)0xFFFFFFFF 7 | 8 | #define DEFENCE_SUMMARY_PROCESSES_FLAGS (\ 9 | PROCESS_TERMINATE |\ 10 | PROCESS_CREATE_THREAD |\ 11 | PROCESS_SET_SESSIONID |\ 12 | PROCESS_VM_OPERATION |\ 13 | PROCESS_VM_READ |\ 14 | PROCESS_VM_WRITE |\ 15 | PROCESS_DUP_HANDLE |\ 16 | PROCESS_SET_INFORMATION |\ 17 | PROCESS_QUERY_INFORMATION |\ 18 | PROCESS_SUSPEND_RESUME |\ 19 | PROCESS_QUERY_LIMITED_INFORMATION \ 20 | ) 21 | 22 | #define DEFENCE_SUMMARY_THREADS_FLAGS (\ 23 | THREAD_TERMINATE |\ 24 | THREAD_SUSPEND_RESUME |\ 25 | THREAD_GET_CONTEXT |\ 26 | THREAD_SET_CONTEXT |\ 27 | THREAD_SET_INFORMATION |\ 28 | THREAD_QUERY_INFORMATION |\ 29 | THREAD_SET_LIMITED_INFORMATION |\ 30 | THREAD_QUERY_LIMITED_INFORMATION \ 31 | ) 32 | 33 | BOOL RegisterProtection(); 34 | VOID UnregisterProtection(); 35 | 36 | VOID AddProtectedProcess (HANDLE ProcessId, HANDLE DefenderId); 37 | VOID RemoveProtectedProcess (HANDLE ProcessId, HANDLE DefenderId); 38 | 39 | typedef enum _PROTECTION_STATUS { 40 | PROCESS_PROTECTED, 41 | PROCESS_NOT_PROTECTED, 42 | DEFENDER_NOT_FOUND 43 | } PROTECTION_STATUS; 44 | 45 | PROTECTION_STATUS IsProcessProtected(HANDLE ProcessId, HANDLE DefenderId); 46 | 47 | VOID ClearProtectedProcessesList(); 48 | 49 | VOID PrintProtectedProcessesList(); 50 | 51 | -------------------------------------------------------------------------------- /EnjoyTheRing0/RegistryUtils.c: -------------------------------------------------------------------------------- 1 | #include "RegistryUtils.h" 2 | 3 | LPWSTR GetFullKeyPath(LPWSTR Root, LPWSTR KeyPath) { 4 | LPWSTR FullKeyPath; 5 | ConcatenateStringsW(Root, KeyPath, &FullKeyPath); 6 | return FullKeyPath; 7 | } 8 | 9 | 10 | 11 | NTSTATUS CreateKey(LPWSTR Root, LPWSTR KeyPath, OUT PHANDLE hKey) { 12 | LPWSTR FullKeyPath = GetFullKeyPath(Root, KeyPath); 13 | UNICODE_STRING UnicodePath; 14 | RtlInitUnicodeString(&UnicodePath, FullKeyPath); 15 | 16 | OBJECT_ATTRIBUTES ObjectAttributes; 17 | InitializeObjectAttributes(&ObjectAttributes, &UnicodePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); 18 | NTSTATUS Status = ZwCreateKey(hKey, KEY_ALL_ACCESS, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL); 19 | 20 | FreeString(FullKeyPath); 21 | return Status; 22 | } 23 | 24 | NTSTATUS OpenKey(LPWSTR Root, LPWSTR KeyPath, OUT PHANDLE hKey) { 25 | LPWSTR FullKeyPath = GetFullKeyPath(Root, KeyPath); 26 | UNICODE_STRING UnicodePath; 27 | RtlInitUnicodeString(&UnicodePath, FullKeyPath); 28 | 29 | OBJECT_ATTRIBUTES ObjectAttributes; 30 | InitializeObjectAttributes(&ObjectAttributes, &UnicodePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); 31 | NTSTATUS Status = ZwOpenKey(hKey, KEY_ALL_ACCESS, &ObjectAttributes); 32 | 33 | FreeString(FullKeyPath); 34 | return Status; 35 | } 36 | 37 | 38 | 39 | NTSTATUS DeleteKey(HANDLE hKey) { 40 | return ZwDeleteKey(hKey); 41 | } 42 | 43 | 44 | 45 | NTSTATUS SetKeyValue(HANDLE hKey, LPWSTR ValueName, ULONG Type, PVOID Data, ULONG DataSize) { 46 | UNICODE_STRING UnicodeValueName; 47 | RtlInitUnicodeString(&UnicodeValueName, ValueName); 48 | return ZwSetValueKey(hKey, &UnicodeValueName, 0, Type, Data, DataSize); 49 | } 50 | 51 | NTSTATUS SetKeyDword(HANDLE hKey, LPWSTR ValueName, DWORD Value) { 52 | return SetKeyValue(hKey, ValueName, REG_DWORD, &Value, sizeof(DWORD)); 53 | } 54 | 55 | NTSTATUS SeyKeyBinary(HANDLE hKey, LPWSTR ValueName, PVOID Data, ULONG DataSize) { 56 | return SetKeyValue(hKey, ValueName, REG_BINARY, Data, DataSize); 57 | } 58 | 59 | NTSTATUS SetKeyString(HANDLE hKey, LPWSTR ValueName, LPWSTR String) { 60 | return SetKeyValue(hKey, ValueName, REG_SZ, String, (ULONG)LengthW(String) * sizeof(WCHAR) + sizeof(WCHAR)); 61 | } 62 | 63 | NTSTATUS SetKeyExpandString(HANDLE hKey, LPWSTR ValueName, LPWSTR String) { 64 | return SetKeyValue(hKey, ValueName, REG_EXPAND_SZ, String, (ULONG)LengthW(String) * sizeof(WCHAR) + sizeof(WCHAR)); 65 | } 66 | 67 | 68 | 69 | NTSTATUS GetKeyValue(HANDLE hKey, LPWSTR ValueName, PVOID OutputBuffer, ULONG BufferSize, OUT OPTIONAL PULONG BytesReturned) { 70 | if (BytesReturned != NULL) *BytesReturned = 0; 71 | 72 | UNICODE_STRING UnicodeValueName; 73 | RtlInitUnicodeString(&UnicodeValueName, ValueName); 74 | 75 | ULONG PartialInformationSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + BufferSize - 1; 76 | PKEY_VALUE_PARTIAL_INFORMATION PartialInformation = GetMem(PartialInformationSize); 77 | 78 | ULONG ResultLength = 0; 79 | NTSTATUS Status = ZwQueryValueKey(hKey, &UnicodeValueName, KeyValuePartialInformation, PartialInformation, PartialInformationSize, &ResultLength); 80 | 81 | if NT_SUCCESS(Status) { 82 | RtlCopyMemory(OutputBuffer, PartialInformation->Data, PartialInformation->DataLength); 83 | if (BytesReturned != NULL) *BytesReturned = PartialInformation->DataLength; 84 | } else if ((BytesReturned != NULL) && ((Status == STATUS_BUFFER_OVERFLOW) || (Status == STATUS_BUFFER_TOO_SMALL))) { 85 | *BytesReturned = ResultLength - sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 1; 86 | } 87 | 88 | FreeMem(PartialInformation); 89 | return Status; 90 | } 91 | 92 | NTSTATUS GetKeyDword(HANDLE hKey, LPWSTR ValueName, OUT PDWORD Value) { 93 | return GetKeyValue(hKey, ValueName, Value, sizeof(DWORD), NULL); 94 | } 95 | 96 | NTSTATUS GetKeyBinary(HANDLE hKey, LPWSTR ValueName, OUT LPWSTR OutputBuffer, ULONG BufferSize, OUT OPTIONAL PULONG BytesReturned) { 97 | return GetKeyValue(hKey, ValueName, OutputBuffer, BufferSize, BytesReturned); 98 | } 99 | 100 | NTSTATUS GetKeyString(HANDLE hKey, LPWSTR ValueName, OUT LPWSTR OutputStringBuffer, ULONG BufferSize, OUT OPTIONAL PULONG BytesReturned) { 101 | return GetKeyValue(hKey, ValueName, OutputStringBuffer, BufferSize, BytesReturned); 102 | } 103 | 104 | NTSTATUS GetKeyStringWithAlloc(HANDLE hKey, LPWSTR ValueName, OUT LPWSTR *OutputStringBuffer, OUT OPTIONAL PULONG BytesReturned) { 105 | if (BytesReturned != NULL) *BytesReturned = 0; 106 | *OutputStringBuffer = NULL; 107 | 108 | ULONG RequiredMemory = 0; 109 | NTSTATUS Status = GetKeyString(hKey, ValueName, NULL, 0, &RequiredMemory); 110 | 111 | if (((Status == STATUS_BUFFER_OVERFLOW) || (Status == STATUS_BUFFER_TOO_SMALL)) && (RequiredMemory > 0)) { 112 | LPWSTR Buffer = GetMem(RequiredMemory); 113 | Status = GetKeyValue(hKey, ValueName, Buffer, RequiredMemory, BytesReturned != NULL ? BytesReturned : NULL); 114 | if (!NT_SUCCESS(Status)) FreeMem(Buffer); else *OutputStringBuffer = Buffer; 115 | } 116 | 117 | return Status; 118 | } 119 | 120 | 121 | 122 | NTSTATUS DeleteKeyValue(HANDLE hKey, LPWSTR ValueName) { 123 | UNICODE_STRING UnicodeValueName; 124 | RtlInitUnicodeString(&UnicodeValueName, ValueName); 125 | return ZwDeleteValueKey(hKey, &UnicodeValueName); 126 | } -------------------------------------------------------------------------------- /EnjoyTheRing0/RegistryUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MemoryUtils.h" 4 | #include "StringsUtils.h" 5 | 6 | // Значение Root для CreateKey и OpenKey: 7 | #define HKEY_CURRENT_USER L"\\Registry\\User\\.Default\\" 8 | #define HKEY_LOCAL_MACHINE L"\\Registry\\Machine\\" 9 | 10 | NTSTATUS CreateKey(LPWSTR Root, LPWSTR KeyPath, OUT PHANDLE hKey); 11 | NTSTATUS OpenKey (LPWSTR Root, LPWSTR KeyPath, OUT PHANDLE hKey); 12 | NTSTATUS DeleteKey(HANDLE hKey); 13 | 14 | #define CloseKey(hKey) ZwClose(hKey) 15 | 16 | NTSTATUS SetKeyValue (HANDLE hKey, LPWSTR ValueName, ULONG Type, PVOID Data, ULONG DataSize); 17 | NTSTATUS SetKeyDword (HANDLE hKey, LPWSTR ValueName, DWORD Value); 18 | NTSTATUS SeyKeyBinary(HANDLE hKey, LPWSTR ValueName, PVOID Data, ULONG DataSize); 19 | NTSTATUS SetKeyString(HANDLE hKey, LPWSTR ValueName, LPWSTR String); 20 | NTSTATUS SetKeyExpandString(HANDLE hKey, LPWSTR ValueName, LPWSTR String); 21 | 22 | NTSTATUS GetKeyValue (HANDLE hKey, LPWSTR ValueName, PVOID OutputBuffer, ULONG BufferSize, OUT OPTIONAL PULONG BytesReturned); 23 | NTSTATUS GetKeyDword (HANDLE hKey, LPWSTR ValueName, OUT PDWORD Value); 24 | 25 | NTSTATUS GetKeyBinary(HANDLE hKey, LPWSTR ValueName, OUT LPWSTR OutputBuffer, ULONG BufferSize, OUT OPTIONAL PULONG BytesReturned); 26 | NTSTATUS GetKeyString(HANDLE hKey, LPWSTR ValueName, OUT LPWSTR OutputStringBuffer, ULONG BufferSize, OUT OPTIONAL PULONG BytesReturned); 27 | NTSTATUS GetKeyStringWithAlloc(HANDLE hKey, LPWSTR ValueName, OUT LPWSTR *OutputStringBuffer, OUT OPTIONAL PULONG BytesReturned); 28 | 29 | NTSTATUS DeleteKeyValue(HANDLE hKey, LPWSTR ValueName); -------------------------------------------------------------------------------- /EnjoyTheRing0/ShellCode.c: -------------------------------------------------------------------------------- 1 | #include "ShellCode.h" 2 | 3 | // Отключаем выравнивание: 4 | #pragma pack(push, 1) 5 | typedef struct _SHELL_CODE_ARGUMENTS { 6 | PVOID GetProcAddress; 7 | PVOID InputData; 8 | PVOID OutputData; 9 | ULONG InputDataSize; 10 | ULONG OutputDataSize; 11 | } SHELL_CODE_ARGUMENTS, *PSHELL_CODE_ARGUMENTS; 12 | #pragma pack(pop) 13 | 14 | // Прототип шелл-функции: 15 | typedef SIZE_T(__stdcall *_ShellProc)(PSHELL_CODE_ARGUMENTS Arguments); 16 | 17 | // Дескриптор подготовленной для шелла памяти: 18 | typedef struct _MEMORY_DESCRIPTOR { 19 | PVOID UsermodeMemory; 20 | PVOID PreparedMemory; 21 | PMDL Mdl; 22 | ULONG Size; 23 | USERMODE_MEMORY_ACCESS AccessMethod; 24 | } MEMORY_DESCRIPTOR, *PMEMORY_DESCRIPTOR; 25 | 26 | // Подготовка юзермодной памяти для работы в ядре: 27 | BOOL FASTCALL PrepareUsermodeMemory(PUM_MEMORY_INFO UmMemoryInfo, PMEMORY_DESCRIPTOR MemoryDescriptor) { 28 | if ((UmMemoryInfo == NULL) && (MemoryDescriptor == NULL)) return FALSE; 29 | 30 | RtlZeroMemory(MemoryDescriptor, sizeof(MEMORY_DESCRIPTOR)); 31 | MemoryDescriptor->AccessMethod = UmMemoryInfo->AccessMethod; 32 | MemoryDescriptor->UsermodeMemory = UmMemoryInfo->Address; 33 | MemoryDescriptor->Size = UmMemoryInfo->Size; 34 | 35 | if (MemoryDescriptor->AccessMethod == UMA_DIRECT_ACCESS) { 36 | MemoryDescriptor->PreparedMemory = UmMemoryInfo->Address; 37 | return TRUE; 38 | } else if ((MemoryDescriptor->UsermodeMemory == NULL) || (MemoryDescriptor->Size == 0)) { 39 | return FALSE; 40 | } 41 | 42 | switch (MemoryDescriptor->AccessMethod) { 43 | case UMA_ALLOC_KERNEL_MEMORY: 44 | MemoryDescriptor->PreparedMemory = GetMem(MemoryDescriptor->Size); 45 | break; 46 | 47 | case UMA_MAP_USERMODE_MEMORY: 48 | MemoryDescriptor->PreparedMemory = MapVirtualMemory( 49 | PsGetCurrentProcessId(), 50 | MemoryDescriptor->UsermodeMemory, 51 | NULL, 52 | MemoryDescriptor->Size, 53 | KernelMode, 54 | &MemoryDescriptor->Mdl 55 | ); 56 | break; 57 | } 58 | 59 | return MemoryDescriptor->PreparedMemory != NULL; 60 | } 61 | 62 | // Освобождение подготовленной памяти: 63 | VOID FASTCALL FreePreparedMemory(PMEMORY_DESCRIPTOR MemoryDescriptor) { 64 | if (MemoryDescriptor == NULL) return; 65 | if (MemoryDescriptor->AccessMethod == UMA_DIRECT_ACCESS) return; 66 | if (MemoryDescriptor->PreparedMemory == NULL) return; 67 | 68 | switch (MemoryDescriptor->AccessMethod) { 69 | case UMA_ALLOC_KERNEL_MEMORY: 70 | FreeMem(MemoryDescriptor->PreparedMemory); 71 | break; 72 | 73 | case UMA_MAP_USERMODE_MEMORY: 74 | if (MemoryDescriptor->Mdl == NULL) 75 | UnmapVirtualMemory(MemoryDescriptor->Mdl, MemoryDescriptor->PreparedMemory); 76 | break; 77 | } 78 | 79 | RtlZeroMemory(MemoryDescriptor, sizeof(MEMORY_DESCRIPTOR)); 80 | } 81 | 82 | // Тип буфера (входной\выходной): 83 | typedef enum _SHELL_IO_BUFFER_TYPE { 84 | ShellInputBuffer, 85 | ShellOutputBuffer 86 | } SHELL_IO_BUFFER_TYPE, *PSHELL_IO_BUFFER_TYPE; 87 | 88 | // Подготовка буферов со входными и выходными данными: 89 | BOOL FASTCALL PrepareIoBuffer( 90 | IN OPTIONAL PUM_MEMORY_INFO MemoryInfo, 91 | IN PMEMORY_DESCRIPTOR MemoryDescriptor, 92 | SHELL_IO_BUFFER_TYPE ShellBufferType 93 | ) { 94 | if (MemoryDescriptor == NULL) return FALSE; 95 | RtlZeroMemory(MemoryDescriptor, sizeof(MEMORY_DESCRIPTOR)); 96 | if (MemoryInfo == NULL) return TRUE; 97 | 98 | // Проверяем, что переданная из юзермода информация о памяти доступна для чтения: 99 | if (!IsUsermodeMemoryReadable(MemoryInfo, sizeof(UM_MEMORY_INFO), NON_ALIGNED)) return FALSE; 100 | 101 | if ((MemoryInfo->AccessMethod != UMA_DIRECT_ACCESS) && (MemoryInfo->Size == 0)) return FALSE; 102 | 103 | // Проверяем, что входной и выходной буферы доступны для чтения\записи: 104 | switch (ShellBufferType) { 105 | case ShellInputBuffer: 106 | if (!IsUsermodeMemoryReadable(MemoryInfo->Address, MemoryInfo->Size, NON_ALIGNED)) return FALSE; 107 | break; 108 | 109 | case ShellOutputBuffer: 110 | if (!IsUsermodeMemoryWriteable(MemoryInfo->Address, MemoryInfo->Size, NON_ALIGNED)) return FALSE; 111 | break; 112 | } 113 | 114 | // Готовим буфер для работы в ядре: 115 | return PrepareUsermodeMemory(MemoryInfo, MemoryDescriptor); 116 | } 117 | 118 | // Исполнялка шеллов: 119 | SHELL_STATUS ExecuteShell( 120 | IN PVOID EntryPoint, 121 | IN PUM_MEMORY_INFO CodeBlock, 122 | IN OPTIONAL PUM_MEMORY_INFO InputData, 123 | IN OPTIONAL PUM_MEMORY_INFO OutputData, 124 | IN OPTIONAL PSIZE_T Result 125 | ) { 126 | // Проверяем валидность переданных аргументов: 127 | if (CodeBlock == NULL) return SHELL_INVALID_CODE_ADDRESS; 128 | if (CodeBlock->Address == NULL) return SHELL_INVALID_CODE_ADDRESS; 129 | #pragma warning(suppress: 4305) 130 | if ((EntryPoint < CodeBlock->Address) || (EntryPoint >= (PVOID)((PBYTE)CodeBlock->Address + CodeBlock->Size))) return SHELL_INVALID_CODE_ADDRESS; 131 | 132 | // Готовим память под код: 133 | MEMORY_DESCRIPTOR CodeMemory; 134 | if (PrepareUsermodeMemory(CodeBlock, &CodeMemory)) { 135 | if (CodeMemory.AccessMethod == UMA_ALLOC_KERNEL_MEMORY) 136 | RtlCopyMemory(CodeMemory.PreparedMemory, CodeMemory.UsermodeMemory, CodeMemory.Size); 137 | } else { 138 | return SHELL_CODE_BUFFER_ERROR; 139 | } 140 | 141 | // Определяем дескрипторы входного и выходного буферов: 142 | MEMORY_DESCRIPTOR InputMemory, OutputMemory; 143 | 144 | BOOL InputPreparingStatus = InputData == NULL; 145 | BOOL OutputPreparingStatus = OutputData == NULL; 146 | 147 | // Готовим входной и выходной буферы: 148 | if (InputData) { 149 | InputPreparingStatus = PrepareIoBuffer(InputData, &InputMemory, ShellInputBuffer); 150 | } else { 151 | RtlZeroMemory(&InputMemory, sizeof(MEMORY_DESCRIPTOR)); 152 | } 153 | 154 | if (OutputData) { 155 | OutputPreparingStatus = PrepareIoBuffer(OutputData, &OutputMemory, ShellOutputBuffer); 156 | } else { 157 | RtlZeroMemory(&OutputMemory, sizeof(MEMORY_DESCRIPTOR)); 158 | } 159 | 160 | // Проверяем, успешно ли подготовили буферы: 161 | if (InputPreparingStatus && OutputPreparingStatus) { 162 | // Если используем выделение памяти в ядре - копируем входные данные в промежуточный буфер: 163 | if (InputMemory.AccessMethod == UMA_ALLOC_KERNEL_MEMORY) 164 | RtlCopyMemory(InputMemory.PreparedMemory, InputMemory.UsermodeMemory, InputMemory.Size); 165 | } else { 166 | FreePreparedMemory(&CodeMemory); 167 | FreePreparedMemory(&InputMemory); 168 | FreePreparedMemory(&OutputMemory); 169 | return InputPreparingStatus ? SHELL_OUTPUT_BUFFER_ERROR : SHELL_INPUT_BUFFER_ERROR; 170 | } 171 | 172 | // Заполняем структуру, передаваемую шеллкоду: 173 | SHELL_CODE_ARGUMENTS ShellArguments; 174 | #pragma warning(suppress: 4152) 175 | ShellArguments.GetProcAddress = &GetKernelProcAddress; 176 | ShellArguments.InputData = InputMemory.PreparedMemory; 177 | ShellArguments.OutputData = OutputMemory.PreparedMemory; 178 | ShellArguments.InputDataSize = InputMemory.Size; 179 | ShellArguments.OutputDataSize = OutputMemory.Size; 180 | 181 | // Сохраняем состояние FPU: 182 | KFLOATING_SAVE FPUState; 183 | if NT_ERROR(KeSaveFloatingPointState(&FPUState)) { 184 | FreePreparedMemory(&CodeMemory); 185 | FreePreparedMemory(&InputMemory); 186 | FreePreparedMemory(&OutputMemory); 187 | return SHELL_SAVING_FPU_STATE_ERROR; 188 | } 189 | 190 | // Отключаем SMEP и защиту от записи: 191 | GlobalDisableSmepSmap(); 192 | GlobalDisableWriteProtection(); 193 | 194 | SHELL_STATUS Status = SHELL_SUCCESS; 195 | 196 | // Выполняем шелл-код: 197 | #pragma warning(suppress: 4305) 198 | SIZE_T EntryPointOffset = (SIZE_T)EntryPoint - (SIZE_T)CodeBlock->Address; 199 | _ShellProc ShellProc = (_ShellProc)((SIZE_T)CodeMemory.PreparedMemory + EntryPointOffset); 200 | __try { 201 | // Переходим на выполнение шелла: 202 | SIZE_T ShellResult = ShellProc(&ShellArguments); 203 | 204 | // Возвращаем результат: 205 | if (Result) { 206 | if (IsUsermodeMemoryWriteable(Result, sizeof(SIZE_T), NON_ALIGNED)) { 207 | *Result = ShellResult; 208 | } else { 209 | Status = SHELL_INVALID_RETURN_ADDRESS; 210 | } 211 | } 212 | 213 | // Возвращаем выходной буфер, если использовался промежуточный буфер в ядре: 214 | if ((OutputData) && (OutputMemory.AccessMethod == UMA_ALLOC_KERNEL_MEMORY)) 215 | RtlCopyMemory(OutputData->Address, OutputMemory.PreparedMemory, OutputData->Size); 216 | } 217 | __except (EXCEPTION_EXECUTE_HANDLER) { 218 | Status = SHELL_RUNTIME_ERROR; 219 | } 220 | 221 | // Включаем SMEP и защиту от записи: 222 | GlobalEnableWriteProtection(); 223 | GlobalEnableSmepSmap(); 224 | 225 | // Возвращаем состояние FPU: 226 | KeRestoreFloatingPointState(&FPUState); 227 | 228 | // Освобождаем ресурсы: 229 | FreePreparedMemory(&CodeMemory); 230 | FreePreparedMemory(&InputMemory); 231 | FreePreparedMemory(&OutputMemory); 232 | 233 | return Status; 234 | } -------------------------------------------------------------------------------- /EnjoyTheRing0/ShellCode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ProcessesUtils.h" 4 | #include "NativeFunctions.h" 5 | #include "MemoryAccessController.h" 6 | 7 | typedef enum _SHELL_STATUS { 8 | SHELL_SUCCESS, 9 | SHELL_CODE_BUFFER_ERROR, 10 | SHELL_INPUT_BUFFER_ERROR, 11 | SHELL_OUTPUT_BUFFER_ERROR, 12 | SHELL_INVALID_CODE_ADDRESS, 13 | SHELL_SAVING_FPU_STATE_ERROR, 14 | SHELL_INVALID_RETURN_ADDRESS, 15 | SHELL_RUNTIME_ERROR 16 | } SHELL_STATUS, *PSHELL_STATUS; 17 | 18 | 19 | #define UMA_DIRECT_ACCESS 0 20 | #define UMA_ALLOC_KERNEL_MEMORY 1 21 | #define UMA_MAP_USERMODE_MEMORY 2 22 | 23 | typedef BYTE USERMODE_MEMORY_ACCESS; 24 | 25 | typedef struct _UM_MEMORY_INFO { 26 | PVOID64 Address; 27 | ULONG Size; 28 | USERMODE_MEMORY_ACCESS AccessMethod; 29 | } UM_MEMORY_INFO, *PUM_MEMORY_INFO; 30 | 31 | SHELL_STATUS ExecuteShell( 32 | IN PVOID EntryPoint, 33 | IN PUM_MEMORY_INFO CodeBlock, 34 | IN OPTIONAL PUM_MEMORY_INFO InputData, 35 | IN OPTIONAL PUM_MEMORY_INFO OutputData, 36 | IN OPTIONAL PSIZE_T Result 37 | ); -------------------------------------------------------------------------------- /EnjoyTheRing0/StringsUtils.c: -------------------------------------------------------------------------------- 1 | #include "StringsUtils.h" 2 | #include 3 | 4 | #define ValidateMaxBufferSize(MaxBufferSizeVariable) if ((MaxBufferSizeVariable) > MAX_CHARS) (MaxBufferSizeVariable) = MAX_CHARS; 5 | 6 | LPWSTR AllocWideString(SIZE_T MaxCharactersCount, BOOL AddNullTerminator, OUT OPTIONAL SIZE_T* AllocatedCharacters) { 7 | if (AddNullTerminator) MaxCharactersCount += 1; 8 | if (AllocatedCharacters != NULL) *AllocatedCharacters = MaxCharactersCount; 9 | return GetMem(MaxCharactersCount * sizeof(WCHAR)); 10 | } 11 | 12 | LPSTR AllocAnsiString(SIZE_T MaxCharactersCount, BOOL AddNullTerminator, OUT OPTIONAL SIZE_T* AllocatedCharacters) { 13 | if (AddNullTerminator) MaxCharactersCount += 1; 14 | if (AllocatedCharacters != NULL) *AllocatedCharacters = MaxCharactersCount; 15 | return GetMem(MaxCharactersCount * sizeof(CHAR)); 16 | } 17 | 18 | NTSTATUS SafeStrCatA(LPSTR Dest, SIZE_T DestMaxCharacters, LPSTR ConcatenateWith) { 19 | ValidateMaxBufferSize(DestMaxCharacters); 20 | return RtlStringCchCatA(Dest, DestMaxCharacters, ConcatenateWith); 21 | } 22 | 23 | NTSTATUS SafeStrCatW(LPWSTR Dest, SIZE_T DestMaxCharacters, LPWSTR ConcatenateWith) { 24 | ValidateMaxBufferSize(DestMaxCharacters); 25 | return RtlStringCchCatW(Dest, DestMaxCharacters, ConcatenateWith); 26 | } 27 | 28 | NTSTATUS SafeStrCpyA(LPSTR Dest, SIZE_T DestMaxCharacters, LPSTR Source) { 29 | ValidateMaxBufferSize(DestMaxCharacters); 30 | return RtlStringCchCopyA(Dest, DestMaxCharacters, Source); 31 | } 32 | 33 | NTSTATUS SafeStrCpyW(LPWSTR Dest, SIZE_T DestMaxCharacters, LPWSTR Source) { 34 | ValidateMaxBufferSize(DestMaxCharacters); 35 | return RtlStringCchCopyW(Dest, DestMaxCharacters, Source); 36 | } 37 | 38 | NTSTATUS SafeStrLenA(LPSTR String, SIZE_T MaxCharacters, PSIZE_T Length) { 39 | ValidateMaxBufferSize(MaxCharacters); 40 | return RtlStringCchLengthA(String, MaxCharacters, (size_t *)Length); 41 | } 42 | 43 | NTSTATUS SafeStrLenW(LPWSTR String, SIZE_T MaxCharacters, PSIZE_T Length) { 44 | ValidateMaxBufferSize(MaxCharacters); 45 | return RtlStringCchLengthW(String, MaxCharacters, (size_t *)Length); 46 | } 47 | 48 | SIZE_T LengthA(LPSTR Str) { 49 | SIZE_T Length = 0; 50 | SafeStrLenA(Str, MAX_CHARS, &Length); 51 | return Length; 52 | } 53 | 54 | SIZE_T LengthW(LPWSTR Str) { 55 | SIZE_T Length = 0; 56 | SafeStrLenW(Str, MAX_CHARS, &Length); 57 | return Length; 58 | } 59 | 60 | SIZE_T ConcatenateStringsA(LPSTR SrcString, LPSTR ConcatenateWith, OUT LPSTR* ResultString) { 61 | SIZE_T SrcStringLength = LengthA(SrcString); 62 | SIZE_T ConcatenateWithLength = LengthA(ConcatenateWith); 63 | SIZE_T ResultLength = SrcStringLength + ConcatenateWithLength; 64 | *ResultString = AllocAnsiString(ResultLength, TRUE, &ResultLength); 65 | SafeStrCpyA(*ResultString, ResultLength, SrcString); 66 | SafeStrCatA(*ResultString, ResultLength, ConcatenateWith); 67 | return ResultLength - 1; // Вычитаем нуль-терминатор 68 | } 69 | 70 | SIZE_T ConcatenateStringsW(LPWSTR SrcString, LPWSTR ConcatenateWith, OUT LPWSTR* ResultString) { 71 | SIZE_T SrcStringLength = LengthW(SrcString); 72 | SIZE_T ConcatenateWithLength = LengthW(ConcatenateWith); 73 | SIZE_T ResultLength = SrcStringLength + ConcatenateWithLength; 74 | *ResultString = AllocWideString(ResultLength, TRUE, &ResultLength); 75 | SafeStrCpyW(*ResultString, ResultLength, SrcString); 76 | SafeStrCatW(*ResultString, ResultLength, ConcatenateWith); 77 | return ResultLength - 1; // Вычитаем нуль-терминатор 78 | } 79 | 80 | -------------------------------------------------------------------------------- /EnjoyTheRing0/StringsUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MemoryUtils.h" 4 | 5 | #define MAX_CHARS 2147483647 // Максимальное значение DestMaxCharacters 6 | 7 | // Выделение памяти под ANSI- и Wide-строки: 8 | LPWSTR AllocWideString(SIZE_T MaxCharactersCount, BOOL AddNullTerminator, OUT OPTIONAL SIZE_T* AllocatedCharacters); 9 | LPSTR AllocAnsiString(SIZE_T MaxCharactersCount, BOOL AddNullTerminator, OUT OPTIONAL SIZE_T* AllocatedCharacters); 10 | 11 | // DestMaxCharacters и MaxCharacters - размер буфера в СИМВОЛАХ с учётом символа для нуль-терминатора 12 | 13 | NTSTATUS SafeStrCatA(LPSTR Dest, SIZE_T DestMaxCharacters, LPSTR ConcatenateWith); 14 | NTSTATUS SafeStrCatW(LPWSTR Dest, SIZE_T DestMaxCharacters, LPWSTR ConcatenateWith); 15 | 16 | NTSTATUS SafeStrCpyA(LPSTR Dest, SIZE_T DestMaxCharacters, LPSTR Source); 17 | NTSTATUS SafeStrCpyW(LPWSTR Dest, SIZE_T DestMaxCharacters, LPWSTR Source); 18 | 19 | NTSTATUS SafeStrLenA(LPSTR String, SIZE_T MaxCharacters, PSIZE_T Length); 20 | NTSTATUS SafeStrLenW(LPWSTR String, SIZE_T MaxCharacters, PSIZE_T Length); 21 | 22 | // Длина строки в символах без нуль-терминатора: 23 | SIZE_T LengthA(LPSTR Str); 24 | SIZE_T LengthW(LPWSTR Str); 25 | 26 | // Выделение памяти и конкатенация строк, возвращает количество символов в итоговой строке БЕЗ нуль-терминатора; 27 | // память необходимо освобождать с помощью FreeString: 28 | SIZE_T ConcatenateStringsA(LPSTR SrcString, LPSTR ConcatenateWith, OUT LPSTR* ResultString); 29 | SIZE_T ConcatenateStringsW(LPWSTR SrcString, LPWSTR ConcatenateWith, OUT LPWSTR* ResultString); 30 | 31 | // Освобождение памяти, выделенной при ConcatenateStrings: 32 | #define FreeString(String) FreeMem(String) -------------------------------------------------------------------------------- /EnjoyTheRing0/Synchronization.c: -------------------------------------------------------------------------------- 1 | #include "Synchronization.h" 2 | 3 | typedef VOID NTKERNELAPI (FASTCALL *_InitializeGuardedMutex) (PKGUARDED_MUTEX GuardedMutex); 4 | typedef VOID NTKERNELAPI (FASTCALL *_AcquireGuardedMutex) (PKGUARDED_MUTEX GuardedMutex); 5 | typedef VOID NTKERNELAPI (FASTCALL *_ReleaseGuardedMutex) (PKGUARDED_MUTEX GuardedMutex); 6 | typedef BOOLEAN NTKERNELAPI (FASTCALL *_TryToAcquireGuardedMutex) (PKGUARDED_MUTEX GuardedMutex); 7 | 8 | static _InitializeGuardedMutex InitializeGuardedMutex = NULL; 9 | static _AcquireGuardedMutex AcquireGuardedMutex = NULL; 10 | static _ReleaseGuardedMutex ReleaseGuardedMutex = NULL; 11 | static _TryToAcquireGuardedMutex TryToAcquireGuardedMutex = NULL; 12 | 13 | static volatile BOOL IsSynchronizationInitialized = FALSE; 14 | static volatile BOOL GuardedSupport = FALSE; 15 | 16 | VOID InitUniversalMutexFunctions() { 17 | #pragma warning(push) 18 | #pragma warning(disable: 4055) 19 | #pragma warning(disable: 4047) 20 | InitializeGuardedMutex = (_InitializeGuardedMutex) GetKernelProcAddress(L"KeInitializeGuardedMutex"); 21 | AcquireGuardedMutex = (_AcquireGuardedMutex) GetKernelProcAddress(L"KeAcquireGuardedMutex"); 22 | ReleaseGuardedMutex = (_ReleaseGuardedMutex) GetKernelProcAddress(L"KeReleaseGuardedMutex"); 23 | TryToAcquireGuardedMutex = (_TryToAcquireGuardedMutex) GetKernelProcAddress(L"KeTryToAcquireGuardedMutex"); 24 | 25 | GuardedSupport = ((SIZE_T)InitializeGuardedMutex & (SIZE_T)AcquireGuardedMutex & 26 | (SIZE_T)ReleaseGuardedMutex & (SIZE_T)TryToAcquireGuardedMutex) != NULL; 27 | #pragma warning(pop) 28 | IsSynchronizationInitialized = TRUE; 29 | } 30 | 31 | BOOL FORCEINLINE FASTCALL IsLockedBy(PMUTEX Mutex, PETHREAD Thread) { 32 | return Mutex->LockedByThread == Thread; 33 | } 34 | 35 | VOID FORCEINLINE FASTCALL LockLegacyMutex(PRKMUTEX Mutex, BOOL UserThread) { 36 | KeWaitForMutexObject(Mutex, UserThread ? UserRequest : Executive, KernelMode, FALSE, NULL); 37 | } 38 | 39 | VOID InitializeMutex(PMUTEX Mutex, BOOL IsUserThread) { 40 | if (!IsSynchronizationInitialized) InitUniversalMutexFunctions(); 41 | 42 | ZeroMemory(Mutex, sizeof(MUTEX)); 43 | 44 | if (GuardedSupport) { 45 | InitializeGuardedMutex(&Mutex->Mutex); 46 | } else { 47 | KeInitializeMutex(&Mutex->LegacyMutex, 0); 48 | Mutex->UserThread = IsUserThread; 49 | } 50 | } 51 | 52 | VOID AcquireLock(PMUTEX Mutex) { 53 | if (GuardedSupport) { 54 | PETHREAD CurrentThread = PsGetCurrentThread(); 55 | 56 | if (IsLockedBy(Mutex, CurrentThread)) { 57 | Mutex->LocksCount++; 58 | return; 59 | } 60 | 61 | AcquireGuardedMutex(&Mutex->Mutex); 62 | Mutex->LockedByThread = CurrentThread; 63 | Mutex->LocksCount = 1; 64 | } else { 65 | LockLegacyMutex(&Mutex->LegacyMutex, Mutex->UserThread); 66 | } 67 | } 68 | 69 | VOID ReleaseLock(PMUTEX Mutex) { 70 | if (GuardedSupport) { 71 | if (IsLockedBy(Mutex, PsGetCurrentThread())) { 72 | Mutex->LocksCount--; 73 | if (Mutex->LocksCount == 0) { 74 | Mutex->LockedByThread = NULL; 75 | ReleaseGuardedMutex(&Mutex->Mutex); 76 | } 77 | } 78 | } else { 79 | KeReleaseMutex(&Mutex->LegacyMutex, FALSE); 80 | } 81 | } 82 | 83 | BOOL IsMutexLocked(PMUTEX Mutex) { 84 | BOOL IsLocked; 85 | if (GuardedSupport) { 86 | IsLocked = TryToAcquireGuardedMutex(&Mutex->Mutex); 87 | if (IsLocked) ReleaseGuardedMutex(&Mutex->Mutex); 88 | } else { 89 | IsLocked = KeReadStateMutex(&Mutex->LegacyMutex) != 1; 90 | } 91 | return IsLocked; 92 | } 93 | 94 | 95 | 96 | VOID WaitMutex(PMUTEX Mutex) { 97 | if (GuardedSupport) { 98 | if (IsLockedBy(Mutex, PsGetCurrentThread())) return; 99 | AcquireLock(Mutex); 100 | ReleaseLock(Mutex); 101 | } else { 102 | LockLegacyMutex(&Mutex->LegacyMutex, Mutex->UserThread); 103 | KeReleaseMutex(&Mutex->LegacyMutex, TRUE); 104 | } 105 | } 106 | 107 | -------------------------------------------------------------------------------- /EnjoyTheRing0/Synchronization.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ProcessesUtils.h" 4 | 5 | typedef struct _MUTEX { 6 | BOOL UserThread; 7 | volatile LONG LocksCount; // Количество блокировок внутри одного потока 8 | volatile PETHREAD LockedByThread; 9 | KGUARDED_MUTEX Mutex; 10 | KMUTEX LegacyMutex; 11 | } MUTEX, *PMUTEX; 12 | 13 | VOID InitializeMutex(PMUTEX Mutex, BOOL IsUserThread); 14 | 15 | VOID AcquireLock(PMUTEX Mutex); 16 | VOID ReleaseLock(PMUTEX Mutex); 17 | 18 | BOOL IsMutexLocked(PMUTEX Mutex); 19 | VOID WaitMutex(PMUTEX Mutex); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EnjoyTheRing0 Project 2 | Шаблон драйвера и обёртки над функциями ядра Windows для быстрой и удобной разработки в Ring0. 3 | Предоставляет функционал для работы с: 4 | * Виртуальной и физической памятью, DMI (✔) 5 | * Строками (✔) 6 | * Файлами и папками (✔) 7 | * Процессами (✔) 8 | * Реестром (✔) 9 | * Портами ввода-вывода (+ проброс в юзермод) (✔) 10 | * Недоступными в юзермоде регистрами (MSR, CR, DR) (✔) 11 | * Выполнением произвольного кода в ядре (шеллами) (✔) 12 | * Железом (PCI) (✔) 13 | 14 | Для сборки требуются [Visual Studio Community](https://www.visualstudio.com/post-download-vs?sku=community&clcid=0x419) 15 | и установленный [Windows Driver Kit](https://msdn.microsoft.com/en-us/windows/hardware/gg454513.aspx). 16 | Для установки и запуска: [DriversAPI Utility](https://github.com/HoShiMin/DriversAPI/releases). 17 | Для просмотра отладочного вывода: [DebugView](https://technet.microsoft.com/ru-ru/sysinternals/bb896647.aspx). 18 | Для проверки работоспособности и отладки: [VMware Player](http://www.vmware.com/products/player/playerpro-evaluation.html) 19 | 20 | Обёртка для Delphi: [Здесь](https://gist.github.com/HoShiMin/f5b1f069e2c177d48033ed1eeb90cea0) 21 | Последний релиз (подписанные бинарники x86/x64): [Здесь](https://github.com/HoShiMin/EnjoyTheRing0/releases) 22 | 23 | Отключение проверки цифровой подписи и перевод в Windows в тестовый режим: 24 | 25 | - Отключение проверки цифровой подписи (разрешить устанавливать неподписанные драйвера): 26 | bcdedit.exe /set loadoptions DISABLE_INTEGRITY_CHECKS 27 | bcdedit.exe /set TESTSIGNING ON 28 | 29 | - Включение проверки цифровой подписи (запретить устанавливать неподписанные драйвера): 30 | bcdedit.exe /set loadoptions ENABLE_INTEGRITY_CHECKS 31 | bcdedit.exe /set TESTSIGNING OFF 32 | 33 | - Включение поддержки ядерной отладки (kernel-debugging) для WinDbg и Kernel Debugger из WDK: 34 | bcdedit.exe /debug on - включить 35 | bcdedit.exe /debug off - выключить 36 | -------------------------------------------------------------------------------- /WinDbg Workspace.WEW: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HoShiMin/EnjoyTheRing0/ea426c4ce56e5cf406732a572dc8db8b3c5e6626/WinDbg Workspace.WEW --------------------------------------------------------------------------------