├── .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 |
241 |
245 |
246 |
247 |
248 |
249 |
--------------------------------------------------------------------------------
/EnjoyTheRing0/EnjoyTheRing0.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
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
--------------------------------------------------------------------------------