├── .gitignore
├── LICENSE
├── MManager
├── MManager.sln
├── MManager
│ ├── MManager.vcxproj
│ ├── MManager.vcxproj.filters
│ ├── main.c
│ ├── mm
│ │ ├── mmtypes.h
│ │ ├── vad.c
│ │ └── vad.h
│ ├── mmanager-dispatch.c
│ ├── mmanager-dispatch.h
│ ├── mmanager-globals.h
│ ├── mmanager-routines.c
│ ├── mmanager-routines.h
│ └── rtl
│ │ └── osversion.h
└── vadlist
│ ├── main.cpp
│ ├── mmanager.cpp
│ ├── mmanager.h
│ ├── vadlist.vcxproj
│ └── vadlist.vcxproj.filters
├── README.md
├── WKI
├── WKI.sln
├── WKIKM
│ ├── WKIKM.vcxproj
│ ├── WKIKM.vcxproj.filters
│ ├── ki-globals.h
│ ├── main.c
│ └── wki
│ │ ├── wki.c
│ │ └── wki.h
└── WKIUM
│ ├── WKIUM.vcxproj
│ ├── WKIUM.vcxproj.filters
│ ├── callback.c
│ ├── dirutil.c
│ ├── inc
│ ├── callback.h
│ ├── dirutil.h
│ ├── interface.h
│ ├── msdia
│ │ └── inlcude
│ │ │ ├── cvconst.h
│ │ │ ├── dia2.h
│ │ │ └── diacreate.h
│ └── registry.h
│ ├── interface.c
│ ├── main.c
│ ├── registry.c
│ └── tools
│ ├── msdia140.dll
│ └── symsrv.dll
└── mpp
├── mpp-client
├── device.hpp
├── main.cpp
├── mpp-client.vcxproj
├── mpp-client.vcxproj.filters
├── sym.cpp
└── sym.hpp
├── mpp.sln
└── mpp
├── main.cpp
├── mpp.cpp
├── mpp.hpp
├── mpp.vcxproj
├── mpp.vcxproj.filters
├── worker.cpp
└── worker.hpp
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Ll]og/
33 | [Ll]ogs/
34 |
35 | # Visual Studio 2015/2017 cache/options directory
36 | .vs/
37 | # Uncomment if you have tasks that create the project's static files in wwwroot
38 | #wwwroot/
39 |
40 | # Visual Studio 2017 auto generated files
41 | Generated\ Files/
42 |
43 | # MSTest test Results
44 | [Tt]est[Rr]esult*/
45 | [Bb]uild[Ll]og.*
46 |
47 | # NUnit
48 | *.VisualState.xml
49 | TestResult.xml
50 | nunit-*.xml
51 |
52 | # Build Results of an ATL Project
53 | [Dd]ebugPS/
54 | [Rr]eleasePS/
55 | dlldata.c
56 |
57 | # Benchmark Results
58 | BenchmarkDotNet.Artifacts/
59 |
60 | # .NET Core
61 | project.lock.json
62 | project.fragment.lock.json
63 | artifacts/
64 |
65 | # ASP.NET Scaffolding
66 | ScaffoldingReadMe.txt
67 |
68 | # StyleCop
69 | StyleCopReport.xml
70 |
71 | # Files built by Visual Studio
72 | *_i.c
73 | *_p.c
74 | *_h.h
75 | *.ilk
76 | *.meta
77 | *.obj
78 | *.iobj
79 | *.pch
80 | *.pdb
81 | *.ipdb
82 | *.pgc
83 | *.pgd
84 | *.rsp
85 | *.sbr
86 | *.tlb
87 | *.tli
88 | *.tlh
89 | *.tmp
90 | *.tmp_proj
91 | *_wpftmp.csproj
92 | *.log
93 | *.tlog
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
298 | *.vbp
299 |
300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
301 | *.dsw
302 | *.dsp
303 |
304 | # Visual Studio 6 technical files
305 | *.ncb
306 | *.aps
307 |
308 | # Visual Studio LightSwitch build output
309 | **/*.HTMLClient/GeneratedArtifacts
310 | **/*.DesktopClient/GeneratedArtifacts
311 | **/*.DesktopClient/ModelManifest.xml
312 | **/*.Server/GeneratedArtifacts
313 | **/*.Server/ModelManifest.xml
314 | _Pvt_Extensions
315 |
316 | # Paket dependency manager
317 | .paket/paket.exe
318 | paket-files/
319 |
320 | # FAKE - F# Make
321 | .fake/
322 |
323 | # CodeRush personal settings
324 | .cr/personal
325 |
326 | # Python Tools for Visual Studio (PTVS)
327 | __pycache__/
328 | *.pyc
329 |
330 | # Cake - Uncomment if you are using it
331 | # tools/**
332 | # !tools/packages.config
333 |
334 | # Tabs Studio
335 | *.tss
336 |
337 | # Telerik's JustMock configuration file
338 | *.jmconfig
339 |
340 | # BizTalk build output
341 | *.btp.cs
342 | *.btm.cs
343 | *.odx.cs
344 | *.xsd.cs
345 |
346 | # OpenCover UI analysis results
347 | OpenCover/
348 |
349 | # Azure Stream Analytics local run output
350 | ASALocalRun/
351 |
352 | # MSBuild Binary and Structured Log
353 | *.binlog
354 |
355 | # NVidia Nsight GPU debugger configuration file
356 | *.nvuser
357 |
358 | # MFractors (Xamarin productivity tool) working folder
359 | .mfractor/
360 |
361 | # Local History for Visual Studio
362 | .localhistory/
363 |
364 | # Visual Studio History (VSHistory) files
365 | .vshistory/
366 |
367 | # BeatPulse healthcheck temp database
368 | healthchecksdb
369 |
370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
371 | MigrationBackup/
372 |
373 | # Ionide (cross platform F# VS Code tools) working folder
374 | .ionide/
375 |
376 | # Fody - auto-generated XML schema
377 | FodyWeavers.xsd
378 |
379 | # VS Code files for those working on multiple tools
380 | .vscode/*
381 | !.vscode/settings.json
382 | !.vscode/tasks.json
383 | !.vscode/launch.json
384 | !.vscode/extensions.json
385 | *.code-workspace
386 |
387 | # Local History for Visual Studio Code
388 | .history/
389 |
390 | # Windows Installer files from build outputs
391 | *.cab
392 | *.msi
393 | *.msix
394 | *.msm
395 | *.msp
396 |
397 | # JetBrains Rider
398 | *.sln.iml
--------------------------------------------------------------------------------
/MManager/MManager.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.3.32505.426
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MManager", "MManager\MManager.vcxproj", "{0B1A382E-0DD8-4822-B4DF-E206B62E52BE}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vadlist", "vadlist\vadlist.vcxproj", "{17475489-56C9-4202-BA6F-79C75805E497}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|ARM64 = Debug|ARM64
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|ARM64 = Release|ARM64
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Debug|ARM64.ActiveCfg = Debug|ARM64
21 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Debug|ARM64.Build.0 = Debug|ARM64
22 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Debug|ARM64.Deploy.0 = Debug|ARM64
23 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Debug|x64.ActiveCfg = Debug|x64
24 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Debug|x64.Build.0 = Debug|x64
25 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Debug|x64.Deploy.0 = Debug|x64
26 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Debug|x86.ActiveCfg = Debug|x64
27 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Debug|x86.Build.0 = Debug|x64
28 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Debug|x86.Deploy.0 = Debug|x64
29 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Release|ARM64.ActiveCfg = Release|ARM64
30 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Release|ARM64.Build.0 = Release|ARM64
31 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Release|ARM64.Deploy.0 = Release|ARM64
32 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Release|x64.ActiveCfg = Release|x64
33 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Release|x64.Build.0 = Release|x64
34 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Release|x64.Deploy.0 = Release|x64
35 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Release|x86.ActiveCfg = Release|x64
36 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Release|x86.Build.0 = Release|x64
37 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}.Release|x86.Deploy.0 = Release|x64
38 | {17475489-56C9-4202-BA6F-79C75805E497}.Debug|ARM64.ActiveCfg = Debug|x64
39 | {17475489-56C9-4202-BA6F-79C75805E497}.Debug|ARM64.Build.0 = Debug|x64
40 | {17475489-56C9-4202-BA6F-79C75805E497}.Debug|x64.ActiveCfg = Debug|x64
41 | {17475489-56C9-4202-BA6F-79C75805E497}.Debug|x64.Build.0 = Debug|x64
42 | {17475489-56C9-4202-BA6F-79C75805E497}.Debug|x64.Deploy.0 = Debug|x64
43 | {17475489-56C9-4202-BA6F-79C75805E497}.Debug|x86.ActiveCfg = Debug|Win32
44 | {17475489-56C9-4202-BA6F-79C75805E497}.Debug|x86.Build.0 = Debug|Win32
45 | {17475489-56C9-4202-BA6F-79C75805E497}.Release|ARM64.ActiveCfg = Release|x64
46 | {17475489-56C9-4202-BA6F-79C75805E497}.Release|ARM64.Build.0 = Release|x64
47 | {17475489-56C9-4202-BA6F-79C75805E497}.Release|x64.ActiveCfg = Release|x64
48 | {17475489-56C9-4202-BA6F-79C75805E497}.Release|x64.Build.0 = Release|x64
49 | {17475489-56C9-4202-BA6F-79C75805E497}.Release|x86.ActiveCfg = Release|Win32
50 | {17475489-56C9-4202-BA6F-79C75805E497}.Release|x86.Build.0 = Release|Win32
51 | EndGlobalSection
52 | GlobalSection(SolutionProperties) = preSolution
53 | HideSolutionNode = FALSE
54 | EndGlobalSection
55 | GlobalSection(ExtensibilityGlobals) = postSolution
56 | SolutionGuid = {6CC78C36-84C3-4A75-AD4D-0D6DFBCF2187}
57 | EndGlobalSection
58 | EndGlobal
59 |
--------------------------------------------------------------------------------
/MManager/MManager/MManager.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x64
7 |
8 |
9 | Release
10 | x64
11 |
12 |
13 | Debug
14 | ARM64
15 |
16 |
17 | Release
18 | ARM64
19 |
20 |
21 |
22 | {0B1A382E-0DD8-4822-B4DF-E206B62E52BE}
23 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d}
24 | v4.5
25 | 12.0
26 | Debug
27 | x64
28 | MManager
29 |
30 |
31 |
32 | Windows10
33 | true
34 | WindowsKernelModeDriver10.0
35 | Driver
36 | WDM
37 | false
38 |
39 |
40 | Windows10
41 | false
42 | WindowsKernelModeDriver10.0
43 | Driver
44 | WDM
45 |
46 |
47 | Windows10
48 | true
49 | WindowsKernelModeDriver10.0
50 | Driver
51 | WDM
52 |
53 |
54 | Windows10
55 | false
56 | WindowsKernelModeDriver10.0
57 | Driver
58 | WDM
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | DbgengKernelDebugger
70 |
71 |
72 | DbgengKernelDebugger
73 |
74 |
75 | DbgengKernelDebugger
76 |
77 |
78 | DbgengKernelDebugger
79 |
80 |
81 |
82 | sha256
83 |
84 |
85 | $(DDK_LIB_PATH)wdmsec.lib;%(AdditionalDependencies)
86 |
87 |
88 |
89 |
90 | sha256
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/MManager/MManager/MManager.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/MManager/MManager/main.c:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: main.c
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 |
8 | Abstract:
9 | Device driver entry point.
10 |
11 | ================================================================================================+*/
12 |
13 | #include "mmanager-globals.h"
14 | #include "mmanager-dispatch.h"
15 |
16 | #include "rtl/osversion.h"
17 |
18 | ///
19 | /// Device driver entry point.
20 | ///
21 | /// Pointer to the driver object.
22 | /// Pointer to the registry path, if any.
23 | /// Functions status code.
24 | EXTERN_C NTSTATUS DriverEntry(
25 | _In_ PDRIVER_OBJECT DriverObject,
26 | _In_ PUNICODE_STRING RegistryPath
27 | );
28 |
29 | #ifdef ALLOC_PRAGMA
30 | #pragma alloc_text(PAGE, DriverEntry)
31 | #endif // ALLOC_PRAGMA
32 |
33 | _Use_decl_annotations_
34 | EXTERN_C NTSTATUS DriverEntry(
35 | _In_ PDRIVER_OBJECT DriverObject,
36 | _In_ PUNICODE_STRING RegistryPath
37 | ) {
38 | UNREFERENCED_PARAMETER(RegistryPath);
39 |
40 | MMDebug(("----------------------------------------------------------------\r\n"));
41 | MMDebug(("Kernel Memory MAnager Utility (MManager) \r\n"));
42 | MMDebug(("Version: 1.0 \r\n"));
43 | MMDebug((" \r\n"));
44 | MMDebug(("Tested on: Windows 10 Kernel Version 19041 MP (1 procs) Free x64\r\n"));
45 | MMDebug(("Edition build lab: 19041.1.amd64fre.vb_release.191206-1406 \r\n"));
46 | MMDebug(("----------------------------------------------------------------\r\n"));
47 |
48 | // 1. Check current Windows version
49 | OSVERSIONINFOW SystemInfo = { 0x00 };
50 | ASSERT(NT_SUCCESS(RtlGetVersion(&SystemInfo)));
51 | ASSERT(SystemInfo.dwMajorVersion == WINDOWS_10);
52 | ASSERT(SystemInfo.dwBuildNumber == WINDOWS_10_19044);
53 |
54 | // Initialise stack variables
55 | NTSTATUS Status = STATUS_SUCCESS;
56 | UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(MMANAGER_DEVICE_NAME);
57 | UNICODE_STRING SymbolicName = RTL_CONSTANT_STRING(MMANAGER_SYMBOLIC_LINK_NAME);
58 |
59 | PDEVICE_OBJECT DeviceObject = NULL;
60 | BOOLEAN SymbolicLink = FALSE;
61 |
62 | // Set all the routines
63 | DriverObject->DriverUnload = MmanDriverUnload;
64 | DriverObject->MajorFunction[IRP_MJ_CLOSE] = MmanDriverCreateClose;
65 | DriverObject->MajorFunction[IRP_MJ_CREATE] = MmanDriverCreateClose;
66 | DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MmanDriverDispatch;
67 |
68 | // Register the device driver and symbolic link
69 | do {
70 | // Exclusive - Prevent multiple handles to be open for the device driver.
71 | // SDDLString - Prevent non-admin and non-SYSTEM from interacting with the device driver.
72 | Status = WdmlibIoCreateDeviceSecure(
73 | DriverObject,
74 | 0x00,
75 | &DeviceName,
76 | FILE_DEVICE_UNKNOWN,
77 | 0x00,
78 | TRUE,
79 | &SDDL_DEVOBJ_SYS_ALL_ADM_ALL,
80 | &MMANAGER_CLASS_GUID,
81 | &DeviceObject
82 | );
83 | if (!NT_SUCCESS(Status)) {
84 | MMDebug(("Failed to create device object (0x%08X).\r\n", Status));
85 | break;
86 | }
87 | DeviceObject->Flags |= DO_DIRECT_IO;
88 |
89 | Status = IoCreateSymbolicLink(&SymbolicName, &DeviceName);
90 | if (!NT_SUCCESS(Status)) {
91 | MMDebug(("Failed to symbolic link (0x%08X).\r\n", Status));
92 | break;
93 | }
94 | SymbolicLink = TRUE;
95 | } while (FALSE);
96 |
97 | // Check for errors
98 | if (!NT_SUCCESS(Status)) {
99 | MMDebug(("Roll-back operations.\r\n"));
100 | if (SymbolicLink)
101 | IoDeleteSymbolicLink(&SymbolicName);
102 | if (DeviceObject != NULL)
103 | IoDeleteDevice(DeviceObject);
104 | MMDebug(("----------------------------------------------------------------\r\n"));
105 | return Status;
106 | }
107 |
108 | // Display final information and exit
109 | MMDebug(("Device name : %wZ\r\n", DeviceName));
110 | MMDebug(("Symbolic link name: %wZ\r\n", SymbolicName));
111 | MMDebug(("----------------------------------------------------------------\r\n"));
112 | return Status;
113 | }
--------------------------------------------------------------------------------
/MManager/MManager/mm/vad.c:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: vad.c
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 |
8 | Abstract:
9 | All the routines used to deal with Virtual Address Descriptors (VADs).
10 | APC must be disabled.
11 |
12 | ================================================================================================+*/
13 |
14 | #include "vad.h"
15 |
16 | #ifdef ALLOC_PRAGMA
17 | #pragma alloc_text(PAGE, XMiInitializeVadTable)
18 | #pragma alloc_text(PAGE, XMiUninitializeVadTable)
19 | #pragma alloc_text(PAGE, XMiBuildVadTable)
20 | #pragma alloc_text(PAGE, XMiGetVadNodeAbstractInfo)
21 | #endif // ALLOC_PRAGMA
22 |
23 | _Use_decl_annotations_
24 | EXTERN_C NTSTATUS XMiInitializeVadTable(
25 | _In_ CONST PEPROCESS Process,
26 | _Out_ PXVAD_TABLE XVadTable
27 | ) {
28 | if (Process == NULL)
29 | return STATUS_INVALID_PARAMETER_1;
30 | if (XVadTable == NULL)
31 | return STATUS_INVALID_PARAMETER_2;
32 |
33 | // Ensure current IRQL allow paging.
34 | PAGED_CODE();
35 |
36 | // Allocate required data
37 | XVadTable->Process = (PEPROCESS)Process;
38 | InitializeListHead(&XVadTable->InsertOrderList);
39 |
40 | return STATUS_SUCCESS;
41 | }
42 |
43 | _Use_decl_annotations_
44 | EXTERN_C NTSTATUS XMiUninitializeVadTable(
45 | _In_ PXVAD_TABLE XVadTable
46 | ) {
47 | if (XVadTable == NULL)
48 | return STATUS_INVALID_PARAMETER_1;
49 |
50 | // Ensure current IRQL allow paging.
51 | PAGED_CODE();
52 |
53 | // Check if there is any nodes
54 | if (XVadTable->NumberOfNodes == 0x00)
55 | return STATUS_SUCCESS;
56 |
57 | // Release all entries
58 | while (!IsListEmpty(&XVadTable->InsertOrderList)) {
59 | PLIST_ENTRY Entry = RemoveTailList(&XVadTable->InsertOrderList);
60 | PXVAD_TABLE_ENTRY Vad = CONTAINING_RECORD(Entry, XVAD_TABLE_ENTRY, List);
61 | if (Vad != NULL) {
62 | ExFreePoolWithTag(Vad, XVAD_MM_TAG);
63 | }
64 | }
65 |
66 | RtlZeroMemory(XVadTable, sizeof(XVAD_TABLE));
67 | return STATUS_SUCCESS;
68 | }
69 |
70 | _Use_decl_annotations_
71 | EXTERN_C PXVAD_TABLE_ENTRY XMiBuildVadTable(
72 | _In_ PXVAD_TABLE XVadTree,
73 | _In_opt_ PMMVAD VadNode,
74 | _In_opt_ PXVAD_TABLE_ENTRY Parent,
75 | _In_ ULONG Level
76 | ) {
77 | // Increase max level
78 | if (Level > XVadTree->MaximumLevel)
79 | XVadTree->MaximumLevel = Level;
80 |
81 | // Allocate memory to store the new node
82 | PXVAD_TABLE_ENTRY NewVadEntry = ExAllocatePool2(POOL_FLAG_PAGED, sizeof(XVAD_TABLE_ENTRY), XVAD_MM_TAG);
83 | if (NewVadEntry == NULL)
84 | return NULL;
85 | NewVadEntry->Level = Level;
86 | XVadTree->NumberOfNodes++;
87 |
88 | // Get VadRoot if VadNode is NULL
89 | if (VadNode == NULL)
90 | VadNode = XMM_GET_PROCESS_VAD_ROOT(XVadTree->Process);
91 |
92 | // Get the information and insert into the list
93 | XMiGetVadNodeAbstractInfo(VadNode, NewVadEntry);
94 | InsertTailList(&XVadTree->InsertOrderList, &NewVadEntry->List);
95 |
96 | // Handle the root node
97 | if (Parent == NULL) {
98 | NewVadEntry->Parent = (struct XVAD_TABLE_ENTRY*)NewVadEntry;
99 | XVadTree->Root = NewVadEntry;
100 | }
101 | else
102 | NewVadEntry->Parent = (struct XVAD_TABLE_ENTRY*)Parent;
103 |
104 | // Get left and right nodes
105 | PMMVAD Left = (PMMVAD)VadNode->Core.VadNode.Left;
106 | PMMVAD Right = (PMMVAD)VadNode->Core.VadNode.Right;
107 |
108 | // Parse left and right nodes
109 | if (Left != NULL) {
110 | NewVadEntry->Left = (struct XVAD_TABLE_ENTRY*)XMiBuildVadTable(
111 | XVadTree,
112 | Left,
113 | NewVadEntry,
114 | Level + 1
115 | );
116 | }
117 | if (Right != NULL) {
118 | NewVadEntry->Right = (struct XVAD_TABLE_ENTRY*)XMiBuildVadTable(
119 | XVadTree,
120 | Right,
121 | NewVadEntry,
122 | Level + 1
123 | );
124 | }
125 | return NewVadEntry;
126 | }
127 |
128 | _Use_decl_annotations_
129 | EXTERN_C VOID XMiGetVadNodeAbstractInfo(
130 | _In_ PMMVAD VadNode,
131 | _In_ PXVAD_TABLE_ENTRY TableEntry
132 | ) {
133 | if (VadNode == NULL)
134 | return;
135 | if (TableEntry == NULL)
136 | return;
137 |
138 | // Ensure current IRQL allow paging.
139 | PAGED_CODE();
140 |
141 | // Easy store of the VAD Node
142 | TableEntry->VadNode = VadNode;
143 |
144 | // Calculate Virtual Page Number (VPN)
145 | TableEntry->StartingVpn = VadNode->Core.StartingVpn;
146 | TableEntry->EndingVpn = VadNode->Core.EndingVpn;
147 | if (VadNode->Core.StartingVpnHigh)
148 | TableEntry->StartingVpn |= ((ULONG64)VadNode->Core.StartingVpnHigh) << 32;
149 | if (VadNode->Core.EndingVpnHigh)
150 | TableEntry->EndingVpn |= ((ULONG64)VadNode->Core.EndingVpnHigh) << 32;
151 |
152 | // Get all flags
153 | TableEntry->VadFlags = VadNode->Core.u.VadFlags;
154 | TableEntry->VadFlags1 = VadNode->Core.u1.VadFlags1;
155 | TableEntry->VadFlags2 = VadNode->u2.VadFlags2;
156 |
157 | // Check for a control area. Applicable only in case this is mapped memory.
158 | if (!TableEntry->VadFlags.PrivateMemory) {
159 | if (VadNode->Subsection != NULL) {
160 | TableEntry->ControlArea = VadNode->Subsection->ControlArea;
161 |
162 | // Now check for the FileObject if any
163 | if (TableEntry->ControlArea->FilePointer.Value != 0x00) {
164 | TableEntry->FileObject = (PFILE_OBJECT)(TableEntry->ControlArea->FilePointer.Value & 0xFFFFFFFFFFFFFFF0);
165 | TableEntry->Name = &TableEntry->FileObject->FileName;
166 | }
167 | }
168 | }
169 |
170 | // Get commit charge
171 | TableEntry->CommitCharge = TableEntry->VadFlags1.CommitCharge;
172 | if (VadNode->Core.CommitChargeHigh)
173 | TableEntry->CommitCharge |= ((ULONG64)VadNode->Core.CommitChargeHigh) << 31;
174 | }
175 |
--------------------------------------------------------------------------------
/MManager/MManager/mm/vad.h:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: vad.h
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 |
8 | Abstract:
9 | All the routines used to deal with Virtual Address Descriptors (VADs).
10 | APC must be disabled.
11 |
12 | ================================================================================================+*/
13 |
14 | #ifndef __X_VAD_H_GUARD__
15 | #define __X_VAD_H_GUARD__
16 |
17 | #include "mmtypes.h"
18 |
19 | // XVAD Memory Pool Tag -- XVad
20 | #define XVAD_MM_TAG (ULONG)0x64615658
21 |
22 | // This is not a reliable way to get the VadRoot but could not find any better for the moment.
23 | #define XMM_GET_PROCESS_VAD_ROOT(ps) (PMMVAD) *(PULONG64)((PUCHAR)ps + 0x7d8)
24 |
25 | ///
26 | /// Virtual Address Descriptor (VAD) abstraction structure.
27 | ///
28 | typedef struct _XVAD_TABLE_ENTRY {
29 | LIST_ENTRY List;
30 | struct XVAD_TABLE_ENTRY* Parent;
31 | struct XVAD_TABLE_ENTRY* Left;
32 | struct XVAD_TABLE_ENTRY* Right;
33 |
34 | // Address of the VAD Node in kernel pool.
35 | union {
36 | PMMVAD VadNode;
37 | PVOID Address;
38 | };
39 |
40 | PCONTROL_AREA ControlArea; // Pointer to the CONTROL_AREA if mapped memory
41 | PFILE_OBJECT FileObject; // Pointer to the FILE_OBJECT if mapped memory.
42 | ULONG64 StartingVpn; // Start of Virtual Page Number(VPN).
43 | ULONG64 EndingVpn; // Start of Virtual Page Number (VPN).
44 | ULONG64 CommitCharge;
45 | ULONG Level; // Depth level in the AFL tree.
46 |
47 | // First set of flags.
48 | union {
49 | ULONG LongVadFlags;
50 | MMVAD_FLAGS VadFlags;
51 | MM_PRIVATE_VAD_FLAGS PrivateVadFlags;
52 | MM_GRAPHICS_VAD_FLAGS GraphicsVadFlags;
53 | MM_SHARED_VAD_FLAGS SharedVadFlags;
54 | };
55 |
56 | // Second set of flags.
57 | union {
58 | MMVAD_FLAGS1 VadFlags1;
59 | ULONG LongVadFlags1;
60 | };
61 |
62 | // Third set of flags.
63 | union {
64 | MMVAD_FLAGS2 VadFlags2;
65 | ULONG LongVadFlags2;
66 | };
67 |
68 | // Name of the mapped file, if any.
69 | PUNICODE_STRING Name;
70 | } XVAD_TABLE_ENTRY, * PXVAD_TABLE_ENTRY;
71 |
72 | ///
73 | /// Global structure used to collect additional information about Virtual Address Descriptors (VADs).
74 | ///
75 | typedef struct _XVAD_TABLE {
76 | ULONG MaximumLevel; // Deepest level
77 | ULONG NumberOfNodes; // Total number of nodes
78 | ULONG64 TotalPrivateCommit; // Total private memory
79 | ULONG64 TotalSharedCommit; // Total shared memory
80 |
81 | PEPROCESS Process; // Process linked to the VAD
82 |
83 | LIST_ENTRY InsertOrderList; // Order in which all nodes have been loaded
84 | PXVAD_TABLE_ENTRY Root; // First entry of the table
85 | } XVAD_TABLE, * PXVAD_TABLE;
86 |
87 |
88 | _IRQL_requires_max_(APC_LEVEL)
89 | EXTERN_C NTSTATUS XMiInitializeVadTable(
90 | _In_ CONST PEPROCESS Process,
91 | _Out_ PXVAD_TABLE XVadTable
92 | );
93 |
94 |
95 | _IRQL_requires_max_(APC_LEVEL)
96 | EXTERN_C NTSTATUS XMiUninitializeVadTable(
97 | _In_ PXVAD_TABLE XVadTree
98 | );
99 |
100 |
101 | _IRQL_requires_max_(APC_LEVEL)
102 | EXTERN_C PXVAD_TABLE_ENTRY XMiBuildVadTable(
103 | _In_ PXVAD_TABLE XVadTree,
104 | _In_opt_ PMMVAD VadNode,
105 | _In_opt_ PXVAD_TABLE_ENTRY Parent,
106 | _In_ ULONG Level
107 | );
108 |
109 | ///
110 | /// Extract all the information from a Virtual Address Descriptor (VAD) node.
111 | ///
112 | /// Most of the logic taken from C:\Program Files\WindowsApps\Microsoft.WinDbg_\amd64\winxp\kdexts.dll
113 | /// Interesting functions to RE from this module are:
114 | /// - vad
115 | /// - PrintVad
116 | ///
117 | /// Pointer to an internal VAD structure.
118 | /// Pointer to global VAD table.
119 | EXTERN_C VOID XMiGetVadNodeAbstractInfo(
120 | _In_ PMMVAD VadNode,
121 | _In_ PXVAD_TABLE_ENTRY TableEntry
122 | );
123 |
124 | #endif // !__X_VAD_H_GUARD__
125 |
--------------------------------------------------------------------------------
/MManager/MManager/mmanager-dispatch.c:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: mmanager-dispatch.c
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 |
8 | Abstract:
9 | This file contains all global definition and information used by the kernel driver.
10 |
11 | ================================================================================================+*/
12 |
13 | #include "mmanager-dispatch.h"
14 | #include "mmanager-routines.h"
15 |
16 | #ifdef ALLOC_PRAGMA
17 | #pragma alloc_text(PAGE, MmanDriverUnload)
18 | #pragma alloc_text(PAGE, MmanDriverCreateClose)
19 | #pragma alloc_text(PAGE, MmanDriverDispatch)
20 | #endif // ALLOC_PRAGMA
21 |
22 | _Use_decl_annotations_
23 | EXTERN_C VOID MmanDriverUnload(
24 | _In_ PDRIVER_OBJECT DriverObject
25 | ) {
26 | MMDebug(("----------------------------------------------------------------\r\n\r\n"));
27 |
28 | // Delete the symbolic link and the device object
29 | UNICODE_STRING SymbolicName = RTL_CONSTANT_STRING(MMANAGER_SYMBOLIC_LINK_NAME);
30 | IoDeleteSymbolicLink(&SymbolicName);
31 | IoDeleteDevice(DriverObject->DeviceObject);
32 | }
33 |
34 | _Use_decl_annotations_
35 | EXTERN_C NTSTATUS MmanDriverCreateClose(
36 | _Inout_ PDEVICE_OBJECT DeviceObject,
37 | _Inout_ PIRP Irp
38 | ) {
39 | UNREFERENCED_PARAMETER(DeviceObject);
40 | MMDebug(("MmanDriverCreateClose: 0x%0x8\r\n", HandleToUlong(PsGetCurrentProcessId())));
41 |
42 | NTSTATUS Status = STATUS_SUCCESS;
43 | Irp->IoStatus.Status = Status;
44 | Irp->IoStatus.Information = 0x00;
45 |
46 | IofCompleteRequest(Irp, IO_NO_INCREMENT);
47 | return STATUS_SUCCESS;
48 | }
49 |
50 | _Use_decl_annotations_
51 | EXTERN_C NTSTATUS MmanDriverDispatch(
52 | _Inout_ PDEVICE_OBJECT DeviceObject,
53 | _Inout_ PIRP Irp
54 | ) {
55 | UNREFERENCED_PARAMETER(DeviceObject);
56 |
57 | // Get the IRP Stack
58 | PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
59 |
60 | ULONG_PTR Information = 0x00;
61 | NTSTATUS Status = STATUS_SUCCESS;
62 |
63 | switch (Stack->Parameters.DeviceIoControl.IoControlCode) {
64 | case IOCTL_MMANAGER_FIND_PROCESS_VADS:
65 | Status = MmanIoctlFindProcessVads(Irp, Stack);
66 | if (NT_SUCCESS(Status))
67 | Information = sizeof(ULONG64);
68 | break;
69 | case IOCTL_MMANAGER_GET_PROCESS_VADS:
70 | Status = MmanIoctlGetProcessVads(Irp, Stack, &Information);
71 | if (!NT_SUCCESS(Status))
72 | Information = 0x00;
73 | break;
74 | default:
75 | MMDebug(("Invalid IOCTL: 0x%08x\r\n", Stack->Parameters.DeviceIoControl.IoControlCode));
76 | Status = STATUS_INVALID_DEVICE_REQUEST;
77 | break;
78 | }
79 |
80 | // Complete request
81 | Irp->IoStatus.Status = Status;
82 | Irp->IoStatus.Information = Information;
83 | IofCompleteRequest(Irp, IO_NO_INCREMENT);
84 | return Status;
85 | }
--------------------------------------------------------------------------------
/MManager/MManager/mmanager-dispatch.h:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: mmanager-dispatch.h
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 |
8 | Abstract:
9 | This file contains all global definition and information used by the kernel driver.
10 |
11 | ================================================================================================+*/
12 |
13 | #ifndef __MMANAGER_DISPATCH_H_GUARD__
14 | #define __MMANAGER_DISPATCH_H_GUARD__
15 |
16 | #include "mmanager-globals.h"
17 |
18 | ///
19 | /// The Unload routine performs any operations that are necessary before the system unloads the driver.
20 | ///
21 | /// Caller-supplied pointer to a DRIVER_OBJECT structure. This is the driver's driver object.
22 | _IRQL_requires_max_(PASSIVE_LEVEL)
23 | EXTERN_C VOID
24 | MmanDriverUnload(
25 | _In_ PDRIVER_OBJECT DriverObject
26 | );
27 |
28 | ///
29 | /// The callback routine for IRP_MJ_CREATE and IRP_MJ_CLOSE.
30 | ///
31 | /// Caller-supplied pointer to a DEVICE_OBJECT structure.This is the device object for the target device, previously created by the driver's AddDevice routine.
32 | /// Caller-supplied pointer to an IRP structure that describes the requested I/O operation.
33 | /// If the routine succeeds, it must return STATUS_SUCCESS. Otherwise, it must return one of the error status values defined in Ntstatus.h.
34 | __drv_dispatchType(IRP_MJ_CREATE)
35 | __drv_dispatchType(IRP_MJ_CLOSE)
36 | _IRQL_requires_max_(PASSIVE_LEVEL)
37 | EXTERN_C NTSTATUS
38 | MmanDriverCreateClose(
39 | _Inout_ PDEVICE_OBJECT DeviceObject,
40 | _Inout_ PIRP Irp
41 | );
42 |
43 | ///
44 | /// The callback routine services various IRPs. In this case handle user-mode IOCTL. For a list of function codes, see mmanager-globals.h.
45 | ///
46 | /// Caller-supplied pointer to a DEVICE_OBJECT structure.This is the device object for the target device, previously created by the driver's AddDevice routine.
47 | /// Caller-supplied pointer to an IRP structure that describes the requested I/O operation.
48 | /// If the routine succeeds, it must return STATUS_SUCCESS. Otherwise, it must return one of the error status values defined in Ntstatus.h.
49 | __drv_dispatchType(IRP_MJ_DEVICE_CONTROL)
50 | _IRQL_requires_max_(DISPATCH_LEVEL)
51 | EXTERN_C NTSTATUS
52 | MmanDriverDispatch(
53 | _Inout_ PDEVICE_OBJECT DeviceObject,
54 | _Inout_ PIRP Irp
55 | );
56 |
57 | #endif // !__MMANAGER_DISPATCH_H_GUARD__
58 |
--------------------------------------------------------------------------------
/MManager/MManager/mmanager-globals.h:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: mmanager-globals.h
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 |
8 | Abstract:
9 | This file contains all global definition and information used by the kernel driver.
10 |
11 | ================================================================================================+*/
12 |
13 | #ifndef __MMANAGER_GLOBALS_H_GUARD__
14 | #define __MMANAGER_GLOBALS_H_GUARD__
15 |
16 | #include
17 | #include
18 |
19 | // Include security routines for driver
20 | #include
21 | #pragma comment(lib, "wdmsec.lib")
22 |
23 | // MManager Device driver Memory Pool Tag - "MMan"
24 | #define MMANAGER_MM_TAG (ULONG)0x6e614d4d
25 |
26 | // MManager Device driver name
27 | #define MMANAGER_DEVICE_NAME L"\\Device\\MManager"
28 |
29 | // MManager Device driver symbolic name
30 | #define MMANAGER_SYMBOLIC_LINK_NAME L"\\??\\MManager"
31 |
32 | // MManager Debug tag
33 | #define MMANAGER_DEBUG_TAG "[MManager] "
34 |
35 | // MManager wrapper around KdPrint for less bloated code.
36 | #define MMDebug(_x_) KdPrint((MMANAGER_DEBUG_TAG)); KdPrint(_x_)
37 |
38 | // MManager class GUID - {F7BD4AF3-BA07-4EB4-BD62-4BBF596D5C23}
39 | // {5C368CE1-3DB6-43EE-8EA8-9338B4803FAE}
40 | static CONST GUID MMANAGER_CLASS_GUID = {
41 | 0x5c368ce1,
42 | 0x3db6,
43 | 0x43ee,
44 | { 0x8e, 0xa8, 0x93, 0x38, 0xb4, 0x80, 0x3f, 0xae }
45 | };
46 |
47 | // Query the VAD tree of a process
48 | #define IOCTL_MMANAGER_FIND_PROCESS_VADS CTL_CODE( \
49 | 0x8000, /* DeviceType */\
50 | 0x800, /* Function */\
51 | METHOD_OUT_DIRECT, /* Method */\
52 | FILE_ANY_ACCESS /* Access */\
53 | )
54 |
55 | // Query the VAD tree of a process
56 | #define IOCTL_MMANAGER_GET_PROCESS_VADS CTL_CODE( \
57 | 0x8000, /* DeviceType */\
58 | 0x801, /* Function */\
59 | METHOD_OUT_DIRECT, /* Method */\
60 | FILE_ANY_ACCESS /* Access */\
61 | )
62 |
63 | #endif // !__MMANAGER_GLOBALS_H_GUARD__
64 |
--------------------------------------------------------------------------------
/MManager/MManager/mmanager-routines.c:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: mmanager-routines.c
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 |
8 | Abstract:
9 | Handle User-Mode IOCTL requests.
10 |
11 | ================================================================================================+*/
12 |
13 | #include "mmanager-routines.h"
14 |
15 | #ifdef ALLOC_PRAGMA
16 | #pragma alloc_text(PAGE, MmanIoctlFindProcessVads)
17 | #pragma alloc_text(PAGE, MmanIoctlGetProcessVads)
18 |
19 | #pragma alloc_text(PAGE, MmanpCalculateStructureSize)
20 | #endif // ALLOC_PRAGMA
21 |
22 | // Global variable to store the size of the UM structure.
23 | ULONG64 VadTableSize = 0x00;
24 |
25 | // Global variable to build the UM structure.
26 | XVAD_TABLE VadTable = {0x00 };
27 |
28 |
29 | _Use_decl_annotations_
30 | EXTERN_C NTSTATUS MmanIoctlFindProcessVads(
31 | _In_ PIRP Irp,
32 | _In_ PIO_STACK_LOCATION Stack
33 | ) {
34 | // Ensure current IRQL allow paging.
35 | PAGED_CODE();
36 |
37 | // Check for the input length
38 | if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
39 | return STATUS_BUFFER_TOO_SMALL;
40 |
41 | // Check for output length
42 | if (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(ULONG64)) {
43 | MMDebug(("MDL too small.\r\n"));
44 | return STATUS_INSUFFICIENT_RESOURCES;
45 | }
46 | PVOID UserBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
47 | if (UserBuffer == NULL) {
48 | MMDebug(("Unable to get MDL.\r\n"));
49 | return STATUS_INSUFFICIENT_RESOURCES;
50 | }
51 |
52 | // Filter out the system "process"
53 | ULONG ProcessId = 0x00;
54 | __try {
55 | RtlCopyMemory(&ProcessId, Irp->AssociatedIrp.SystemBuffer, sizeof(ULONG));
56 | }
57 | __except (EXCEPTION_EXECUTE_HANDLER) {
58 | MMDebug(("Unreadable user-mode buffer.\r\n"));
59 | return STATUS_ACCESS_VIOLATION;
60 | }
61 | if (ProcessId <= 0x04 || (ProcessId % 0x04) != 0x00) {
62 | MMDebug(("Invalid process ID supplied.\r\n"));
63 | return STATUS_INVALID_PARAMETER;
64 | }
65 | MMDebug(("Process ID : 0x%x\r\n", ProcessId));
66 |
67 | // Forward declaration of stack variables
68 | NTSTATUS Status = STATUS_SUCCESS;
69 | BOOLEAN ProcessAttached = FALSE;
70 | KAPC_STATE ProcessApcState = { 0x00 };
71 |
72 | // Get the EPROCESS structure based on the requested ID
73 | PEPROCESS Process = NULL;
74 | Status = PsLookupProcessByProcessId(ULongToHandle(ProcessId), &Process);
75 | if (!NT_SUCCESS(Status)) {
76 | MMDebug(("Unable to get the _EPROCESS structure for the given PID (0x%08x).\r\n", Status));
77 | goto exit;
78 | }
79 |
80 | // Increase reference counter to prevent process from terminating while
81 | // parsing the VAD tree
82 | ObReferenceObject(Process);
83 | KeStackAttachProcess(Process, &ProcessApcState);
84 | ProcessAttached = TRUE;
85 | MMDebug(("_EPROCESS address: 0x%p\r\n", Process));
86 |
87 | // Initialize internal VAD table
88 | Status = XMiInitializeVadTable(Process, &VadTable);
89 | if (!NT_SUCCESS(Status)) {
90 | MMDebug(("Failed to initialize the VAD table (0x%08x).\r\n", Status));
91 | goto exit;
92 | }
93 |
94 | // Get the whole table
95 | VadTable.Process = Process;
96 | XMiBuildVadTable(&VadTable, NULL, NULL, 0x00);
97 |
98 | // Release the proces object
99 | KeUnstackDetachProcess(&ProcessApcState);
100 | ObDereferenceObject(Process);
101 | ProcessAttached = FALSE;
102 |
103 | // Calculate the user-mode size of the data
104 | VadTableSize = MmanpCalculateStructureSize();
105 |
106 | // Return the data to the user-mode caller
107 | __try {
108 | RtlCopyMemory(UserBuffer, &VadTableSize, sizeof(ULONG64));
109 | return STATUS_SUCCESS;
110 | }
111 | __except (EXCEPTION_EXECUTE_HANDLER) {
112 | MMDebug(("Unable to return buffer size to caller.\r\n"));
113 | Status = STATUS_INVALID_PARAMETER;
114 | }
115 |
116 | // Cleanup and dereference the object
117 | exit:
118 | if (ProcessAttached)
119 | KeUnstackDetachProcess(&ProcessApcState);
120 | if (Process != NULL)
121 | ObDereferenceObject(Process);
122 | if (VadTable.Process == NULL) {
123 | VadTableSize = 0x00;
124 | XMiUninitializeVadTable(&VadTable);
125 | }
126 | return Status;
127 | }
128 |
129 |
130 | _Use_decl_annotations_
131 | EXTERN_C NTSTATUS MmanIoctlGetProcessVads(
132 | _In_ PIRP Irp,
133 | _In_ PIO_STACK_LOCATION Stack,
134 | _Out_ ULONG_PTR* BufferOutSize
135 | ) {
136 | UNREFERENCED_PARAMETER(Stack);
137 |
138 | // Ensure current IRQL allow paging.
139 | PAGED_CODE();
140 |
141 | NTSTATUS Status = STATUS_SUCCESS;
142 | PVOID UserBuffer = NULL;
143 | ULONG64 UmAddress = 0x00;
144 |
145 | // Check the input buffer
146 | if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG64)) {
147 | MMDebug(("Buffer too small.\r\n"));
148 | Status = STATUS_BUFFER_TOO_SMALL;
149 | goto exit;
150 | }
151 | __try {
152 | RtlCopyMemory(&UmAddress, Irp->AssociatedIrp.SystemBuffer, sizeof(ULONG64));
153 | }
154 | __except (EXCEPTION_EXECUTE_HANDLER) {
155 | MMDebug(("Unreadable user-mode buffer.\r\n"));
156 | Status = STATUS_ACCESS_VIOLATION;
157 | goto exit;
158 | }
159 |
160 | // Check the size of the output buffer
161 | if (MmGetMdlByteCount(Irp->MdlAddress) < VadTableSize) {
162 | MMDebug(("MDL too small.\r\n"));
163 | Status = STATUS_INSUFFICIENT_RESOURCES;
164 | goto exit;
165 | }
166 | UserBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
167 | if (UserBuffer == NULL) {
168 | MMDebug(("Unable to get MDL.\r\n"));
169 | Status = STATUS_INSUFFICIENT_RESOURCES;
170 | goto exit;
171 | }
172 |
173 | // Get the header
174 | PMMANAGER_VADLIST_HEADER Header = UserBuffer;
175 | Header->Size = sizeof(MMANAGER_VADLIST_HEADER);
176 | Header->MaximumLevel = VadTable.MaximumLevel;
177 | Header->NumberOfNodes = VadTable.NumberOfNodes;
178 | Header->TotalPrivateCommit = VadTable.TotalPrivateCommit;
179 | Header->TotalSharedCommit = VadTable.TotalSharedCommit;
180 | Header->Eprocess = VadTable.Process;
181 |
182 | // Get address of first entry
183 | PVOID EntryPoint = (PUCHAR)Header + Header->Size;
184 | Header->First = XLATE_TO_UM_ADDRESS(UmAddress, Header, EntryPoint);
185 |
186 | PMMANAGER_VADLIST_ENTRY Blink = NULL;
187 |
188 | // Parse all entries
189 | PLIST_ENTRY ListEntry = VadTable.InsertOrderList.Flink;
190 | do {
191 | PXVAD_TABLE_ENTRY TableEntry = CONTAINING_RECORD(ListEntry, XVAD_TABLE_ENTRY, List);
192 | if (TableEntry == NULL)
193 | break;
194 |
195 | // New entry in output memory
196 | PMMANAGER_VADLIST_ENTRY OutEntry = EntryPoint;
197 | OutEntry->List.Blink = XLATE_TO_UM_ADDRESS(UmAddress, Header, Blink);
198 |
199 | if (OutEntry == Header->First)
200 | OutEntry->List.Blink = NULL;
201 |
202 | OutEntry->VadAddress = TableEntry->Address;
203 | OutEntry->Level = TableEntry->Level;
204 | OutEntry->VpnStarting = TableEntry->StartingVpn;
205 | OutEntry->VpnEnding = TableEntry->EndingVpn;
206 | OutEntry->CommitCharge = TableEntry->CommitCharge;
207 | OutEntry->LongVadFlags = TableEntry->LongVadFlags;
208 | OutEntry->LongVadFlags1 = TableEntry->LongVadFlags1;
209 | OutEntry->LongVadFlags2 = TableEntry->LongVadFlags2;
210 |
211 | if (TableEntry->Name != NULL) {
212 | OutEntry->FileNameSize = TableEntry->Name->Length;
213 | RtlCopyMemory(OutEntry->FileName, TableEntry->Name->Buffer, OutEntry->FileNameSize);
214 | }
215 | else if (TableEntry->ControlArea != NULL) {
216 | OutEntry->CommitPageCount = TableEntry->ControlArea->u3.CommittedPageCount;
217 | }
218 |
219 | OutEntry->Size = sizeof(MMANAGER_VADLIST_ENTRY) + OutEntry->FileNameSize;
220 | Header->Size += OutEntry->Size;
221 |
222 | // Check for end of the parsing
223 | if (ListEntry->Flink == &VadTable.InsertOrderList) {
224 | OutEntry->List.Flink = NULL;
225 | break;
226 | }
227 |
228 | // Move to next entry
229 | EntryPoint = (PUCHAR)EntryPoint + OutEntry->Size;
230 | OutEntry->List.Flink = XLATE_TO_UM_ADDRESS(UmAddress, Header, EntryPoint);
231 |
232 | Blink = OutEntry;
233 | ListEntry = ListEntry->Flink;
234 | } while (TRUE);
235 |
236 | // Set last data
237 | Header->Last = XLATE_TO_UM_ADDRESS(UmAddress, Header, EntryPoint);;
238 | *BufferOutSize = Header->Size;
239 | exit:
240 | // Release memory
241 | if (VadTableSize != 0x00) {
242 | XMiUninitializeVadTable(&VadTable);
243 | VadTableSize = 0x00;
244 | }
245 | return Status;
246 | }
247 |
248 |
249 | _Use_decl_annotations_
250 | EXTERN_C ULONG64 MmanpCalculateStructureSize(
251 | VOID
252 | ) {
253 | if (VadTable.Process == NULL)
254 | return 0x00;
255 |
256 | // Ensure current IRQL allow paging.
257 | PAGED_CODE();
258 |
259 | ULONG64 TotalSize = sizeof(MMANAGER_VADLIST_HEADER);
260 |
261 | // Parse all entries
262 | PLIST_ENTRY Entry = VadTable.InsertOrderList.Flink;
263 | do {
264 | PXVAD_TABLE_ENTRY TableEntry = CONTAINING_RECORD(Entry, XVAD_TABLE_ENTRY, List);
265 | if (TableEntry == NULL)
266 | break;
267 |
268 | TotalSize += sizeof(MMANAGER_VADLIST_ENTRY);
269 | if (TableEntry->Name != NULL)
270 | TotalSize += TableEntry->Name->Length + sizeof(WCHAR);
271 |
272 | // Next entry
273 | if (Entry->Flink == &VadTable.InsertOrderList)
274 | break;
275 | Entry = Entry->Flink;
276 | } while (TRUE);
277 |
278 | // Return the aligned memory.
279 | while ((TotalSize % PAGE_SIZE) != 0x00)
280 | TotalSize++;
281 | return TotalSize;
282 | }
--------------------------------------------------------------------------------
/MManager/MManager/mmanager-routines.h:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: mmanager-routines.h
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 |
8 | Abstract:
9 | Handle User-Mode IOCTL requests.
10 |
11 | ================================================================================================+*/
12 |
13 | #ifndef __MMANAGER_H_GUARD__
14 | #define __MMANAGER_H_GUARD__
15 |
16 | #include "mmanager-globals.h"
17 | #include "mm/vad.h"
18 |
19 | #define XLATE_TO_UM_ADDRESS(UM, KM, Address) \
20 | (PVOID)(((PUCHAR)UM) + ((PUCHAR)Address - ((PUCHAR)KM)))
21 |
22 | typedef struct _MMANAGER_VADLIST_ENTRY {
23 | struct {
24 | struct _MMANAGER_VADLIST_ENTRY* Flink;
25 | struct _MMANAGER_VADLIST_ENTRY* Blink;
26 | } List;
27 |
28 | ULONG64 Size; // Size of the entry (structure + PWCHAR if filename)
29 |
30 | PVOID VadAddress; // Address of the VAD node
31 | ULONG Level; // Node depth level
32 | ULONG64 VpnStarting; // Start of Virtual Page Number(VPN).
33 | ULONG64 VpnEnding; // Start of Virtual Page Number (VPN).
34 | ULONG64 CommitCharge; // Number of bytes commit
35 | ULONG64 CommitPageCount; // Number of pages commit
36 |
37 | // First set of flags.
38 | union {
39 | ULONG LongVadFlags;
40 | MMVAD_FLAGS VadFlags;
41 | MM_PRIVATE_VAD_FLAGS PrivateVadFlags;
42 | MM_GRAPHICS_VAD_FLAGS GraphicsVadFlags;
43 | MM_SHARED_VAD_FLAGS SharedVadFlags;
44 | };
45 | // Second set of flags.
46 | union {
47 | ULONG LongVadFlags1;
48 | MMVAD_FLAGS1 VadFlags1;
49 | };
50 | // Third set of flags.
51 | union {
52 | ULONG LongVadFlags2;
53 | MMVAD_FLAGS2 VadFlags2;
54 | };
55 |
56 | ULONG FileNameSize; // Size of the filename
57 | WCHAR FileName[ANYSIZE_ARRAY]; // Pointer to the filename
58 | } MMANAGER_VADLIST_ENTRY, * PMMANAGER_VADLIST_ENTRY;
59 |
60 |
61 | typedef struct _MMANAGER_VADLIST_HEADER {
62 | ULONG64 Size; // Size of the data (header + all entries)
63 | ULONG MaximumLevel; // Deepest level
64 | ULONG NumberOfNodes; // Total number of nodes
65 | ULONG64 TotalPrivateCommit; // Total private memory
66 | ULONG64 TotalSharedCommit; // Total shared memory
67 | PVOID Eprocess; //
68 |
69 | PMMANAGER_VADLIST_ENTRY First;
70 | PMMANAGER_VADLIST_ENTRY Last;
71 | } MMANAGER_VADLIST_HEADER, * PMMANAGER_VADLIST_HEADER;
72 |
73 |
74 | // Global variable to store the size of the UM structure.
75 | extern ULONG64 VadTableSize;
76 |
77 | // Global variable to build the UM structure.
78 | extern XVAD_TABLE VadTable;
79 |
80 |
81 | _IRQL_requires_max_(DISPATCH_LEVEL)
82 | EXTERN_C NTSTATUS MmanIoctlFindProcessVads(
83 | _In_ PIRP Irp,
84 | _In_ PIO_STACK_LOCATION Stack
85 | );
86 |
87 |
88 | _IRQL_requires_max_(DISPATCH_LEVEL)
89 | EXTERN_C NTSTATUS MmanIoctlGetProcessVads(
90 | _In_ PIRP Irp,
91 | _In_ PIO_STACK_LOCATION Stack,
92 | _Out_ ULONG_PTR* BufferOutSize
93 | );
94 |
95 |
96 | _IRQL_requires_max_(DISPATCH_LEVEL)
97 | EXTERN_C ULONG64 MmanpCalculateStructureSize(
98 | VOID
99 | );
100 |
101 | #endif // !__MMANAGER_H_GUARD__
102 |
103 |
--------------------------------------------------------------------------------
/MManager/MManager/rtl/osversion.h:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: osversion.h
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 |
8 | Abstract:
9 | Windows operating system versions runtime library.
10 |
11 | ================================================================================================+*/
12 |
13 | #ifndef __X_RTL_OSVERSION_H_GUARD__
14 | #define __X_RTL_OSVERSION_H_GUARD__
15 |
16 | // OS Versions
17 | #define WINDOWS_10 (ULONG)0x0000000A
18 |
19 | // Build versions
20 | #define WINDOWS_10_19044 (ULONG)0x00004A64
21 | #define WINDOWS_10_22000 (ULONG)0x000055F0
22 |
23 | #endif // !__X_RTL_OSVERSION_H_GUARD__
24 |
--------------------------------------------------------------------------------
/MManager/vadlist/main.cpp:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: main.cpp
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 |
8 | Abstract:
9 | Console application entry point.
10 |
11 | ================================================================================================+*/
12 |
13 | #include
14 | #include
15 | #include
16 |
17 | #include "mmanager.h"
18 |
19 | INT32 main(
20 | _In_ int argc,
21 | _In_ const char* argv[]
22 | ) {
23 | // Banner
24 | wprintf(L"================================================================================================\r\n");
25 | wprintf(L"Module Name: Virtual Address Descriptor List (vadlist) \r\n");
26 | wprintf(L"Author : Paul L. (@am0nsec) \r\n");
27 | wprintf(L"Origin : https://github.com/am0nsec/wkpe/ \r\n\r\n");
28 | wprintf(L"Tested OS : Windows 10 (20h2) - 19044.1706 \r\n");
29 | wprintf(L"================================================================================================\r\n\r\n");
30 |
31 | // Check for parameters
32 | if (argc < 0x02) {
33 | printf("Usage: vadlist.exe \r\n\r\n");
34 | return EXIT_FAILURE;
35 | }
36 |
37 | // Check for the PID provided
38 | ULONG ProcessId = atoi(argv[0x01]);;
39 | if (ProcessId <= 0x04 || (ProcessId % 4) != 0x00) {
40 | printf("Invalid process ID supplied. \r\n\r\n");
41 | return EXIT_FAILURE;
42 | }
43 |
44 | // Open handle to the device driver
45 | std::unique_ptr MManager = std::make_unique();
46 | if (!MManager->IsDeviceReady()) {
47 | printf("Failed to open handle to device driver.\r\n\r\n");
48 | return EXIT_FAILURE;
49 | }
50 |
51 | // Get the list of VADs
52 | if (!MManager->FindProcessVads(ProcessId)) {
53 | printf("Failed to retrieve VAD list.\r\n\r\n");
54 | return EXIT_FAILURE;
55 | }
56 | MManager->PrintProcessVads();
57 |
58 | return EXIT_SUCCESS;
59 | }
60 |
--------------------------------------------------------------------------------
/MManager/vadlist/mmanager.cpp:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: mmanager.cpp
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 |
8 | Abstract:
9 | User mode interface to query VAD list of a process.
10 |
11 | ================================================================================================+*/
12 |
13 | #include
14 | #include "mmanager.h"
15 |
16 |
17 | CMManager::CMManager() {
18 | // Open handle to the device driver
19 | this->m_DeviceHandle = ::CreateFileW(
20 | MMANAGER_DEVICE_NAME_UM,
21 | (GENERIC_READ | GENERIC_WRITE),
22 | 0x00,
23 | NULL,
24 | OPEN_EXISTING,
25 | 0x00,
26 | NULL
27 | );
28 |
29 | }
30 |
31 |
32 | CMManager::~CMManager() {
33 | if (this->m_DeviceHandle != INVALID_HANDLE_VALUE) {
34 | CloseHandle(this->m_DeviceHandle);
35 | }
36 | if (this->m_ListHeader != NULL) {
37 | HeapFree(GetProcessHeap(), 0x00, this->m_ListHeader);
38 | }
39 | }
40 |
41 |
42 | _Use_decl_annotations_
43 | BOOLEAN CMManager::IsDeviceReady() {
44 | return this->m_DeviceHandle != INVALID_HANDLE_VALUE;
45 | }
46 |
47 |
48 | _Use_decl_annotations_
49 | BOOLEAN CMManager::FindProcessVads(
50 | _In_ CONST ULONG ProcessId
51 | ) {
52 | if (ProcessId == 0x00)
53 | return FALSE;
54 | if (!this->IsDeviceReady())
55 | return FALSE;
56 |
57 | // Make sure we do not allocate too much memory
58 | if (this->m_ListHeader != NULL)
59 | HeapFree(GetProcessHeap(), 0x00, this->m_ListHeader);
60 |
61 | // Send first IOCTL to get the amount of memory to allocate.
62 | ULONG64 BufferSize = 0x00;
63 | DWORD ReturnedBytes = 0x00;
64 |
65 | BOOL Success = ::DeviceIoControl(
66 | this->m_DeviceHandle,
67 | IOCTL_MMANAGER_FIND_PROCESS_VADS,
68 | (LPVOID)&ProcessId,
69 | sizeof(ULONG),
70 | &BufferSize,
71 | sizeof(ULONG64),
72 | &ReturnedBytes,
73 | NULL
74 | );
75 | if (!Success) {
76 | wprintf(L"IOCTL_MMANAGER_FIND_PROCESS_VADS failed (%d).\r\n", GetLastError());
77 | return Success;
78 | }
79 |
80 | // Allocate memory
81 | this->m_ListHeader = (MMANAGER_VADLIST_HEADER*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, BufferSize);
82 | if (this->m_ListHeader == NULL) {
83 | wprintf(L"Not enough memory (%d).\r\n", GetLastError());
84 | return FALSE;
85 | }
86 |
87 | // Call to get the data back
88 | ULONG64 UmAddress = (ULONG64)this->m_ListHeader;
89 | Success = ::DeviceIoControl(
90 | this->m_DeviceHandle,
91 | IOCTL_MMANAGER_GET_PROCESS_VADS,
92 | (PVOID)&UmAddress,
93 | sizeof(PVOID),
94 | this->m_ListHeader,
95 | (DWORD)BufferSize,
96 | &ReturnedBytes,
97 | NULL
98 | );
99 | if (!Success) {
100 | wprintf(L"IOCTL_MMANAGER_GET_PROCESS_VADS failed (%d).\r\n", GetLastError());
101 | HeapFree(GetProcessHeap(), 0x00, this->m_ListHeader);
102 | }
103 | return Success;
104 | }
105 |
106 |
107 | VOID CMManager::PrintProcessVads() {
108 | if (this->m_ListHeader == NULL)
109 | return;
110 |
111 | // Header of the table
112 | wprintf(L"VAD Level VPN Start VPN End Commit Type Protection Pagefile/Image\r\n");
113 | wprintf(L"--- ----- --------- ------- ------ ---- ---------- --------------\r\n");
114 | PMMANAGER_VADLIST_ENTRY Entry = this->m_ListHeader->First;
115 | do {
116 | // VAD node generic information
117 | wprintf(L"%p %5d %9llx %9llx %-8I64d %s",
118 | Entry->VadAddress,
119 | Entry->Level,
120 |
121 | Entry->VpnStarting,
122 | Entry->VpnEnding,
123 | Entry->CommitCharge,
124 | Entry->VadFlags.PrivateMemory != 0x00 ? L"Private " : L"Mapped "
125 | );
126 |
127 | // VAD node type information
128 | switch ((MI_VAD_TYPE)Entry->VadFlags.VadType) {
129 | case VadDevicePhysicalMemory:
130 | wprintf(L"Phys ");
131 | break;
132 | case VadImageMap:
133 | wprintf(L"Exe ");
134 | break;
135 | case VadAwe:
136 | wprintf(L"AWE ");
137 | break;
138 | case VadWriteWatch:
139 | wprintf(L"WrtWatch ");
140 | break;
141 | case VadLargePages:
142 | wprintf(L"LargePag ");
143 | break;
144 | case VadRotatePhysical:
145 | wprintf(L"Rotate ");
146 | break;
147 | case VadLargePageSection:
148 | wprintf(L"LargePagSec ");
149 | break;
150 | case VadNone:
151 | default:
152 | wprintf(L" ");
153 | break;
154 | }
155 |
156 | // VAD node permissions
157 | switch (Entry->VadFlags.Protection & MM_PROTECTION_OPERATION_MASK) {
158 | case MM_READONLY:
159 | wprintf(L"READONLY ");
160 | break;
161 | case MM_EXECUTE:
162 | wprintf(L"EXECUTE ");
163 | break;
164 | case MM_EXECUTE_READ:
165 | wprintf(L"EXECUTE_READ ");
166 | break;
167 | case MM_READWRITE:
168 | wprintf(L"READWRITE ");
169 | break;
170 | case MM_WRITECOPY:
171 | wprintf(L"WRITECOPY ");
172 | break;
173 | case MM_EXECUTE_READWRITE:
174 | wprintf(L"EXECUTE_READWRITE ");
175 | break;
176 | case MM_EXECUTE_WRITECOPY:
177 | wprintf(L"EXECUTE_WRITECOPY ");
178 | break;
179 | }
180 | if ((Entry->VadFlags.Protection & ~MM_PROTECTION_OPERATION_MASK) != 0x00) {
181 | switch (Entry->VadFlags.Protection >> 0x03) {
182 | case (MM_NOCACHE >> 0x03):
183 | wprintf(L"NOCACHE ");
184 | break;
185 | case (MM_GUARD_PAGE >> 0x03):
186 | wprintf(L"GUARD_PAGE ");
187 | break;
188 | case (MM_NOACCESS >> 0x03):
189 | wprintf(L"NO_ACCESS ");
190 | break;
191 | }
192 | }
193 |
194 | // Display file name if mapped
195 | if (Entry->FileName[0x00] != 0x00) {
196 | wprintf(L"%s", (PWCHAR)Entry->FileName);
197 | }
198 | else if (Entry->CommitPageCount != 0x00) {
199 | wprintf(L"Pagefile section, shared commit %#I64x", Entry->CommitPageCount);
200 | }
201 | wprintf(L"\r\n");
202 | } while (Entry = Entry->List.Flink);
203 |
204 | wprintf(L"\r\n");
205 | wprintf(L"EPROCESS : 0x%p\r\n", this->m_ListHeader->Eprocess);
206 | wprintf(L"Total VADs : %d\r\n", this->m_ListHeader->NumberOfNodes);
207 | wprintf(L"Maximum depth: %d\r\n", this->m_ListHeader->MaximumLevel);
208 | wprintf(L"\r\n");
209 | }
--------------------------------------------------------------------------------
/MManager/vadlist/mmanager.h:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: mmanager.h
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 |
8 | Abstract:
9 | User mode interface to query VAD list of a process.
10 |
11 | ================================================================================================+*/
12 |
13 | #ifndef __MMANAGER_H_GUARD__
14 | #define __MMANAGER_H_GUARD__
15 |
16 | #include
17 | #include
18 |
19 | // Query the VAD tree of a process
20 | #define IOCTL_MMANAGER_FIND_PROCESS_VADS CTL_CODE( \
21 | 0x8000, /* DeviceType */\
22 | 0x800, /* Function */\
23 | METHOD_OUT_DIRECT, /* Method */\
24 | FILE_ANY_ACCESS /* Access */\
25 | )
26 |
27 | // Query the VAD tree of a process
28 | #define IOCTL_MMANAGER_GET_PROCESS_VADS CTL_CODE( \
29 | 0x8000, /* DeviceType */\
30 | 0x801, /* Function */\
31 | METHOD_OUT_DIRECT, /* Method */\
32 | FILE_ANY_ACCESS /* Access */\
33 | )
34 |
35 | // User-mode name of the device driver
36 | #define MMANAGER_DEVICE_NAME_UM L"\\\\.\\MManager"
37 |
38 | #define MM_ZERO_ACCESS 0 // this value is not used.
39 | #define MM_READONLY 1
40 | #define MM_EXECUTE 2
41 | #define MM_EXECUTE_READ 3
42 | #define MM_READWRITE 4 // bit 2 is set if this is writable.
43 | #define MM_WRITECOPY 5
44 | #define MM_EXECUTE_READWRITE 6
45 | #define MM_EXECUTE_WRITECOPY 7
46 |
47 | #define MM_NOCACHE 0x8
48 | #define MM_GUARD_PAGE 0x10
49 | #define MM_DECOMMIT 0x10 // NO_ACCESS, Guard page
50 | #define MM_NOACCESS 0x18 // NO_ACCESS, Guard_page, nocache.
51 | #define MM_UNKNOWN_PROTECTION 0x100 // bigger than 5 bits!
52 |
53 | #define MM_INVALID_PROTECTION ((ULONG)-1) // bigger than 5 bits!
54 |
55 | #define MM_PROTECTION_WRITE_MASK 4
56 | #define MM_PROTECTION_COPY_MASK 1
57 | #define MM_PROTECTION_OPERATION_MASK 7 // mask off guard page and nocache.
58 | #define MM_PROTECTION_EXECUTE_MASK 2
59 |
60 | typedef enum _MI_VAD_TYPE {
61 | VadNone,
62 | VadDevicePhysicalMemory,
63 | VadImageMap,
64 | VadAwe,
65 | VadWriteWatch,
66 | VadLargePages,
67 | VadRotatePhysical,
68 | VadLargePageSection
69 | } MI_VAD_TYPE, * PMI_VAD_TYPE;
70 |
71 | typedef struct _MMVAD_FLAGS {
72 | ULONG Lock : 1;
73 | ULONG LockContended : 1;
74 | ULONG DeleteInProgress : 1;
75 | ULONG NoChange : 1;
76 | ULONG VadType : 3;
77 | ULONG Protection : 5;
78 | ULONG PreferredNode : 6;
79 | ULONG PageSize : 2;
80 | ULONG PrivateMemory : 1;
81 | } MMVAD_FLAGS, * PMMVAD_FLAGS;
82 |
83 | typedef struct _MMVAD_FLAGS1 {
84 | ULONG CommitCharge : 31;
85 | ULONG MemCommit : 1;
86 | } MMVAD_FLAGS1, * PMMVAD_FLAGS1;
87 |
88 | typedef struct _MMVAD_FLAGS2 {
89 | ULONG FileOffset : 24;
90 | ULONG Large : 1;
91 | ULONG TrimBehind : 1;
92 | ULONG Inherit : 1;
93 | ULONG NoValidationNeeded : 1;
94 | ULONG PrivateDemandZero : 1;
95 | ULONG Spare : 3;
96 | } MMVAD_FLAGS2, * PMMVAD_FLAGS2;
97 |
98 | typedef struct _MM_PRIVATE_VAD_FLAGS {
99 | union {
100 | ULONG Lock : 1;
101 | ULONG LockContended : 1;
102 | ULONG DeleteInProgress : 1;
103 | ULONG NoChange : 1;
104 | ULONG VadType : 3;
105 | ULONG Protection : 5;
106 | ULONG PreferredNode : 6;
107 | ULONG PageSize : 2;
108 | ULONG PrivateMemoryAlwaysSet : 1;
109 | ULONG WriteWatch : 1;
110 | ULONG FixedLargePageSize : 1;
111 | ULONG ZeroFillPagesOptional : 1;
112 | ULONG Graphics : 1;
113 | ULONG Enclave : 1;
114 | ULONG ShadowStack : 1;
115 | ULONG PhysicalMemoryPfnsReferenced : 1;
116 | };
117 | } MM_PRIVATE_VAD_FLAGS, * PMM_PRIVATE_VAD_FLAGS;
118 |
119 | typedef struct _MM_GRAPHICS_VAD_FLAGS {
120 | union {
121 | ULONG Lock : 1;
122 | ULONG LockContended : 1;
123 | ULONG DeleteInProgress : 1;
124 | ULONG NoChange : 1;
125 | ULONG VadType : 3;
126 | ULONG Protection : 5;
127 | ULONG PreferredNode : 6;
128 | ULONG PageSize : 2;
129 | ULONG PrivateMemoryAlwaysSet : 1;
130 | ULONG WriteWatch : 1;
131 | ULONG FixedLargePageSize : 1;
132 | ULONG ZeroFillPagesOptional : 1;
133 | ULONG GraphicsAlwaysSet : 1;
134 | ULONG GraphicsUseCoherentBus : 1;
135 | ULONG GraphicsNoCache : 1;
136 | ULONG GraphicsPageProtection : 3;
137 | };
138 | } MM_GRAPHICS_VAD_FLAGS, * PMM_GRAPHICS_VAD_FLAGS;
139 |
140 | typedef struct _MM_SHARED_VAD_FLAGS {
141 | union {
142 | ULONG Lock : 1;
143 | ULONG LockContended : 1;
144 | ULONG DeleteInProgress : 1;
145 | ULONG NoChange : 1;
146 | ULONG VadType : 3;
147 | ULONG Protection : 5;
148 | ULONG PreferredNode : 6;
149 | ULONG PageSize : 2;
150 | ULONG PrivateMemoryAlwaysClear : 1;
151 | ULONG PrivateFixup : 1;
152 | ULONG HotPatchAllowed : 1;
153 | };
154 | } MM_SHARED_VAD_FLAGS, * PMM_SHARED_VAD_FLAGS;
155 |
156 | typedef struct _MMANAGER_VADLIST_ENTRY {
157 | struct {
158 | struct _MMANAGER_VADLIST_ENTRY* Flink;
159 | struct _MMANAGER_VADLIST_ENTRY* Blink;
160 | } List;
161 |
162 | ULONG64 Size; // Size of the entry (structure + PWCHAR if filename)
163 |
164 | PVOID VadAddress; // Address of the VAD node
165 | ULONG Level; // Node depth level
166 | ULONG64 VpnStarting; // Start of Virtual Page Number(VPN).
167 | ULONG64 VpnEnding; // Start of Virtual Page Number (VPN).
168 | ULONG64 CommitCharge; // Number of bytes commit
169 | ULONG64 CommitPageCount; // Number of pages commited
170 |
171 | // First set of flags.
172 | union {
173 | ULONG LongVadFlags;
174 | MMVAD_FLAGS VadFlags;
175 | MM_PRIVATE_VAD_FLAGS PrivateVadFlags;
176 | MM_GRAPHICS_VAD_FLAGS GraphicsVadFlags;
177 | MM_SHARED_VAD_FLAGS SharedVadFlags;
178 | };
179 | // Second set of flags.
180 | union {
181 | ULONG LongVadFlags1;
182 | MMVAD_FLAGS1 VadFlags1;
183 | };
184 | // Third set of flags.
185 | union {
186 | ULONG LongVadFlags2;
187 | MMVAD_FLAGS2 VadFlags2;
188 | };
189 |
190 | ULONG FileNameSize; // Size of the filename
191 | WCHAR FileName[ANYSIZE_ARRAY]; // Pointer to the filename
192 | } MMANAGER_VADLIST_ENTRY, *PMMANAGER_VADLIST_ENTRY;
193 |
194 | typedef struct _MMANAGER_VADLIST_HEADER {
195 | ULONG64 Size; // Size of the data (header + all entries)
196 | ULONG MaximumLevel; // Deepest level
197 | ULONG NumberOfNodes; // Total number of nodes
198 | ULONG64 TotalPrivateCommit; // Total private memory
199 | ULONG64 TotalSharedCommit; // Total shared memory
200 | PVOID Eprocess; //
201 |
202 | PMMANAGER_VADLIST_ENTRY First;
203 | PMMANAGER_VADLIST_ENTRY Last;
204 | } MMANAGER_VADLIST_HEADER, *PMMANAGER_VADLIST_HEADER;
205 |
206 | class CMManager {
207 |
208 | public:
209 | CMManager();
210 | ~CMManager();
211 |
212 | _Must_inspect_result_
213 | BOOLEAN IsDeviceReady();
214 |
215 | _Must_inspect_result_
216 | BOOLEAN FindProcessVads(
217 | _In_ CONST ULONG ProcessId
218 | );
219 |
220 | VOID PrintProcessVads();
221 |
222 | private:
223 | ///
224 | /// Handle to the device driver.
225 | ///
226 | HANDLE m_DeviceHandle{ INVALID_HANDLE_VALUE };
227 |
228 | ///
229 | /// Pointer to the header of the list.
230 | ///
231 | PMMANAGER_VADLIST_HEADER m_ListHeader{ NULL };
232 | };
233 |
234 | #endif // !__MMANAGER_H_GUARD__
235 |
--------------------------------------------------------------------------------
/MManager/vadlist/vadlist.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {17475489-56c9-4202-ba6f-79c75805e497}
25 | vadlist
26 | 10.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v143
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v143
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v143
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v143
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | Level3
76 | true
77 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
78 | true
79 |
80 |
81 | Console
82 | true
83 |
84 |
85 |
86 |
87 | Level3
88 | true
89 | true
90 | true
91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
92 | true
93 |
94 |
95 | Console
96 | true
97 | true
98 | true
99 |
100 |
101 |
102 |
103 | Level3
104 | true
105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
106 | true
107 | MultiThreadedDebug
108 |
109 |
110 | Console
111 | true
112 |
113 |
114 |
115 |
116 | Level3
117 | true
118 | true
119 | true
120 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
121 | true
122 |
123 |
124 | Console
125 | true
126 | true
127 | true
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/MManager/vadlist/vadlist.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Windows Kernel Programming Experiments
2 | --------------------------------------
3 | All projects and the code within this repository are solely proof of concepts and have not been thoroughly tested on different versions of Microsoft Windows.
4 |
5 | The `DriverEntry` routines of each driver checks for the version of the operating system and will make sure it is `Windows 10 (20h2) - 19044.1706`, as it the Windows 10 version I used to test the drivers.
6 |
7 | All structures and other `typedef` have been defined via available PDBs, WinDBG and [resym tool](https://github.com/ergrelet/resym). Structures and data may differ from one version to another - use with caution.
8 |
9 | ### MManager
10 | Experiments with the Windows Memory Manager (Mm/Mi). Currently listing Virtual Address Descriptors (VADs) of a process.
11 |
12 | Kernel Device Name: `\\Device\\MManager`
13 |
14 | List of User-Mode applications:
15 | - vadlist.exe
--------------------------------------------------------------------------------
/WKI/WKI.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.3.32505.426
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WKIKM", "WKIKM\WKIKM.vcxproj", "{75E14ADD-808F-491C-A221-B29E5AA667D8}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WKIUM", "WKIUM\WKIUM.vcxproj", "{5E103710-74AD-495F-9A72-C69573DF2D2A}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|ARM64 = Debug|ARM64
14 | Debug|x64 = Debug|x64
15 | Debug|x86 = Debug|x86
16 | Release|Any CPU = Release|Any CPU
17 | Release|ARM64 = Release|ARM64
18 | Release|x64 = Release|x64
19 | Release|x86 = Release|x86
20 | EndGlobalSection
21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Debug|Any CPU.ActiveCfg = Debug|x64
23 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Debug|Any CPU.Build.0 = Debug|x64
24 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Debug|Any CPU.Deploy.0 = Debug|x64
25 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Debug|ARM64.ActiveCfg = Debug|ARM64
26 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Debug|ARM64.Build.0 = Debug|ARM64
27 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Debug|ARM64.Deploy.0 = Debug|ARM64
28 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Debug|x64.ActiveCfg = Debug|x64
29 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Debug|x64.Build.0 = Debug|x64
30 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Debug|x64.Deploy.0 = Debug|x64
31 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Debug|x86.ActiveCfg = Debug|x64
32 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Debug|x86.Build.0 = Debug|x64
33 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Debug|x86.Deploy.0 = Debug|x64
34 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Release|Any CPU.ActiveCfg = Release|x64
35 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Release|Any CPU.Build.0 = Release|x64
36 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Release|Any CPU.Deploy.0 = Release|x64
37 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Release|ARM64.ActiveCfg = Release|ARM64
38 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Release|ARM64.Build.0 = Release|ARM64
39 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Release|ARM64.Deploy.0 = Release|ARM64
40 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Release|x64.ActiveCfg = Release|x64
41 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Release|x64.Build.0 = Release|x64
42 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Release|x64.Deploy.0 = Release|x64
43 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Release|x86.ActiveCfg = Release|x64
44 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Release|x86.Build.0 = Release|x64
45 | {75E14ADD-808F-491C-A221-B29E5AA667D8}.Release|x86.Deploy.0 = Release|x64
46 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Debug|Any CPU.ActiveCfg = Debug|x64
47 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Debug|Any CPU.Build.0 = Debug|x64
48 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Debug|ARM64.ActiveCfg = Debug|x64
49 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Debug|ARM64.Build.0 = Debug|x64
50 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Debug|x64.ActiveCfg = Debug|x64
51 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Debug|x64.Build.0 = Debug|x64
52 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Debug|x86.ActiveCfg = Debug|Win32
53 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Debug|x86.Build.0 = Debug|Win32
54 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Release|Any CPU.ActiveCfg = Release|x64
55 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Release|Any CPU.Build.0 = Release|x64
56 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Release|ARM64.ActiveCfg = Release|x64
57 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Release|ARM64.Build.0 = Release|x64
58 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Release|x64.ActiveCfg = Release|x64
59 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Release|x64.Build.0 = Release|x64
60 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Release|x86.ActiveCfg = Release|Win32
61 | {5E103710-74AD-495F-9A72-C69573DF2D2A}.Release|x86.Build.0 = Release|Win32
62 | EndGlobalSection
63 | GlobalSection(SolutionProperties) = preSolution
64 | HideSolutionNode = FALSE
65 | EndGlobalSection
66 | GlobalSection(ExtensibilityGlobals) = postSolution
67 | SolutionGuid = {ED1B074C-3945-47E8-B42C-3F70C01E4BAC}
68 | EndGlobalSection
69 | EndGlobal
70 |
--------------------------------------------------------------------------------
/WKI/WKIKM/WKIKM.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x64
7 |
8 |
9 | Release
10 | x64
11 |
12 |
13 | Debug
14 | ARM64
15 |
16 |
17 | Release
18 | ARM64
19 |
20 |
21 |
22 | {75E14ADD-808F-491C-A221-B29E5AA667D8}
23 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d}
24 | v4.5
25 | 12.0
26 | Debug
27 | x64
28 | KernelIntrospection
29 | WKIKM
30 | $(LatestTargetPlatformVersion)
31 |
32 |
33 |
34 | Windows10
35 | true
36 | WindowsKernelModeDriver10.0
37 | Driver
38 | WDM
39 | false
40 |
41 |
42 | Windows10
43 | false
44 | WindowsKernelModeDriver10.0
45 | Driver
46 | WDM
47 |
48 |
49 | Windows10
50 | true
51 | WindowsKernelModeDriver10.0
52 | Driver
53 | WDM
54 |
55 |
56 | Windows10
57 | false
58 | WindowsKernelModeDriver10.0
59 | Driver
60 | WDM
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | DbgengKernelDebugger
72 | wkikm
73 |
74 |
75 | DbgengKernelDebugger
76 |
77 |
78 | DbgengKernelDebugger
79 |
80 |
81 | DbgengKernelDebugger
82 |
83 |
84 |
85 | sha256
86 |
87 |
88 | wdmsec.lib;Aux_Klib.lib;%(AdditionalDependencies)
89 |
90 |
91 |
92 |
93 | sha256
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/WKI/WKIKM/WKIKM.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/WKI/WKIKM/ki-globals.h:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: ki-globals.h
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | This file contains all global definition and information used by the kernel driver.
9 | ================================================================================================+*/
10 |
11 | #ifndef __KI_H_GUARD__
12 | #define __KI_H_GUARD__
13 |
14 | #include
15 | #include
16 |
17 | // Include security routines for driver
18 | #include
19 |
20 | // Windows Kernel Introspection Device driver name
21 | #define KI_DEVICE_NAME L"\\Device\\WKI"
22 |
23 | // Windows Kernel Introspection Device driver symbolic name
24 | #define KI_SYMBOLIC_LINK_NAME L"\\??\\WKI"
25 |
26 | // Windows Kernel Introspection Debug tag
27 | #define KI_DEBUG_TAG "[WKI] "
28 |
29 | // Windows Kernel Introspection wrapper around KdPrint for less bloated code.
30 | #define KiDebug(_x_) KdPrint((KI_DEBUG_TAG)); KdPrint(_x_)
31 |
32 | // Windows Kernel Introspection class GUID - {3E07100B-E36E-4F2E-8345-1399B9947497}
33 | static CONST GUID KI_CLASS_GUID = {
34 | 0x3e07100b,
35 | 0xe36e,
36 | 0x4f2e,
37 | { 0x83, 0x45, 0x13, 0x99, 0xb9, 0x94, 0x74, 0x97 }
38 | };
39 |
40 | #endif // !__KI_H_GUARD__
41 |
--------------------------------------------------------------------------------
/WKI/WKIKM/main.c:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: main.c
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | Device driver entry point.
9 | ================================================================================================+*/
10 |
11 | #include "ki-globals.h"
12 | #include "wki/wki.h"
13 |
14 | ///
15 | /// Device driver entry point.
16 | ///
17 | /// Pointer to the driver object.
18 | /// Pointer to the registry path, if any.
19 | EXTERN_C NTSTATUS DriverEntry(
20 | _In_ PDRIVER_OBJECT DriverObject,
21 | _In_ PUNICODE_STRING RegistryPath
22 | );
23 |
24 | ///
25 | /// The Unload routine performs any operations that are necessary before the system unloads the driver.
26 | ///
27 | _IRQL_requires_max_(PASSIVE_LEVEL)
28 | EXTERN_C VOID DriverUnload(
29 | _In_ PDRIVER_OBJECT DriverObject
30 | );
31 |
32 | ///
33 | /// Test Windows Kernel Introspection initialisation and the successful retreival of required
34 | /// symbols for the list of memory pool tags.
35 | ///
36 | _IRQL_requires_max_(PASSIVE_LEVEL)
37 | EXTERN_C VOID TestWKI(
38 | VOID
39 | );
40 |
41 | ///
42 | /// List kernel memory ppol tags.
43 | ///
44 | _IRQL_requires_max_(PASSIVE_LEVEL)
45 | EXTERN_C VOID ListPoolTags(
46 | VOID
47 | );
48 |
49 | #ifdef ALLOC_PRAGMA
50 | #pragma alloc_text(INIT, DriverEntry)
51 |
52 | #pragma alloc_text(PAGE, DriverUnload)
53 | #pragma alloc_text(PAGE, TestWKI)
54 | #pragma alloc_text(PAGE, ListPoolTags)
55 | #endif // ALLOC_PRAGMA
56 |
57 |
58 | _Use_decl_annotations_
59 | EXTERN_C NTSTATUS DriverEntry(
60 | _In_ PDRIVER_OBJECT DriverObject,
61 | _In_ PUNICODE_STRING RegistryPath
62 | ) {
63 | UNREFERENCED_PARAMETER(RegistryPath);
64 |
65 | KiDebug(("=================================================================\r\n"));
66 | KiDebug(("Module Name: Windows Kernel Introspection -- KM \r\n"));
67 | KiDebug(("Author : Paul L. (@am0nsec) \r\n"));
68 | KiDebug(("Origin : https://github.com/am0nsec/wkpe/ \r\n"));
69 | KiDebug(("Tested OS : Windows 10 (20h2) - 19044.1889 \r\n"));
70 | KiDebug((" Windows 10 (20h2) - 19044.1766 \r\n"));
71 | KiDebug((" Windows 10 (20h2) - 19044.1706 \r\n"));
72 | KiDebug(("=================================================================\r\n"));
73 |
74 | // Initialise stack variables
75 | NTSTATUS Status = STATUS_SUCCESS;
76 | UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(KI_DEVICE_NAME);
77 | UNICODE_STRING SymbolicName = RTL_CONSTANT_STRING(KI_SYMBOLIC_LINK_NAME);
78 |
79 | PDEVICE_OBJECT DeviceObject = NULL;
80 | BOOLEAN SymbolicLink = FALSE;
81 |
82 | // Set unload routine
83 | DriverObject->DriverUnload = DriverUnload;
84 |
85 | // Register the device driver and symbolic link
86 | do {
87 | // Exclusive - Prevent multiple handles to be open for the device driver.
88 | // SDDLString - Prevent non-admin and non-SYSTEM from interacting with the device driver.
89 | Status = WdmlibIoCreateDeviceSecure(
90 | DriverObject,
91 | 0x00,
92 | &DeviceName,
93 | FILE_DEVICE_UNKNOWN,
94 | 0x00,
95 | TRUE,
96 | &SDDL_DEVOBJ_SYS_ALL_ADM_ALL,
97 | &KI_CLASS_GUID,
98 | &DeviceObject
99 | );
100 | if (!NT_SUCCESS(Status)) {
101 | KiDebug(("Failed to create device object (0x%08X).\r\n", Status));
102 | break;
103 | }
104 |
105 | Status = IoCreateSymbolicLink(&SymbolicName, &DeviceName);
106 | if (!NT_SUCCESS(Status)) {
107 | KiDebug(("Failed to symbolic link (0x%08X).\r\n", Status));
108 | break;
109 | }
110 | SymbolicLink = TRUE;
111 | } while (FALSE);
112 |
113 | // Check for errors
114 | if (!NT_SUCCESS(Status)) {
115 | KiDebug(("Roll-back operations.\r\n"));
116 | if (SymbolicLink)
117 | IoDeleteSymbolicLink(&SymbolicName);
118 | if (DeviceObject != NULL)
119 | IoDeleteDevice(DeviceObject);
120 | KiDebug(("----------------------------------------------------------------\r\n"));
121 | return Status;
122 | }
123 |
124 | // Display final information and exit
125 | KiDebug(("Device name : %wZ\r\n", DeviceName));
126 | KiDebug(("Symbolic link name: %wZ\r\n", SymbolicName));
127 | KiDebug(("-----------------------------------------------\r\n"));
128 |
129 | TestWKI();
130 | ListPoolTags();
131 | return Status;
132 | }
133 |
134 |
135 | _Use_decl_annotations_
136 | EXTERN_C VOID DriverUnload(
137 | _In_ PDRIVER_OBJECT DriverObject
138 | ) {
139 | KiDebug(("-----------------------------------------------\r\n"));
140 |
141 | // Uninitialise WKI
142 | WkiUninitialise();
143 |
144 | // Delete the symbolic link and the device object
145 | UNICODE_STRING SymbolicName = RTL_CONSTANT_STRING(KI_SYMBOLIC_LINK_NAME);
146 | IoDeleteSymbolicLink(&SymbolicName);
147 | IoDeleteDevice(DriverObject->DeviceObject);
148 | }
149 |
150 |
151 | _Use_decl_annotations_
152 | EXTERN_C VOID TestWKI(
153 | VOID
154 | ) {
155 | KiDebug(("Start testing wki ...\r\n"));
156 |
157 | NTSTATUS Status = WkiInitialise();
158 | if (NT_ERROR(Status)) {
159 | KiDebug(("WkiInitialise failed \r\n"));
160 | WkiUninitialise();
161 | return;
162 | }
163 |
164 | // Make sure everything is available when required
165 | ASSERT(WkiGetSymbol("KeNumberProcessors"));
166 | ASSERT(WkiGetSymbol("ExPoolTagTables"));
167 | ASSERT(WkiGetSymbol("PoolTrackTableSize"));
168 |
169 | KiDebug(("Start testing wki ... ok\r\n"));
170 | KiDebug(("-----------------------------------------------\r\n"));
171 | }
172 |
173 | typedef struct _POOL_TRACKER_TABLE {
174 | INT32 Key;
175 | UINT64 NonPagedBytes;
176 | UINT64 NonPagedAllocs;
177 | UINT64 NonPagedFrees;
178 | UINT64 PagedBytes;
179 | UINT64 PagedAllocs;
180 | UINT64 PagedFrees;
181 | } POOL_TRACKER_TABLE, *PPOOL_TRACKER_TABLE;
182 |
183 |
184 | EXTERN_C VOID MakePrintableString(
185 | _In_ UINT32 Key,
186 | _Out_ PUCHAR String
187 | ) {
188 |
189 | for (UINT16 cx = 0x04; cx > 0x00; cx--) {
190 |
191 | INT Shift = (0x08 * (cx - 1));
192 | INT Char = (Key & (UINT32)((UINT32)0xFF << Shift)) >> Shift;
193 |
194 | if (isprint(Char))
195 | String[cx - 1] = (UCHAR)Char;
196 | else
197 | String[cx - 1] = (UCHAR)0x2E;
198 | }
199 | }
200 |
201 |
202 | _Use_decl_annotations_
203 | ///
204 | /// List Windows Kernel Memory Pool Tags.
205 | ///
206 | EXTERN_C VOID ListPoolTags(
207 | VOID
208 | ) {
209 | KiDebug(("List kernel memory pool tags ...\r\n"));
210 |
211 | // Get the number of processors on the system.
212 | PVOID XxKeNumberProcessors = WkiGetSymbol("KeNumberProcessors");
213 | if (XxKeNumberProcessors == NULL) {
214 | KiDebug(("Error \"KeNumberProcessors\" symbol not found.\r\n"));
215 | return;
216 | }
217 |
218 | // Get the list of Pool tables
219 | PVOID PoolTagTables = WkiGetSymbol("ExPoolTagTables");
220 | if (PoolTagTables == NULL) {
221 | KiDebug(("Error \"ExPoolTagTables\" symbol not found.\r\n"));
222 | return;
223 | }
224 |
225 | // Get the pointer to the size of the kernel pool table.
226 | PVOID XxPoolTrackTableSize = WkiGetSymbol("PoolTrackTableSize");
227 | if (XxPoolTrackTableSize == NULL) {
228 | KiDebug(("Error \"PoolTrackTableSize\" symbol not found.\r\n"));
229 | return;
230 | }
231 |
232 | // Get the pool block shift if any
233 | PVOID XxExpPoolBlockShift = WkiGetSymbol("ExpPoolBlockShift");
234 |
235 | // Get pool table expansion
236 | PVOID XxPoolTrackTableExpansion = WkiGetSymbol("PoolTrackTableExpansion");
237 | PVOID XxPoolTrackTableExpansionSize = WkiGetSymbol("PoolTrackTableExpansionSize");
238 |
239 | // Prepare all local stack variables required
240 | UINT64 PoolTableEntries = 0x01;
241 | if (XxKeNumberProcessors != NULL)
242 | PoolTableEntries = WkiReadValue(XxKeNumberProcessors, sizeof(UINT32));
243 |
244 | UINT64 PoolBlockShift = 0x00;
245 | if (XxExpPoolBlockShift != NULL)
246 | PoolBlockShift = WkiReadValue(XxExpPoolBlockShift, sizeof(UINT64));
247 |
248 | UINT64 TrackTableExpansionEntries = 0x00;
249 | if (XxPoolTrackTableExpansionSize != NULL)
250 | TrackTableExpansionEntries = WkiReadValue(XxPoolTrackTableExpansionSize, sizeof(UINT64));
251 |
252 | PPOOL_TRACKER_TABLE TrackTableExpansion = NULL;
253 | if (XxPoolTrackTableExpansion != NULL)
254 | TrackTableExpansion = (PVOID)WkiReadValue(XxPoolTrackTableExpansion, sizeof(UINT64));
255 |
256 | UINT64 TrackTableEntries = WkiReadValue(XxPoolTrackTableSize, sizeof(UINT64));
257 |
258 | // Allocate memory to store all the data in order to filter the result.
259 | PPOOL_TRACKER_TABLE PoolTags = ExAllocatePool2(
260 | POOL_FLAG_NON_PAGED,
261 | ((TrackTableEntries + TrackTableExpansionEntries) * sizeof(POOL_TRACKER_TABLE)),
262 | WKI_MM_TAG
263 | );
264 | if (PoolTags == NULL)
265 | return;
266 |
267 | // Parse all tracker entries
268 | UINT64 ValidEntries = 0x00;
269 | for (UINT64 cx = 0x00; cx < TrackTableEntries; cx++) {
270 |
271 | BOOLEAN Valid = TRUE;
272 | for (UINT64 dx = 0x00; dx < PoolTableEntries; dx++) {
273 |
274 | // Get proper tracker table
275 | PPOOL_TRACKER_TABLE TrackerTable = (PVOID)WkiReadValue(((PUCHAR)PoolTagTables + (0x8 * dx)), sizeof(PPOOL_TRACKER_TABLE));
276 | if (TrackerTable == NULL)
277 | continue;
278 |
279 | if (TrackerTable[cx].Key == 0x00)
280 | continue;
281 |
282 | PoolTags[cx].NonPagedAllocs += TrackerTable[cx].NonPagedAllocs;
283 | PoolTags[cx].NonPagedFrees += TrackerTable[cx].NonPagedFrees;
284 | PoolTags[cx].NonPagedBytes += TrackerTable[cx].NonPagedBytes;
285 | PoolTags[cx].PagedAllocs += TrackerTable[cx].PagedAllocs;
286 | PoolTags[cx].PagedFrees += TrackerTable[cx].PagedFrees;
287 | PoolTags[cx].PagedBytes += TrackerTable[cx].PagedBytes;
288 | PoolTags[cx].Key = TrackerTable[cx].Key;
289 |
290 | if (PoolTags[cx].Key != 0x00 && Valid) {
291 | ValidEntries++;
292 | Valid = FALSE;
293 | }
294 | }
295 | }
296 | if (TrackTableExpansion != NULL) {
297 | for (UINT64 cx = 0x00; cx < TrackTableExpansionEntries; cx++) {
298 | PoolTags[ValidEntries + cx].NonPagedAllocs += TrackTableExpansion[cx].NonPagedAllocs;
299 | PoolTags[ValidEntries + cx].NonPagedFrees += TrackTableExpansion[cx].NonPagedFrees;
300 | PoolTags[ValidEntries + cx].NonPagedBytes += TrackTableExpansion[cx].NonPagedBytes;
301 | PoolTags[ValidEntries + cx].PagedAllocs += TrackTableExpansion[cx].PagedAllocs;
302 | PoolTags[ValidEntries + cx].PagedFrees += TrackTableExpansion[cx].PagedFrees;
303 | PoolTags[ValidEntries + cx].PagedBytes += TrackTableExpansion[cx].PagedBytes;
304 | PoolTags[ValidEntries + cx].Key = TrackTableExpansion[cx].Key;
305 | }
306 | }
307 |
308 | // Display all information
309 | KdPrint((" NonPaged Paged\r\n"));
310 | KdPrint((" Tag Allocs Frees Diff Used Allocs Frees Diff Used\r\n\r\n"));
311 |
312 | for (UINT64 cx = 0x00; cx < TrackTableEntries; cx++) {
313 | POOL_TRACKER_TABLE Entry = PoolTags[cx];
314 | if (Entry.Key == 0x00)
315 | continue;
316 |
317 | UCHAR KeyString[sizeof(UINT64)] = { 0x00 };
318 | MakePrintableString(Entry.Key, KeyString);
319 |
320 | KdPrint((" %s %11I64u %11I64u %9I64u %12I64d %11I64u %11I64u %9I64u %12I64d\r\n",
321 | KeyString,
322 | Entry.NonPagedAllocs,
323 | Entry.NonPagedFrees,
324 | (Entry.NonPagedAllocs - Entry.NonPagedFrees),
325 | Entry.NonPagedBytes,
326 | Entry.PagedAllocs,
327 | Entry.PagedFrees,
328 | (Entry.PagedAllocs - Entry.PagedFrees),
329 | Entry.PagedBytes
330 | ));
331 | }
332 |
333 | // Cleanup
334 | ExFreePoolWithTag(PoolTags, WKI_MM_TAG);
335 | KiDebug(("List kernel memory pool tags ... ok\r\n"));
336 | KiDebug(("-----------------------------------------------\r\n"));
337 | }
--------------------------------------------------------------------------------
/WKI/WKIKM/wki/wki.h:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: wki.h
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wspe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | Windows Kernel Introspection (WKI).
9 |
10 | ================================================================================================+*/
11 |
12 | #ifndef __WKI_H_GUARD__
13 | #define __WKI_H_GUARD__
14 |
15 | #ifndef _NTIFS_
16 | #include
17 | #endif // !_NTIFS_
18 | #ifndef _NTSTRSAFE_H_INCLUDED_
19 | #include
20 | #endif // !_NTSTRSAFE_H_INCLUDED_
21 | #ifndef _AUX_KLIB_H
22 | #include
23 | #endif // !_AUX_KLIB_H
24 |
25 |
26 | // Windows Kernel Introspection (WKI) Memory Pool Tag - "Wki ".
27 | #define WKI_MM_TAG (ULONG)0x20696b57
28 |
29 | // Name of the Windows Registry key that store the current OS version.
30 | #define WKI_CURRENTVERSION_KEY_NAME L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
31 |
32 | // Name of the Windows Registry key that store all the WKI information.
33 | #define WKI_KINTROSPECTION_KEY_NAME L"\\Registry\\Machine\\SOFTWARE\\WKI"
34 |
35 |
36 | ///
37 | /// Structure representing a symbol.
38 | ///
39 | typedef struct _WKI_SYMBOL_ENTRY {
40 | LIST_ENTRY List;
41 |
42 | struct {
43 | UINT32 DJB;
44 | UINT32 OFF;
45 | UINT32 RVA;
46 | UINT32 SEG;
47 | } Body;
48 | } WKI_SYMBOL_ENTRY, *PWKI_SYMBOL_ENTRY;
49 |
50 |
51 | ///
52 | /// Global data used internally by WKI.
53 | ///
54 | typedef struct _WKI_GLOBALS {
55 | UINT32 NumberOfSymbols;
56 | UINT32 NumberOfRoutines;
57 | UINT32 NumberOfStructures;
58 |
59 | UINT64 KernelBase;
60 |
61 | LIST_ENTRY SymbolHead;
62 | LIST_ENTRY StructureHead;
63 | } WKI_GLOBALS, *PWKI_GLOBALS;
64 |
65 |
66 | ///
67 | ///
68 | ///
69 | EXTERN_C NTSTATUS
70 | _IRQL_requires_max_(APC_LEVEL)
71 | _Must_inspect_result_
72 | _Success_(return == STATUS_SUCCESS)
73 | WkiInitialise();
74 |
75 |
76 | ///
77 | ///
78 | ///
79 | EXTERN_C VOID
80 | _IRQL_requires_max_(APC_LEVEL)
81 | WkiUninitialise();
82 |
83 |
84 | ///
85 | ///
86 | ///
87 | ///
88 | ///
89 | EXTERN_C PVOID
90 | _IRQL_requires_max_(APC_LEVEL)
91 | _Must_inspect_result_
92 | _Success_(return != NULL)
93 | WkiGetSymbol(
94 | _In_ LPCSTR SymbolName
95 | );
96 |
97 |
98 | EXTERN_C UINT64
99 | _IRQL_requires_max_(APC_LEVEL)
100 | _Must_inspect_result_
101 | _Success_(return != 0x00)
102 | WkiReadValue(
103 | _In_ PVOID Address,
104 | _In_ UINT16 Size
105 | );
106 |
107 | // Global Windows Kernel Introspection (WKI) Data.
108 | extern WKI_GLOBALS WkiGlobal;
109 |
110 | #endif // !__WKI_H_GUARD__
111 |
--------------------------------------------------------------------------------
/WKI/WKIUM/WKIUM.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {5e103710-74ad-495f-9a72-c69573df2d2a}
25 | KernelIntrospectionUM
26 | 10.0
27 | WKIUM
28 |
29 |
30 |
31 | Application
32 | true
33 | v143
34 | Unicode
35 |
36 |
37 | Application
38 | false
39 | v143
40 | true
41 | Unicode
42 |
43 |
44 | Application
45 | true
46 | v143
47 | Unicode
48 |
49 |
50 | Application
51 | false
52 | v143
53 | true
54 | Unicode
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | wkium
76 |
77 |
78 |
79 | Level3
80 | true
81 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
82 | true
83 |
84 |
85 | Console
86 | true
87 |
88 |
89 |
90 |
91 | Level3
92 | true
93 | true
94 | true
95 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
96 | true
97 |
98 |
99 | Console
100 | true
101 | true
102 | true
103 |
104 |
105 |
106 |
107 | Level3
108 | true
109 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
110 | true
111 | MultiThreadedDebug
112 |
113 |
114 | Console
115 | true
116 | %(AdditionalDependencies)
117 |
118 |
119 | false
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 | Level3
129 | true
130 | true
131 | true
132 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
133 | true
134 |
135 |
136 | Console
137 | true
138 | true
139 | true
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/WKI/WKIUM/WKIUM.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/WKI/WKIUM/callback.c:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: callback.c
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | Abstraction of the Microsoft Debug Interface Access (DIA) SDK.
9 |
10 | In this case this module contains the code for the CCallback COM interface implementation when loading PDB from
11 | a PE EXE file.
12 |
13 | Documentation available at: https://docs.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/debug-interface-access-sdk
14 | Most of the code is based on the Dia2Dump code sample shipped with the MS DIA SDK.
15 | ================================================================================================+*/
16 |
17 | #include
18 | #include
19 |
20 | #include "inc/callback.h"
21 |
22 | // 4688a074-5a4d-4486-aea8-7b90711d9f7c
23 | CONST IID IID_IDiaLoadCallback2 = {
24 | 0x4688a074, 0x5a4d, 0x4486, { 0xae, 0xa8, 0x7b, 0x90, 0x71, 0x1d, 0x9f, 0x7c }
25 | };
26 |
27 | // C32ADB82-73F4-421b-95D5-A4706EDF5DBE
28 | CONST IID IID_IDiaLoadCallback = {
29 | 0xC32ADB82, 0x73F4, 0x421b, { 0x95, 0xD5, 0xA4, 0x70, 0x6E, 0xDF, 0x5D, 0xBE }
30 | };
31 |
32 | // Global handle variable used to allocate/free executable heap memory.
33 | HANDLE g_HeapHandle = INVALID_HANDLE_VALUE;
34 |
35 |
36 | HRESULT STDMETHODCALLTYPE QueryInterface(
37 | IDiaLoadCallback2* This,
38 | REFIID rid,
39 | PVOID* ppUnk
40 | ) {
41 | if (ppUnk == NULL) {
42 | return E_INVALIDARG;
43 | }
44 |
45 | if (IsEqualIID(rid, &IID_IDiaLoadCallback2))
46 | *ppUnk = (IDiaLoadCallback2*)This;
47 | else if (IsEqualIID(rid, &IID_IDiaLoadCallback))
48 | *ppUnk = (IDiaLoadCallback*)This;
49 | else if (IsEqualIID(rid, &IID_IUnknown))
50 | *ppUnk = (IUnknown*)This;
51 | else
52 | *ppUnk = NULL;
53 | if (*ppUnk != NULL) {
54 | This->lpVtbl->AddRef(This);
55 | return S_OK;
56 | }
57 | return E_NOINTERFACE;
58 | }
59 |
60 | ULONG STDMETHODCALLTYPE AddRef(
61 | IDiaLoadCallback2* This
62 | ) {
63 | DiaCallback* Callback = (DiaCallback*)This;
64 | return ++Callback->m_nRefCount;
65 | }
66 |
67 | ULONG STDMETHODCALLTYPE Release(
68 | IDiaLoadCallback2* This
69 | ) {
70 | DiaCallback* Callback = (DiaCallback*)This;
71 |
72 | if ((--Callback->m_nRefCount) == 0) {
73 | DiaCallbackHelper(FALSE, (PVOID)&This);
74 | return 0x00;
75 | }
76 | return Callback->m_nRefCount;
77 | }
78 |
79 | HRESULT STDMETHODCALLTYPE NotifyDebugDir(
80 | IDiaLoadCallback2* This,
81 | BOOL fExecutable,
82 | DWORD cbData,
83 | BYTE data[]
84 | ) {
85 | return S_OK;
86 | }
87 |
88 | HRESULT STDMETHODCALLTYPE NotifyOpenDBG(
89 | IDiaLoadCallback2* This,
90 | LPCOLESTR dbgPath,
91 | HRESULT resultCode
92 | ) {
93 | return S_OK;
94 | }
95 |
96 | HRESULT STDMETHODCALLTYPE NotifyOpenPDB(
97 | IDiaLoadCallback2* This,
98 | LPCOLESTR pdbPath,
99 | HRESULT resultCode
100 | ) {
101 | if (SUCCEEDED(resultCode)) {
102 | wprintf(L"[*] Open: %s\r\n", pdbPath);
103 | }
104 | return S_OK;
105 | }
106 |
107 | HRESULT STDMETHODCALLTYPE RestrictRegistryAccess(
108 | IDiaLoadCallback2* This
109 | ) {
110 | // return hr != S_OK to prevent querying the registry for symbol search paths
111 | return S_OK;
112 | }
113 |
114 | HRESULT STDMETHODCALLTYPE RestrictSymbolServerAccess(
115 | IDiaLoadCallback2* This
116 | ) {
117 | // return hr != S_OK to prevent accessing a symbol server
118 | return S_OK;
119 | }
120 |
121 | HRESULT STDMETHODCALLTYPE RestrictOriginalPathAccess(
122 | IDiaLoadCallback2* This
123 | ) {
124 | // return hr != S_OK to prevent querying the registry for symbol search paths
125 | return S_OK;
126 | }
127 |
128 | HRESULT STDMETHODCALLTYPE RestrictReferencePathAccess(
129 | IDiaLoadCallback2* This
130 | ) {
131 | // return hr != S_OK to prevent accessing a symbol server
132 | return S_OK;
133 | }
134 |
135 | HRESULT STDMETHODCALLTYPE RestrictDBGAccess(
136 | IDiaLoadCallback2* This
137 | ) {
138 | return S_OK;
139 | }
140 |
141 | HRESULT STDMETHODCALLTYPE RestrictSystemRootAccess(
142 | IDiaLoadCallback2* This
143 | ) {
144 | return S_OK;
145 | }
146 |
147 |
148 | ///
149 | /// Callback virtual table.
150 | ///
151 | static CONST IDiaLoadCallback2Vtbl CallbackVirtualTable = {
152 | // IUnknown
153 | QueryInterface,
154 | AddRef,
155 | Release,
156 |
157 | // IDiaLoadCallback
158 | NotifyDebugDir,
159 | NotifyOpenDBG,
160 | NotifyOpenPDB,
161 | RestrictRegistryAccess,
162 | RestrictSymbolServerAccess,
163 |
164 | // IDiaLoadCallback2
165 | RestrictOriginalPathAccess,
166 | RestrictReferencePathAccess,
167 | RestrictDBGAccess,
168 | RestrictSystemRootAccess
169 | };
170 |
171 |
172 | _Use_decl_annotations_
173 | HRESULT STDMETHODCALLTYPE DiaCallbackHelper(
174 | _In_ BOOLEAN Initialise,
175 | _Inout_ PVOID** Callback
176 | ) {
177 | if (Callback == NULL)
178 | return E_FAIL;
179 |
180 | // Create the structure for the callback
181 | if (Initialise) {
182 | if (g_HeapHandle != INVALID_HANDLE_VALUE)
183 | return E_FAIL;
184 |
185 | // Create executable heap
186 | g_HeapHandle = HeapCreate(
187 | HEAP_CREATE_ENABLE_EXECUTE,
188 | sizeof(IDiaLoadCallback2Vtbl) + sizeof(DiaCallback),
189 | 0x1000
190 | );
191 | if (g_HeapHandle == INVALID_HANDLE_VALUE)
192 | return E_FAIL;
193 |
194 | // Allocate memory in the new heap
195 | DiaCallback* Buffer = HeapAlloc(g_HeapHandle, HEAP_ZERO_MEMORY, sizeof(DiaCallback) + sizeof(IDiaLoadCallback2Vtbl));
196 | if (Buffer == NULL) {
197 | HeapDestroy(g_HeapHandle);
198 | return E_FAIL;
199 | }
200 |
201 | PVOID cstruct = HeapAlloc(g_HeapHandle, HEAP_ZERO_MEMORY, sizeof(DiaCallback));;
202 | PVOID vtable = NULL;
203 |
204 |
205 | // Assemble everything
206 | Buffer->m_nRefCount = 0x00;
207 | Buffer->lpVtbl = (IDiaLoadCallback2*)&CallbackVirtualTable;
208 |
209 | *Callback = (PVOID)Buffer;
210 | return S_OK;
211 | }
212 | // Delete the structure for the callback
213 | else {
214 | if (g_HeapHandle == INVALID_HANDLE_VALUE || Callback == NULL)
215 | return E_FAIL;
216 |
217 | // Check that the reference count is zero
218 | DiaCallback* src = (DiaCallback*)*Callback;
219 | if (src->m_nRefCount != 0x00)
220 | return E_FAIL;
221 |
222 | // Free the memory and destroy the executable heap
223 | HeapFree(g_HeapHandle, 0x00, src);
224 | HeapDestroy(g_HeapHandle);
225 | g_HeapHandle = INVALID_HANDLE_VALUE;
226 | }
227 |
228 | return E_FAIL;
229 | }
--------------------------------------------------------------------------------
/WKI/WKIUM/dirutil.c:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: dirutil.c
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | Windows Directory utility code.
9 | Used to change directory to the "PDB" folder and get the correct symbol server search path.
10 |
11 | ================================================================================================+*/
12 |
13 | #include
14 | #include
15 | #include
16 |
17 | #include "inc/dirutil.h"
18 |
19 |
20 | _Use_decl_annotations_
21 | NTSTATUS GetSymSrvSearchPath(
22 | _Out_ PWCHAR* SymSearchPath
23 | ) {
24 | // Get the current path
25 | PWSTR DefaultDirectory[MAX_PATH] = { 0x00 };
26 | DWORD dwCurrentDirectory = GetCurrentDirectoryW(MAX_PATH, (LPWSTR)DefaultDirectory);
27 | if (dwCurrentDirectory == 0x00)
28 | return E_FAIL;
29 |
30 | // Other local Stack Variables
31 | CONST PWCHAR Pdb = L"pdb";
32 | CONST PWCHAR Sym = L"symsrv";
33 | CONST PWCHAR Dll = L"symsrv.dll";
34 | CONST PWCHAR Web = L"https://msdl.microsoft.com/download/symbols";
35 |
36 | // Calculate the size of the buffer to allocate
37 | DWORD dwBuffer = 0x100;
38 | DWORD dwSize = lstrlenW(Pdb) + lstrlenW(Sym) + lstrlenW(Dll) + lstrlenW(Web) + (sizeof(WCHAR) * 4) + lstrlenW((LPWSTR)DefaultDirectory);
39 | while (dwBuffer < dwSize)
40 | dwBuffer += 0x100;
41 |
42 | PWCHAR Out = calloc(1, dwBuffer);
43 | if (Out == NULL) {
44 | *SymSearchPath = NULL;
45 | return E_OUTOFMEMORY;
46 | }
47 |
48 | // Assemble the whole string now
49 | HRESULT Result = StringCbPrintfW(
50 | Out,
51 | dwBuffer,
52 | L"%s*%s*%s\\%s*%s\0",
53 | Sym,
54 | Dll,
55 | (LPWSTR)DefaultDirectory,
56 | Pdb,
57 | Web
58 | );
59 | if (FAILED(Result)) {
60 | free(Out);
61 | *SymSearchPath = NULL;
62 | return E_FAIL;
63 | }
64 |
65 | *SymSearchPath = Out;
66 | return S_OK;
67 | }
68 |
--------------------------------------------------------------------------------
/WKI/WKIUM/inc/callback.h:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: callback.h
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | Abstraction of the Microsoft Debug Interface Access (DIA) SDK.
9 |
10 | In this case this module contains the code for the CCallback COM interface implementation when loading PDB from
11 | a PE EXE file.
12 |
13 | Documentation available at: https://docs.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/debug-interface-access-sdk
14 | Most of the code is based on the Dia2Dump code sample shipped with the MS DIA SDK.
15 | ================================================================================================+*/
16 |
17 | #ifndef __DIA_CALLBACK_H_GUARD__
18 | #define __DIA_CALLBACK_H_GUARD__
19 |
20 | #include
21 |
22 | #include "msdia/inlcude/dia2.h"
23 |
24 | typedef struct DiaCallback {
25 |
26 | // Virtual Table for the callback
27 | CONST_VTBL struct IDiaLoadCallback2* lpVtbl;
28 |
29 | // Reference counter for the AddRef/Release methods
30 | int m_nRefCount;
31 | } DiaCallback;
32 |
33 | ///
34 | /// Dynamically create the callback COM object used by DIA.
35 | ///
36 | HRESULT STDMETHODCALLTYPE
37 | _Must_inspect_result_
38 | _Success_(return == S_OK)
39 | DiaCallbackHelper(
40 | _In_ BOOLEAN Initialise,
41 | _Inout_ PVOID * *Callback
42 | );
43 |
44 | #endif // !__DIA_CALLBACK_H_GUARD__
--------------------------------------------------------------------------------
/WKI/WKIUM/inc/dirutil.h:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: dirutil.h
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | Windows Directory utility code.
9 | Used to change directory to the "PDB" folder and get the correct symbol server search path.
10 | ================================================================================================+*/
11 |
12 | #ifndef __DIA_DIRUTIL_H_GUARD__
13 | #define __DIA_DIRUTIL_H_GUARD__
14 |
15 | #include
16 |
17 | ///
18 | /// Utility function to get the proper symbol server address to download PDB.
19 | ///
20 | NTSTATUS STDMETHODCALLTYPE
21 | _Must_inspect_result_
22 | GetSymSrvSearchPath(
23 | _Out_ PWCHAR* SymSearchPath
24 | );
25 |
26 | #endif // !__DIA_DIRUTIL_H_GUARD__
27 |
--------------------------------------------------------------------------------
/WKI/WKIUM/inc/interface.h:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: interface.h
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | Abstraction of the Microsoft Debug Interface Access (DIA) SDK.
9 |
10 | Documentation available at: https://docs.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/debug-interface-access-sdk
11 | Most of the code is based on the Dia2Dump code sample shipped with the MS DIA SDK.
12 | ================================================================================================+*/
13 |
14 | #ifndef __DIA_INTERFACE_H_GUARD__
15 | #define __DIA_INTERFACE_H_GUARD__
16 |
17 | #include
18 |
19 | #include "msdia/inlcude/dia2.h"
20 | #include "msdia/inlcude/cvconst.h"
21 |
22 | #include "callback.h"
23 | #include "dirutil.h"
24 |
25 | // Type definition of the "DllGetClassObject" routine from the msdiaXXX.dll module.
26 | typedef HRESULT(STDMETHODCALLTYPE* TDllGetClassObject)(
27 | _In_ REFCLSID rclsid,
28 | _In_ REFIID riid,
29 | _Out_ LPVOID* ppv
30 | );
31 |
32 | ///
33 | /// Simple structure to store all the information
34 | ///
35 | typedef struct _PUBLIC_SYMBOL {
36 | DWORD dwTag;
37 | DWORD dwRVA;
38 | DWORD dwOff;
39 | DWORD dwSeg;
40 | BSTR Name;
41 | } PUBLIC_SYMBOL, * PPUBLIC_SYMBOL;
42 |
43 |
44 | ///
45 | /// Initialise the COM runtime and IDiaDataSource interface.
46 | ///
47 | HRESULT STDMETHODCALLTYPE
48 | _Must_inspect_result_
49 | _Success_(return == S_OK)
50 | DiaInitialise(
51 | _In_ PWCHAR DllName
52 | );
53 |
54 |
55 | ///
56 | /// Uninitialise the COM runtime and general cleanup.
57 | ///
58 | VOID STDMETHODCALLTYPE DiaUninitialise();
59 |
60 |
61 | ///
62 | /// Load the data from the PDB file provided.
63 | ///
64 | HRESULT STDMETHODCALLTYPE
65 | _Must_inspect_result_
66 | _Success_(return == S_OK)
67 | DiaLoadDataFromPdb(
68 | _In_ PWCHAR FilePath
69 | );
70 |
71 |
72 | ///
73 | /// Parse the PDB file to find all symbols requested.
74 | ///
75 | HRESULT STDMETHODCALLTYPE
76 | _Must_inspect_result_
77 | _Success_(return == S_OK)
78 | DiaFindPublicSymbols(
79 | _In_ PUBLIC_SYMBOL PublicSymbols[],
80 | _In_ DWORD Elements
81 | );
82 |
83 | #endif // !__DIA_INTERFACE_H_GUARD__
--------------------------------------------------------------------------------
/WKI/WKIUM/inc/msdia/inlcude/diacreate.h:
--------------------------------------------------------------------------------
1 | // diacreate.h - creation helper functions for DIA initialization
2 | //-----------------------------------------------------------------
3 | //
4 | // Copyright Microsoft Corporation. All Rights Reserved.
5 | //
6 | //---------------------------------------------------------------
7 | #ifndef _DIACREATE_H_
8 | #define _DIACREATE_H_
9 |
10 | //
11 | // Create a dia data source object from the dia dll (by dll name - does not access the registry).
12 | //
13 |
14 | HRESULT STDMETHODCALLTYPE NoRegCoCreate(const __wchar_t* dllName,
15 | REFCLSID rclsid,
16 | REFIID riid,
17 | void** ppv);
18 |
19 | #ifndef _NATIVE_WCHAR_T_DEFINED
20 | #ifdef __cplusplus
21 |
22 | HRESULT STDMETHODCALLTYPE NoRegCoCreate(const wchar_t* dllName,
23 | REFCLSID rclsid,
24 | REFIID riid,
25 | void** ppv)
26 | {
27 | return NoRegCoCreate((const __wchar_t*)dllName, rclsid, riid, ppv);
28 | }
29 |
30 | #endif
31 | #endif
32 |
33 |
34 |
35 | //
36 | // Create a dia data source object from the dia dll (looks up the class id in the registry).
37 | //
38 | HRESULT STDMETHODCALLTYPE NoOleCoCreate(REFCLSID rclsid,
39 | REFIID riid,
40 | void** ppv);
41 |
42 | #endif
--------------------------------------------------------------------------------
/WKI/WKIUM/inc/registry.h:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: registry.h
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | Windows Registry related routines. Used to create and store symbols for access from the kernel driver.
9 | ================================================================================================+*/
10 |
11 | #ifndef __KI_REGISTRY_H_GUARD__
12 | #define __KI_REGISTRY_H_GUARD__
13 |
14 | #include
15 | #include
16 | #include
17 |
18 | #include "interface.h"
19 |
20 | // Base registry key
21 | #define REGISTRY_BASE_KEY L"SOFTWARE\\WKI"
22 |
23 | #define REGISTRY_ROUTINES_KEY L"Routines"
24 | #define REGISTRY_SYMBOLS_KEY L"Symbols"
25 | #define REGISTRY_STRUCTS_KEY L"Structs"
26 |
27 | // Dodgy macro to make the code less bloated
28 | #define RtlCreateOrOpenKey(Status, hKey, SubKey, hResult) \
29 | Status = RegCreateKeyExW(hKey, SubKey, 0x00, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, hResult, NULL); \
30 | if (Status != ERROR_SUCCESS) { RtlGetErrorMessageW((DWORD)Status); RegistryUninitialise(); return E_FAIL; }
31 |
32 | ///
33 | /// Get OS Build number and initialise Windows Registry keys.
34 | ///
35 | HRESULT STDMETHODCALLTYPE
36 | _Must_inspect_result_
37 | _Success_(return == S_OK) RegistryInitialise(
38 | VOID
39 | );
40 |
41 |
42 | ///
43 | /// Internal cleanup of all handles and memory.
44 | ///
45 | VOID STDMETHODCALLTYPE RegistryUninitialise(
46 | VOID
47 | );
48 |
49 |
50 | ///
51 | /// Add symbols to the windows registry.
52 | ///
53 | HRESULT STDMETHODCALLTYPE RegistryAddSymbols(
54 | _In_ PUBLIC_SYMBOL Symbols[],
55 | _In_ DWORD Entries
56 | );
57 |
58 | #endif // !__KI_REGISTRY_H_GUARD__
59 |
--------------------------------------------------------------------------------
/WKI/WKIUM/interface.c:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: interface.c
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | Abstraction of the Microsoft Debug Interface Access (DIA) SDK.
9 |
10 | Documentation available at: https://docs.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/debug-interface-access-sdk
11 | Most of the code is based on the Dia2Dump code sample shipped with the MS DIA SDK.
12 | ================================================================================================+*/
13 |
14 | #include
15 | #include
16 |
17 | #include "inc/interface.h"
18 |
19 | // e6756135-1e65-4d17-8576-610761398c3c
20 | CONST CLSID CLSID_DiaSource = {
21 | 0xe6756135, 0x1e65, 0x4d17, { 0x85, 0x76, 0x61, 0x07, 0x61, 0x39, 0x8c, 0x3c }
22 | };
23 |
24 | // 79F1BB5F-B66E-48e5-B6A9-1545C323CA3D
25 | CONST IID IID_IDiaDataSource = {
26 | 0x79F1BB5F, 0xB66E, 0x48e5, { 0xB6, 0xA9, 0x15, 0x45, 0xC3, 0x23, 0xCA, 0x3D }
27 | };
28 |
29 | // Global Data Source COM interface
30 | IDiaDataSource* g_DataSource = NULL;
31 |
32 | // Global Session COM interface
33 | IDiaSession* g_Session = NULL;
34 |
35 | // Global Symbol COM interface
36 | IDiaSymbol* g_GlobalSymbol = NULL;
37 |
38 | // Global Callback COM interface
39 | IDiaLoadCallback2* g_Callback = NULL;
40 |
41 |
42 | // Tags returned by Dia
43 | const wchar_t* const rgTags[] = {
44 | L"(SymTagNull)", // SymTagNull
45 | L"Executable (Global)", // SymTagExe
46 | L"Compiland", // SymTagCompiland
47 | L"CompilandDetails", // SymTagCompilandDetails
48 | L"CompilandEnv", // SymTagCompilandEnv
49 | L"Function", // SymTagFunction
50 | L"Block", // SymTagBlock
51 | L"Data", // SymTagData
52 | L"Annotation", // SymTagAnnotation
53 | L"Label", // SymTagLabel
54 | L"PublicSymbol", // SymTagPublicSymbol
55 | L"UserDefinedType", // SymTagUDT
56 | L"Enum", // SymTagEnum
57 | L"FunctionType", // SymTagFunctionType
58 | L"PointerType", // SymTagPointerType
59 | L"ArrayType", // SymTagArrayType
60 | L"BaseType", // SymTagBaseType
61 | L"Typedef", // SymTagTypedef
62 | L"BaseClass", // SymTagBaseClass
63 | L"Friend", // SymTagFriend
64 | L"FunctionArgType", // SymTagFunctionArgType
65 | L"FuncDebugStart", // SymTagFuncDebugStart
66 | L"FuncDebugEnd", // SymTagFuncDebugEnd
67 | L"UsingNamespace", // SymTagUsingNamespace
68 | L"VTableShape", // SymTagVTableShape
69 | L"VTable", // SymTagVTable
70 | L"Custom", // SymTagCustom
71 | L"Thunk", // SymTagThunk
72 | L"CustomType", // SymTagCustomType
73 | L"ManagedType", // SymTagManagedType
74 | L"Dimension", // SymTagDimension
75 | L"CallSite", // SymTagCallSite
76 | L"InlineSite", // SymTagInlineSite
77 | L"BaseInterface", // SymTagBaseInterface
78 | L"VectorType", // SymTagVectorType
79 | L"MatrixType", // SymTagMatrixType
80 | L"HLSLType", // SymTagHLSLType
81 | L"Caller", // SymTagCaller,
82 | L"Callee", // SymTagCallee,
83 | L"Export", // SymTagExport,
84 | L"HeapAllocationSite", // SymTagHeapAllocationSite
85 | L"CoffGroup", // SymTagCoffGroup
86 | L"Inlinee", // SymTagInlinee
87 | };
88 |
89 |
90 | _Use_decl_annotations_
91 | HRESULT STDMETHODCALLTYPE DiaInitialise(
92 | _In_ PWCHAR DllName
93 | ) {
94 | // Check if already initialised
95 | HRESULT Result = S_OK;
96 | if (g_DataSource != NULL)
97 | return Result;
98 |
99 | // Initialise COM runtime
100 | if (!SUCCEEDED(CoInitialize(NULL)))
101 | return E_FAIL;
102 |
103 | // Load the module
104 | HMODULE hModule = LoadLibraryExW(DllName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
105 | if (hModule == NULL)
106 | return E_FAIL;
107 |
108 | // Get exported routine
109 | TDllGetClassObject DllGetClassObject = (TDllGetClassObject)GetProcAddress(hModule, "DllGetClassObject");
110 | if (DllGetClassObject == NULL)
111 | return GetLastError();
112 |
113 | // Create Instance of the IDiaDataSource COM interface
114 | IClassFactory* ClassFactory = NULL;
115 | if (SUCCEEDED(DllGetClassObject(&CLSID_DiaSource, &IID_IClassFactory, (LPVOID*)&ClassFactory))) {
116 | Result = ClassFactory->lpVtbl->CreateInstance(ClassFactory, NULL, &IID_IDiaDataSource, &g_DataSource);
117 | if (SUCCEEDED(Result))
118 | ClassFactory->lpVtbl->AddRef(ClassFactory);
119 | return Result;
120 | }
121 | else {
122 | HRESULT Result = GetLastError();
123 | if (Result > 0x00)
124 | Result |= REASON_LEGACY_API;
125 | return Result;
126 | }
127 | }
128 |
129 |
130 | _Use_decl_annotations_
131 | VOID STDMETHODCALLTYPE DiaUninitialise() {
132 | if (g_GlobalSymbol != NULL) {
133 | g_GlobalSymbol->lpVtbl->Release(g_GlobalSymbol);
134 | g_GlobalSymbol = NULL;
135 | }
136 |
137 | if (g_Session != NULL) {
138 | g_Session->lpVtbl->Release(g_Session);
139 | g_Session = NULL;
140 | }
141 |
142 | if (g_DataSource != NULL) {
143 | g_DataSource->lpVtbl->Release(g_DataSource);
144 | g_DataSource = NULL;
145 | }
146 |
147 | if (g_Callback != NULL) {
148 | g_Callback->lpVtbl->Release(g_Callback);
149 | g_Callback = NULL;
150 | }
151 |
152 | CoUninitialize();
153 | }
154 |
155 |
156 | _Use_decl_annotations_
157 | HRESULT STDMETHODCALLTYPE DiaLoadDataFromPdb(
158 | _In_ PWCHAR FilePath
159 | ) {
160 | // Check if already initialised
161 | if (g_DataSource == NULL)
162 | return E_FAIL;
163 | HRESULT Result = S_OK;
164 |
165 | // Extract the file extension from the path
166 | PWCHAR FileExtension = calloc(1, MAX_PATH * sizeof(WCHAR));
167 | if (FileExtension == NULL)
168 | return E_OUTOFMEMORY;
169 | _wsplitpath_s(FilePath, NULL, 0, NULL, 0, NULL, 0, FileExtension, MAX_PATH);
170 |
171 | // File is a ".PDB"
172 | if (!_wcsicmp(FileExtension, L".pdb")) {
173 | free(FileExtension);
174 |
175 | Result = g_DataSource->lpVtbl->loadDataFromPdb(g_DataSource, FilePath);
176 | if (FAILED(Result)) {
177 | wprintf(L"[-] Failed to load data from the PDB file (%08X).\r\n", Result);
178 | return Result;
179 | }
180 | }
181 | // File is a ".EXE"
182 | else if (!_wcsicmp(FileExtension, L".exe")) {
183 | free(FileExtension);
184 |
185 | // Create the callback COM implementation
186 | if (FAILED(DiaCallbackHelper(TRUE, (PVOID)&g_Callback))) {
187 | wprintf(L"[-] Failed to create the DIA Callback.\r\n");
188 | return E_FAIL;
189 | }
190 | g_Callback->lpVtbl->AddRef(g_Callback);
191 |
192 | // Forge the Symbol search path
193 | PWCHAR SymSearchPath = NULL;
194 | if (FAILED(GetSymSrvSearchPath(&SymSearchPath))) {
195 | g_Callback->lpVtbl->Release(g_Callback);
196 | return E_FAIL;
197 | }
198 |
199 | // Load the PDB from Microsoft symbol server
200 | Result = g_DataSource->lpVtbl->loadDataForExe(
201 | g_DataSource,
202 | FilePath,
203 | SymSearchPath,
204 | (PVOID)g_Callback
205 | );
206 |
207 | free(SymSearchPath);
208 | if (FAILED(Result)) {
209 | wprintf(L"[-] Failed to load PDB file (%08X).\r\n", Result);
210 | g_Callback->lpVtbl->Release(g_Callback);
211 | return Result;
212 | }
213 | }
214 |
215 | // Open session to access symbols
216 | Result = g_DataSource->lpVtbl->openSession(g_DataSource, &g_Session);
217 | if (FAILED(Result)) {
218 | wprintf(L"[-] Failed to open session (%08X).\r\n", Result);
219 | return Result;
220 | }
221 |
222 | // Get the global scope
223 | Result = g_Session->lpVtbl->get_globalScope(g_Session, &g_GlobalSymbol);
224 | if (FAILED(Result)) {
225 | wprintf(L"[-] Failed to get global scope (%08X).\r\n", Result);
226 | return Result;
227 | }
228 |
229 | return Result;
230 | }
231 |
232 |
233 | _Use_decl_annotations_
234 | HRESULT STDMETHODCALLTYPE DiaFindPublicSymbols(
235 | _In_ PUBLIC_SYMBOL PublicSymbols[],
236 | _In_ DWORD Elements
237 | ) {
238 | // Check if everything has been properly initialised.
239 | if (g_DataSource == NULL || g_Session == NULL || g_GlobalSymbol == NULL)
240 | return E_FAIL;
241 |
242 | // Enumerates the various symbols contained in the data source.
243 | IDiaEnumSymbols* EnumSymbols = NULL;
244 | HRESULT Result = g_GlobalSymbol->lpVtbl->findChildren(
245 | g_GlobalSymbol,
246 | SymTagPublicSymbol,
247 | NULL,
248 | nsNone,
249 | &EnumSymbols
250 | );
251 | if (FAILED(Result)) {
252 | wprintf(L"[-] Failed to load symbol enumerator (%08X).\r\n", Result);
253 | return Result;
254 | }
255 |
256 | // Parse all symbols
257 | IDiaSymbol* Symbol = NULL;
258 | ULONG celt = 0x00;
259 | while (SUCCEEDED(EnumSymbols->lpVtbl->Next(EnumSymbols, 0x01, &Symbol, &celt)) && (celt == 1)) {
260 |
261 | DWORD dwTag = 0x00;
262 | DWORD dwRVA = 0x00;
263 | DWORD dwOff = 0x00;
264 | DWORD dwSeg = 0x00;
265 | BSTR Name = NULL;
266 |
267 | // Make sure we have a tag for the symbol
268 | if (FAILED(Symbol->lpVtbl->get_symTag(Symbol, &dwTag)))
269 | goto next_symbol;
270 |
271 | // Get the name of the global variable
272 | if (SUCCEEDED(Symbol->lpVtbl->get_name(Symbol, &Name))) {
273 |
274 | // Find the symbol
275 | BOOLEAN Found = FALSE;
276 | DWORD Index = 0x00;
277 | for (DWORD cx = 0x00; cx < Elements; cx++) {
278 | if (wcscmp(PublicSymbols[cx].Name, Name) == 0x00) {
279 | Index = cx;
280 | Found = TRUE;
281 | break;
282 | }
283 | }
284 | if (!Found)
285 | goto next_symbol;
286 |
287 | // Get the Relative Virtual Address (RVA), the offset and section
288 | if (FAILED(Symbol->lpVtbl->get_relativeVirtualAddress(Symbol, &dwRVA)))
289 | dwRVA = 0xFFFFFFFF;
290 | Symbol->lpVtbl->get_addressSection(Symbol, &dwSeg);
291 | Symbol->lpVtbl->get_addressOffset(Symbol, &dwOff);
292 |
293 | PublicSymbols[Index].dwTag = dwTag;
294 | PublicSymbols[Index].dwRVA = dwRVA;
295 | PublicSymbols[Index].dwOff = dwOff;
296 | PublicSymbols[Index].dwSeg = dwSeg;
297 |
298 | // Release current interface
299 | next_symbol:
300 | Symbol->lpVtbl->Release(Symbol);
301 | }
302 | }
303 | EnumSymbols->lpVtbl->Release(EnumSymbols);
304 | return S_OK;
305 | }
306 |
--------------------------------------------------------------------------------
/WKI/WKIUM/main.c:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: main.c
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | Application entry point.
9 | ================================================================================================+*/
10 |
11 | #include
12 | #include
13 |
14 | #include "inc/interface.h"
15 | #include "inc/registry.h"
16 |
17 | // Macro to make the code less bloated
18 | #define EXIT_ON_FAILURE(ex) if (!SUCCEEDED(ex)) { return EXIT_FAILURE; }
19 |
20 | // Macro to add an entry in the intenral symbol table.
21 | #define ADD_TABLE_ENTRY(str) { 0x00, 0x00, 0x00, 0x00, str }
22 |
23 |
24 | ///
25 | /// Sort the symbol table.
26 | ///
27 | VOID SortTable(
28 | _In_ PUBLIC_SYMBOL PublicSymbols[],
29 | _In_ DWORD Elements
30 | ) {
31 | // Sort with segment
32 | for (DWORD cx = 0x00; cx < (Elements - 1); cx++) {
33 | for (DWORD dx = 0x00; dx < (Elements - cx - 1); dx++) {
34 | if (PublicSymbols[dx].dwSeg > PublicSymbols[dx + 1].dwSeg) {
35 |
36 | PUBLIC_SYMBOL Temp = PublicSymbols[dx];
37 | RtlCopyMemory(&Temp, &PublicSymbols[dx], sizeof(PUBLIC_SYMBOL));
38 | RtlCopyMemory(&PublicSymbols[dx], &PublicSymbols[dx + 1], sizeof(PUBLIC_SYMBOL));
39 | RtlCopyMemory(&PublicSymbols[dx + 1], &Temp, sizeof(PUBLIC_SYMBOL));
40 | }
41 | }
42 | }
43 |
44 | // Sort with RVA
45 | for (DWORD cx = 0x00; cx < (Elements - 1); cx++) {
46 | for (DWORD dx = 0x00; dx < (Elements - cx - 1); dx++) {
47 | if (PublicSymbols[dx].dwRVA > PublicSymbols[dx + 1].dwRVA) {
48 |
49 | PUBLIC_SYMBOL Temp = PublicSymbols[dx];
50 | RtlCopyMemory(&Temp, &PublicSymbols[dx], sizeof(PUBLIC_SYMBOL));
51 | RtlCopyMemory(&PublicSymbols[dx], &PublicSymbols[dx + 1], sizeof(PUBLIC_SYMBOL));
52 | RtlCopyMemory(&PublicSymbols[dx + 1], &Temp, sizeof(PUBLIC_SYMBOL));
53 | }
54 | }
55 | }
56 | }
57 |
58 |
59 | ///
60 | /// Application Entry Point.
61 | ///
62 | INT main(VOID) {
63 | // Banner
64 | wprintf(L"=================================================================\r\n");
65 | wprintf(L"Module Name: Windows Kernel Introspection -- UM \r\n");
66 | wprintf(L"Author : Paul L. (@am0nsec) \r\n");
67 | wprintf(L"Origin : https://github.com/am0nsec/wkpe/ \r\n\r\n");
68 | wprintf(L"Tested OS : Windows 10 (20h2) - 19044.1889 \r\n");
69 | wprintf(L"=================================================================\r\n\r\n");
70 |
71 | // Initialise COM runtime and get IDiaDataSource interface.
72 | wprintf(L"[*] Initialise MSDIA \r\n");
73 | EXIT_ON_FAILURE(DiaInitialise(L"msdia140.dll"));
74 |
75 | // Load the data from the PDB
76 | wprintf(L"[*] Open PDB from EXE: C:\\WINDOWS\\System32\\ntoskrnl.exe\r\n");
77 | EXIT_ON_FAILURE(DiaLoadDataFromPdb(L"C:\\WINDOWS\\System32\\ntoskrnl.exe"));
78 |
79 | // Parse all public symbols
80 | PUBLIC_SYMBOL Symbols[] = {
81 | // Memory Manager variables
82 | ADD_TABLE_ENTRY(L"ExPoolTagTables"),
83 | ADD_TABLE_ENTRY(L"PoolTrackTableSize"),
84 | ADD_TABLE_ENTRY(L"ExpPoolBlockShift"),
85 | ADD_TABLE_ENTRY(L"PoolTrackTableExpansion"),
86 | ADD_TABLE_ENTRY(L"PoolTrackTableExpansionSize"),
87 |
88 | // General kernel info
89 | ADD_TABLE_ENTRY(L"KeNumberProcessors")
90 | };
91 | EXIT_ON_FAILURE(DiaFindPublicSymbols(Symbols, _ARRAYSIZE(Symbols)));
92 |
93 | // Display everything to console
94 | SortTable(Symbols, _ARRAYSIZE(Symbols));
95 |
96 | wprintf(L"\r\n");
97 | wprintf(L"Found Segment RVA Offset Name\r\n");
98 | wprintf(L"----- ------- --- ------ ----\r\n");
99 |
100 | DWORD Found = 0x00;
101 | for (DWORD cx = 0x00; cx < _ARRAYSIZE(Symbols); cx++) {
102 | wprintf(L"%s %04X %08X %08X %s\r\n",
103 | Symbols[cx].dwRVA != 0x00 ? L"\033[0;32mY\033[0;37m" : L"\033[0;31mN\033[0;37m",
104 | Symbols[cx].dwSeg,
105 | Symbols[cx].dwRVA,
106 | Symbols[cx].dwOff,
107 | Symbols[cx].Name
108 | );
109 | Found += Symbols[cx].dwRVA != 0x00 ? 1 : 0;
110 | }
111 |
112 | wprintf(L"\r\n");
113 | wprintf(L"[*] Found: %i/%i\r\n", Found, (int)_ARRAYSIZE(Symbols));
114 | wprintf(L"=================================================================\r\n\r\n");
115 |
116 | // Initialise registry module
117 | RegistryInitialise();
118 | RegistryAddSymbols(Symbols, _ARRAYSIZE(Symbols));
119 | RegistryUninitialise();
120 |
121 | // Uninitialise COM runtime and general cleanup
122 | DiaUninitialise();
123 | return EXIT_SUCCESS;
124 | }
--------------------------------------------------------------------------------
/WKI/WKIUM/registry.c:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: registry.c
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | Windows Registry related routines. Used to create and store symbols for access from the kernel driver.
9 | ================================================================================================+*/
10 | #include "inc/registry.h"
11 |
12 | // Handle to the base registry key
13 | HKEY g_BaseKey = INVALID_HANDLE_VALUE;
14 |
15 | // Handle to the key for the current build number
16 | HKEY g_BuilKey = INVALID_HANDLE_VALUE;
17 |
18 | // Handle to the key for the public symbols
19 | HKEY g_Symbols = INVALID_HANDLE_VALUE;
20 |
21 | // Handle to the key for the structures
22 | HKEY g_Structs = INVALID_HANDLE_VALUE;
23 |
24 | // Handle to the key for the routines
25 | HKEY g_Routines = INVALID_HANDLE_VALUE;
26 |
27 | // The OS version string
28 | WCHAR g_VersionString[0x20] = { 0x00 };
29 |
30 |
31 | ///
32 | /// Display message related to an error message.
33 | ///
34 | /// Error id returned by GetLastError.
35 | VOID RtlGetErrorMessageW(
36 | _In_ DWORD dwError
37 | ) {
38 | WCHAR ErrorW[1024] = { 0x00 };
39 | if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0x00, ErrorW, 1024, NULL) != 0x0) {
40 | wprintf(L"Message is \"%s\"\n", ErrorW);
41 | }
42 | else {
43 | wprintf(L"Failed! Error code %d\n", GetLastError());
44 | }
45 | }
46 |
47 |
48 | ///
49 | /// Get the OS build number.
50 | ///
51 | HRESULT RtlGetOSVersion() {
52 | LSTATUS Status = ERROR_SUCCESS;
53 |
54 | // Get the major build version
55 | DWORD CurrentMajorVersionNumber = 0x00;
56 | DWORD CurrentMajorVersionNumberSize = sizeof(DWORD);
57 | Status = RegGetValueA(
58 | HKEY_LOCAL_MACHINE,
59 | "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
60 | "CurrentMajorVersionNumber",
61 | RRF_RT_REG_DWORD,
62 | NULL,
63 | &CurrentMajorVersionNumber,
64 | &CurrentMajorVersionNumberSize
65 | );
66 | if (Status != ERROR_SUCCESS) {
67 | RtlGetErrorMessageW((DWORD)GetLastError());
68 | return E_FAIL;
69 | }
70 |
71 | // Get the current build number
72 | char CurrentBuildNumber[0x10] = { 0x00 };
73 | DWORD CurrentBuildNumberSize = ARRAYSIZE(CurrentBuildNumber);
74 | Status = RegGetValueA(
75 | HKEY_LOCAL_MACHINE,
76 | "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
77 | "CurrentBuildNumber",
78 | RRF_RT_REG_SZ,
79 | NULL,
80 | CurrentBuildNumber,
81 | &CurrentBuildNumberSize
82 | );
83 | if (Status != ERROR_SUCCESS) {
84 | RtlGetErrorMessageW((DWORD)GetLastError());
85 | return E_FAIL;
86 | }
87 |
88 | // Get the update build revision
89 | DWORD UpdateBuildRevision = 0x00;
90 | DWORD UpdateBuildRevisionSize = sizeof(DWORD);
91 | Status = RegGetValueA(
92 | HKEY_LOCAL_MACHINE,
93 | "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
94 | "UBR",
95 | RRF_RT_REG_DWORD,
96 | NULL,
97 | &UpdateBuildRevision,
98 | &UpdateBuildRevisionSize
99 | );
100 | if (Status != ERROR_SUCCESS) {
101 | RtlGetErrorMessageW((DWORD)GetLastError());
102 | return E_FAIL;
103 | }
104 |
105 | // Build the version string
106 | HRESULT Result = StringCbPrintfW(
107 | g_VersionString,
108 | sizeof(WCHAR) * 0x20,
109 | L"%u.%c%c%c%c%c.%u\0",
110 | CurrentMajorVersionNumber,
111 | CurrentBuildNumber[0],
112 | CurrentBuildNumber[1],
113 | CurrentBuildNumber[2],
114 | CurrentBuildNumber[3],
115 | CurrentBuildNumber[4],
116 | UpdateBuildRevision
117 | );
118 | return Result;
119 | }
120 |
121 |
122 | ///
123 | /// Get the DJBT hash of a string.
124 | ///
125 | DWORD RtlGetHash(BSTR String) {
126 | // Allocate memory
127 | LPSTR MultiByte = calloc(0x01, 0x100);
128 | if (MultiByte == NULL)
129 | return 0x00;
130 |
131 | // Convert from wide-character to multibyte-character
132 | SIZE_T Count = 0x00;
133 | wcstombs_s(&Count, MultiByte, 0x100, String, lstrlenW(String));
134 | if (Count == 0x00) {
135 | free(MultiByte);
136 | return 0x00;
137 | }
138 |
139 | // Calculate the djb2 hash
140 | DWORD Hash = 0x1505;
141 | INT c = 0x0000;
142 | LPSTR d = MultiByte;
143 |
144 | while (c = *d++)
145 | Hash = ((Hash << 5) + Hash) + c;
146 |
147 | free(MultiByte);
148 | return Hash;
149 | }
150 |
151 |
152 | _Use_decl_annotations_
153 | HRESULT STDMETHODCALLTYPE RegistryInitialise(
154 | VOID
155 | ) {
156 | // Check if already initialised
157 | if (g_BaseKey != INVALID_HANDLE_VALUE)
158 | return S_OK;
159 |
160 | // Check if key exist
161 | LSTATUS Status = ERROR_SUCCESS;
162 | RtlCreateOrOpenKey(Status, HKEY_LOCAL_MACHINE, REGISTRY_BASE_KEY, &g_BaseKey);
163 |
164 | // Get OS Version
165 | if (FAILED(RtlGetOSVersion())) {
166 | RtlGetErrorMessageW((DWORD)GetLastError());
167 | return E_FAIL;
168 | }
169 | wprintf(L"[*] OS Build: %s\r\n", g_VersionString);
170 |
171 | // Open or create the key with the version string
172 | RtlCreateOrOpenKey(Status, g_BaseKey, g_VersionString, &g_BuilKey);
173 |
174 | // Open or create the keys for:
175 | // - Public Symbols
176 | // - Structures
177 | // - Routines
178 | RtlCreateOrOpenKey(Status, g_BuilKey, REGISTRY_SYMBOLS_KEY, &g_Symbols);
179 | RtlCreateOrOpenKey(Status, g_BuilKey, REGISTRY_STRUCTS_KEY, &g_Structs);
180 | RtlCreateOrOpenKey(Status, g_BuilKey, REGISTRY_ROUTINES_KEY, &g_Routines);
181 |
182 | return S_OK;
183 | }
184 |
185 |
186 | _Use_decl_annotations_
187 | VOID STDMETHODCALLTYPE RegistryUninitialise(
188 | VOID
189 | ) {
190 | if (g_BaseKey != INVALID_HANDLE_VALUE)
191 | RegCloseKey(g_BaseKey);
192 | if (g_BuilKey != INVALID_HANDLE_VALUE)
193 | RegCloseKey(g_BuilKey);
194 | if (g_Symbols != INVALID_HANDLE_VALUE)
195 | RegCloseKey(g_Symbols);
196 | if (g_Structs != INVALID_HANDLE_VALUE)
197 | RegCloseKey(g_Structs);
198 | if (g_Routines != INVALID_HANDLE_VALUE)
199 | RegCloseKey(g_Routines);
200 |
201 | memset(g_VersionString, 0x00, 0x20);
202 | }
203 |
204 |
205 | _Use_decl_annotations_
206 | HRESULT STDMETHODCALLTYPE RegistryAddSymbols(
207 | _In_ PUBLIC_SYMBOL Symbols[],
208 | _In_ DWORD Entries
209 | ) {
210 | if (g_Symbols == INVALID_HANDLE_VALUE || Entries == 0x00 || Symbols == NULL)
211 | return E_FAIL;
212 |
213 | // Parse all the entries
214 | DWORD ValidEntries = 0x00;
215 | for (DWORD cx = 0x00; cx < Entries; cx++) {
216 |
217 | // If symbol has not been resolved, go to next entry
218 | if (Symbols[cx].dwRVA == 0x00)
219 | continue;
220 | ValidEntries++;
221 |
222 | // Create new key
223 | HKEY CurrentKey = INVALID_HANDLE_VALUE;
224 | LSTATUS Status = ERROR_SUCCESS;
225 | RtlCreateOrOpenKey(Status, g_Symbols, Symbols[cx].Name, &CurrentKey);
226 | wprintf(L"\\HKLM\\%s\\%s\\%s\\%s\r\n", REGISTRY_BASE_KEY, g_VersionString, REGISTRY_SYMBOLS_KEY, Symbols[cx].Name);
227 |
228 | // Add information
229 | RegSetKeyValueW(CurrentKey, NULL, L"RVA", REG_DWORD, &Symbols[cx].dwRVA, sizeof(DWORD));
230 | RegSetKeyValueW(CurrentKey, NULL, L"OFF", REG_DWORD, &Symbols[cx].dwOff, sizeof(DWORD));
231 | RegSetKeyValueW(CurrentKey, NULL, L"SEG", REG_DWORD, &Symbols[cx].dwSeg, sizeof(DWORD));
232 |
233 | // Get the hash of the name
234 | DWORD Hash = RtlGetHash(Symbols[cx].Name);
235 | RegSetKeyValueW(CurrentKey, NULL, L"DJB", REG_DWORD, &Hash, sizeof(DWORD));
236 |
237 | RegCloseKey(CurrentKey);
238 | }
239 |
240 | // Set the total number of entries
241 | RegSetKeyValueW(g_BuilKey, NULL, L"NumberOfSymbols", REG_DWORD, &ValidEntries, sizeof(DWORD));
242 | return S_OK;
243 | }
--------------------------------------------------------------------------------
/WKI/WKIUM/tools/msdia140.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/am0nsec/wkpe/708844b6bf7d2893b1a023f13ae4906e19868ef2/WKI/WKIUM/tools/msdia140.dll
--------------------------------------------------------------------------------
/WKI/WKIUM/tools/symsrv.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/am0nsec/wkpe/708844b6bf7d2893b1a023f13ae4906e19868ef2/WKI/WKIUM/tools/symsrv.dll
--------------------------------------------------------------------------------
/mpp/mpp-client/device.hpp:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: device.hpp
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | Wrapper for MMP kernel device access.
9 | ================================================================================================+*/
10 |
11 | #ifndef __MPPCLIENT_DEVICE_H_GUARD__
12 | #define __MPPCLIENT_DEVICE_H_GUARD__
13 |
14 | #include
15 |
16 | constexpr ULONG MppAddImageName() {
17 | return (ULONG)CTL_CODE(\
18 | 0x8000, /* DeviceType */\
19 | 0x800, /* Function */\
20 | METHOD_IN_DIRECT, /* Method */\
21 | FILE_ANY_ACCESS /* Access */\
22 | );
23 | }
24 |
25 | constexpr ULONG MppRemoveImageName() {
26 | return (ULONG)CTL_CODE(\
27 | 0x8000, /* DeviceType */\
28 | 0x801, /* Function */\
29 | METHOD_IN_DIRECT, /* Method */\
30 | FILE_ANY_ACCESS /* Access */\
31 | );
32 | }
33 |
34 | constexpr ULONG MppInitialiseKernelRoutines() {
35 | return (ULONG)CTL_CODE(\
36 | 0x8000, /* DeviceType */\
37 | 0x802, /* Function */\
38 | METHOD_IN_DIRECT, /* Method */\
39 | FILE_ANY_ACCESS /* Access */\
40 | );
41 | }
42 |
43 | constexpr WCHAR AmsiImageName[] = L"amsi.dll\0";
44 |
45 | /// @brief Data structure for `MppInitialiseKernelRoutines` input buffer IOCTL.
46 | typedef struct _MPP_KERNEL_ROUTINES_OFFSETS {
47 | DWORD MiAddSecureEntry;
48 | DWORD MiObtainReferencedVadEx;
49 | DWORD MiUnlockAndDereferenceVad;
50 | } MPP_KERNEL_ROUTINES_OFFSETS, *PMPP_KERNEL_ROUTINES_OFFSETS;
51 |
52 | /// @brief Data structure for `MppRemoveImageName` input buffer IOCTL.
53 | typedef struct _MPP_REMOVE_IMAGE_NAME {
54 | SIZE_T Size;
55 | WCHAR Name[MAX_PATH];
56 | } MPP_REMOVE_IMAGE_NAME, *PMPP_REMOVE_IMAGE_NAME;
57 |
58 | /// @brief Data structure for `MppAddImageName` input buffer IOCTL.
59 | typedef struct _MPP_ADD_IMAGE_NAME {
60 | SIZE_T Size;
61 | WCHAR Name[MAX_PATH];
62 | } MPP_ADD_IMAGE_NAME, *PMPP_ADD_IMAGE_NAME;
63 |
64 | /// @brief Class wrapper to manage kernel device driver.
65 | class CDeviceManager {
66 | public:
67 | CDeviceManager() {
68 | // Open handle to the device driver
69 | this->hDevice = ::CreateFileA(
70 | "\\\\.\\MppDrv",
71 | (GENERIC_READ | GENERIC_WRITE),
72 | 0x00,
73 | NULL,
74 | OPEN_EXISTING,
75 | 0x00,
76 | NULL
77 | );
78 | }
79 |
80 | /// @brief Check if handle to kernel device driver is valid.
81 | _inline BOOLEAN
82 | _Must_inspect_result_
83 | IsDeviceReady() {
84 | return this->hDevice != INVALID_HANDLE_VALUE;
85 | }
86 |
87 | /// @brief IOCTL to send offset of kernel routines.
88 | /// @param KernelRoutines List of offsets of kernel routines.
89 | BOOLEAN
90 | _Must_inspect_result_
91 | SendKernelRoutinesOffsets(
92 | _In_ MPP_KERNEL_ROUTINES_OFFSETS KernelRoutines
93 | ) {
94 | DWORD ReturnedBytes = 0x00;
95 | BOOL Success = ::DeviceIoControl(
96 | this->hDevice,
97 | MppInitialiseKernelRoutines(),
98 | &KernelRoutines,
99 | sizeof(MPP_KERNEL_ROUTINES_OFFSETS),
100 | nullptr,
101 | 0x00,
102 | &ReturnedBytes,
103 | nullptr
104 | );
105 | if (!Success) {
106 | ::printf("Failed to initialise kernel routines (%d).\r\n", ::GetLastError());
107 | return Success;
108 | }
109 | }
110 |
111 | /// @brief IOCTL to add a new image name.
112 | /// @param ImageName Structure used to add a new image name.
113 | BOOLEAN
114 | _Must_inspect_result_
115 | SendAddImageName(
116 | _In_ MPP_ADD_IMAGE_NAME ImageName
117 | ) {
118 | DWORD ReturnedBytes = 0x00;
119 | BOOL Success = ::DeviceIoControl(
120 | this->hDevice,
121 | MppAddImageName(),
122 | &ImageName,
123 | sizeof(MPP_ADD_IMAGE_NAME),
124 | nullptr,
125 | 0x00,
126 | &ReturnedBytes,
127 | nullptr
128 | );
129 | if (!Success) {
130 | ::printf("Failed to add new image name (%d).\r\n", ::GetLastError());
131 | return Success;
132 | }
133 | }
134 |
135 | private:
136 | /// @brief Handle to kernel device driver.
137 | HANDLE hDevice{ INVALID_HANDLE_VALUE };
138 |
139 | };
140 |
141 | #endif // !__MPPCLIENT_DEVICE_H_GUARD__
142 |
143 |
144 |
--------------------------------------------------------------------------------
/mpp/mpp-client/main.cpp:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: main.cpp
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | Memory Patching Protection (MPP) Kernel Device Driver User-Mode Client.
9 | ================================================================================================+*/
10 |
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | #include "sym.hpp"
18 | #include "device.hpp"
19 |
20 |
21 | INT32 main(
22 | _In_ int argc,
23 | _In_ const char* argv[]
24 | ) {
25 | // Banner
26 | wprintf(L"=================================================================\r\n");
27 | wprintf(L"Module Name: Memory Patching Protection (MPP) User-Mode Client \r\n");
28 | wprintf(L"Author : Paul L. (@am0nsec) \r\n");
29 | wprintf(L"Origin : https://github.com/am0nsec/wkpe/ \r\n");
30 | wprintf(L"Tested OS : Windows 10 (20h2) - 19044.2006 \r\n");
31 | wprintf(L"=================================================================\r\n");
32 |
33 | // Download PDB file of ntoskrnl
34 | auto SymDatabase = std::make_unique("C:\\Windows\\System32\\ntoskrnl.exe");
35 |
36 | if (FAILED(SymDatabase->DownloadFromServer()))
37 | return EXIT_FAILURE;
38 |
39 | // Add symbols to find
40 | SymDatabase->Symbols.insert(std::make_pair("MiAddSecureEntry", 0x00));
41 | SymDatabase->Symbols.insert(std::make_pair("MiObtainReferencedVadEx", 0x00));
42 | SymDatabase->Symbols.insert(std::make_pair("MiUnlockAndDereferenceVad", 0x00));
43 |
44 | // Find symbols
45 | ::printf("\r\n[+] Searching symbols ...\r\n");
46 | if (FAILED(SymDatabase->LoadAndCheckSym()))
47 | return EXIT_FAILURE;
48 | ::printf("[+] Searching symbols ... OK\r\n");
49 |
50 | // Send information to the kernel driver
51 | auto DeviceManager = std::make_unique();
52 | if (!DeviceManager->IsDeviceReady()) {
53 | ::printf("[-] Failed to open handle to kernel device.\r\n");
54 | return EXIT_FAILURE;
55 | }
56 |
57 | MPP_KERNEL_ROUTINES_OFFSETS KernelRoutines = {
58 | .MiAddSecureEntry = SymDatabase->Symbols["MiAddSecureEntry"],
59 | .MiObtainReferencedVadEx = SymDatabase->Symbols["MiObtainReferencedVadEx"],
60 | .MiUnlockAndDereferenceVad = SymDatabase->Symbols["MiUnlockAndDereferenceVad"]
61 | };
62 | DeviceManager->SendKernelRoutinesOffsets(KernelRoutines);
63 |
64 | // Add AMSI DLL
65 | MPP_ADD_IMAGE_NAME ImageName = {
66 | .Size = ARRAYSIZE(AmsiImageName) * sizeof(WCHAR)
67 | };
68 | RtlCopyMemory(ImageName.Name, AmsiImageName, ImageName.Size);
69 | DeviceManager->SendAddImageName(ImageName);
70 |
71 | return EXIT_SUCCESS;
72 | }
--------------------------------------------------------------------------------
/mpp/mpp-client/mpp-client.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {76a08b15-abf0-48d7-9ae7-5c5a16a6dbee}
25 | mppclient
26 | 10.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v143
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v143
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v143
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v143
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | Level3
76 | true
77 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
78 | true
79 |
80 |
81 | Console
82 | true
83 |
84 |
85 |
86 |
87 | Level3
88 | true
89 | true
90 | true
91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
92 | true
93 |
94 |
95 | Console
96 | true
97 | true
98 | true
99 |
100 |
101 |
102 |
103 | Level3
104 | true
105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
106 | true
107 | stdcpp20
108 |
109 |
110 | Console
111 | true
112 |
113 |
114 |
115 |
116 | Level3
117 | true
118 | true
119 | true
120 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
121 | true
122 |
123 |
124 | Console
125 | true
126 | true
127 | true
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/mpp/mpp-client/mpp-client.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/mpp/mpp-client/sym.cpp:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: sym.cpp
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | Windows PDB symbols Extractor.
9 | Based on: https://github.com/Coldzer0/TinyPDBParser
10 | ================================================================================================+*/
11 |
12 | #include "sym.hpp"
13 |
14 |
15 | _Use_decl_annotations_
16 | HRESULT CSymDatabase::DownloadFromServer(
17 | VOID
18 | ) {
19 |
20 | // Make sure path exists
21 | if (!std::filesystem::exists(this->FilePath)) {
22 | ::printf("File does not exist: %s\r\n", this->FilePath.c_str());
23 | return E_UNEXPECTED;
24 | }
25 |
26 | // Get the content of the EXE file
27 | std::ifstream Executable(
28 | this->FilePath,
29 | std::ios::binary | std::ios::ate
30 | );
31 | SIZE_T ExecutableSize = Executable.tellg();
32 |
33 | // Set pointer to beginning of file
34 | Executable.seekg(0x00, std::ios::beg);
35 |
36 | // Allocate memory
37 | PVOID ModuleBase = ::malloc(ExecutableSize);
38 | if (ModuleBase == nullptr) {
39 | ::printf("Unable to allocate memory for executable: %d\r\n", ::GetLastError());
40 | return E_OUTOFMEMORY;
41 | }
42 |
43 | // Start reading the file
44 | if (!Executable.read((char*)ModuleBase, ExecutableSize)) {
45 | ::free(ModuleBase);
46 | ::printf("Unable to read content of the file\r\n");
47 | return E_UNEXPECTED;
48 | }
49 |
50 | // Get debug directory
51 | PIMAGE_DATA_DIRECTORY DataDirectory = this->GetImageDataDirectory(ModuleBase);
52 | if (DataDirectory == nullptr) {
53 | ::free(ModuleBase);
54 | ::printf("Failed to get debug directory for executable\r\n");
55 | return E_UNEXPECTED;
56 | }
57 |
58 | // Get offset to the data within the executable
59 | DWORD Offset = this->GetVirtualAddress(
60 | ModuleBase,
61 | DataDirectory->VirtualAddress
62 | );
63 | if (Offset == 0x00) {
64 | ::free(ModuleBase);
65 | ::printf("Failed to get debug directory for executable\r\n");
66 | return E_UNEXPECTED;
67 | }
68 |
69 | // Parse all debug entries
70 | PIMAGE_DEBUG_DIRECTORY DebugEntry = reinterpret_cast(
71 | reinterpret_cast(ModuleBase)
72 | + Offset
73 | );
74 | for (DWORD cx = 0x00; cx < (DataDirectory->Size / sizeof(IMAGE_DEBUG_DIRECTORY)); cx++) {
75 |
76 | // Check if the type of debug is contains what is required
77 | if (DebugEntry->Type != IMAGE_DEBUG_TYPE_CODEVIEW) {
78 | DebugEntry++;
79 | continue;
80 | }
81 |
82 | // Get the CodeView Header
83 | PCV_HEADER CvHeader = reinterpret_cast(
84 | reinterpret_cast(ModuleBase)
85 | + DebugEntry->PointerToRawData
86 | );
87 |
88 | // Check if PDB 2.00 or PDB 7.00
89 | switch (CvHeader->CvSignature) {
90 | case PDB70: {
91 | PCV_INFO_PDB70 Info = reinterpret_cast(CvHeader);
92 |
93 | // Get basic information
94 | this->PdbName = reinterpret_cast(Info->PdbFileName);
95 |
96 | // Build the server URL to the PDB
97 | this->ServerPath =
98 | std::string("http://msdl.microsoft.com/download/symbols/")
99 | + this->PdbName
100 | + "/"
101 | + this->GuidToString(&Info->Signature)
102 | + std::to_string(Info->Age)
103 | + "/"
104 | + this->PdbName;
105 | break;
106 | }
107 | case PDB20: {
108 | PCV_INFO_PDB20 Info = reinterpret_cast(CvHeader);
109 |
110 | // Get basic information
111 | this->PdbName = reinterpret_cast(Info->PdbFileName);
112 |
113 | // Build the server URL to the PDB
114 | char AgeString[10];
115 | ::snprintf(AgeString, sizeof(AgeString), "%08X%x", Info->Signature, Info->Age);
116 |
117 | this->ServerPath =
118 | std::string("http://msdl.microsoft.com/download/symbols/")
119 | + this->PdbName
120 | + "/"
121 | + std::string(AgeString)
122 | + "/"
123 | + this->PdbName;
124 |
125 | break;
126 | }
127 | default: {
128 | ::free(ModuleBase);
129 | ::printf("Unsupported CodeView signature %d.\n\r", CvHeader->CvSignature);
130 | return E_UNEXPECTED;
131 | }
132 | }
133 |
134 | // Display Information
135 | ::printf("[+] PDB Information\r\n");
136 | ::printf(" %s\r\n", this->ServerPath.c_str());
137 | ::free(ModuleBase);
138 |
139 | // Update the
140 | this->OutputPath =
141 | this->CurrentDirectory + "\\" + this->PdbName;
142 |
143 | // Download file
144 | HRESULT hr = URLDownloadToFileA(
145 | nullptr,
146 | this->ServerPath.c_str(),
147 | this->OutputPath.c_str(),
148 | BINDF_GETNEWESTVERSION,
149 | nullptr
150 | );
151 | if (FAILED(hr))
152 | ::printf("[-] Failed to download PDB from symbol server: %d\r\n", ::GetLastError());
153 | else
154 | ::printf("[+] PDB successfully downloaded from symbol server.\r\n");
155 |
156 | return hr;
157 | }
158 |
159 | // Cleanup and exit
160 | if (ModuleBase != nullptr)
161 | ::free(ModuleBase);
162 | return E_UNEXPECTED;
163 | }
164 |
165 |
166 | _Use_decl_annotations_
167 | HRESULT CSymDatabase::LoadAndCheckSym(
168 | VOID
169 | ) {
170 |
171 | // Open handle to current process
172 | HANDLE hProcess = INVALID_HANDLE_VALUE;
173 | hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, false, GetCurrentProcessId());
174 | if (hProcess == INVALID_HANDLE_VALUE) {
175 | ::printf("Unable to open handle to current process: %d\r\n", ::GetLastError());
176 | return E_UNEXPECTED;
177 | }
178 |
179 | // Initialise symbol library
180 | bool SymbolsPathInit = ::SymInitialize(
181 | hProcess,
182 | this->OutputPath.c_str(),
183 | false
184 | );
185 | if (!SymbolsPathInit) {
186 | ::printf("Unable to initialise symbol library: %d\r\n", ::GetLastError());
187 |
188 | ::CloseHandle(hProcess);
189 | return E_UNEXPECTED;
190 | }
191 |
192 | // Load PDB file
193 | ::SymSetOptions(SymGetOptions() | SYMOPT_CASE_INSENSITIVE | SYMOPT_LOAD_ANYTHING);
194 | ::SymSetSearchPath(hProcess, this->OutputPath.c_str());
195 |
196 | SIZE_T SymBase = ::SymLoadModule(
197 | hProcess,
198 | nullptr,
199 | "C:\\Windows\\System32\\ntoskrnl.exe",
200 | nullptr,
201 | 0x00,
202 | 0x00
203 | );
204 | if (SymBase == 0x00) {
205 | ::printf("Failed to load module: %d\r\n", ::GetLastError());
206 |
207 | ::CloseHandle(hProcess);
208 | return E_UNEXPECTED;
209 | }
210 |
211 | // Set symbol enumeration callback
212 | HRESULT hr = S_OK;
213 | BOOL Success = SymEnumSymbols(
214 | hProcess,
215 | SymBase,
216 | nullptr,
217 | (PSYM_ENUMERATESYMBOLS_CALLBACK)CSymDatabase::EnumSymCallback,
218 | this
219 | );
220 | if (!Success) {
221 | ::printf("Failed to set symbol enumeration callback: %d\r\n", ::GetLastError());
222 |
223 | ::CloseHandle(hProcess);
224 | return E_UNEXPECTED;
225 | }
226 |
227 | // Cleanup and return
228 | ::CloseHandle(hProcess);
229 | return S_OK;
230 | }
231 |
232 |
233 | _Use_decl_annotations_
234 | PIMAGE_DATA_DIRECTORY CSymDatabase::GetImageDataDirectory(
235 | _In_ LPVOID ModuleBase
236 | ) {
237 | if (ModuleBase == nullptr)
238 | return nullptr;
239 |
240 | // DOS Header
241 | PIMAGE_DOS_HEADER DosHeader = reinterpret_cast(ModuleBase);
242 | if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
243 | return nullptr;
244 |
245 | // NT Header
246 | PIMAGE_NT_HEADERS NtHeaders = reinterpret_cast(
247 | reinterpret_cast(ModuleBase)
248 | + DosHeader->e_lfanew
249 | );
250 | if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
251 | return nullptr;
252 |
253 | // Get data directory
254 | if (!NtHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64
255 | || !NtHeaders->FileHeader.Machine == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
256 | ::printf("Unsupported executable machine type: %d\r\n", NtHeaders->FileHeader.Machine);
257 | return nullptr;
258 | }
259 |
260 | return &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
261 | }
262 |
263 |
264 | _Use_decl_annotations_
265 | DWORD CSymDatabase::GetVirtualAddress(
266 | _In_ LPVOID ModuleBase,
267 | _In_ DWORD RelativeAddress
268 | ) {
269 | // DOS Header
270 | PIMAGE_DOS_HEADER DosHeader = reinterpret_cast(ModuleBase);
271 | if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
272 | return 0x00;
273 |
274 | // NT Header
275 | PIMAGE_NT_HEADERS NtHeaders = reinterpret_cast(
276 | reinterpret_cast(ModuleBase)
277 | + DosHeader->e_lfanew
278 | );
279 | if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
280 | return 0x00;
281 |
282 | PIMAGE_SECTION_HEADER Section = IMAGE_FIRST_SECTION(NtHeaders);
283 | for (int i = 0; i < NtHeaders->FileHeader.NumberOfSections; ++i) {
284 | if (RelativeAddress >= Section->VirtualAddress
285 | && RelativeAddress < (Section->VirtualAddress + Section->SizeOfRawData)) {
286 | return (Section->PointerToRawData + (RelativeAddress - Section->VirtualAddress));
287 | }
288 |
289 | Section++;
290 | }
291 | return 0x00;
292 | }
293 |
294 |
295 | _Use_decl_annotations_
296 | _inline std::string CSymDatabase::GuidToString(
297 | _In_ GUID* Guid
298 | ) {
299 | char Str[37]; // 32 hex chars + 4 hyphens + null terminator
300 | snprintf(Str, sizeof(Str),
301 | "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X",
302 | Guid->Data1,
303 | Guid->Data2,
304 | Guid->Data3,
305 | Guid->Data4[0],
306 | Guid->Data4[1],
307 | Guid->Data4[2],
308 | Guid->Data4[3],
309 | Guid->Data4[4],
310 | Guid->Data4[5],
311 | Guid->Data4[6],
312 | Guid->Data4[7]
313 | );
314 | return Str;
315 | }
316 |
317 |
318 | _Use_decl_annotations_
319 | BOOLEAN CSymDatabase::EnumSymCallback(
320 | _In_ PSYMBOL_INFO pSymInfo,
321 | _In_ ULONG SymbolSize,
322 | _In_ PVOID UserContext
323 | ) {
324 | if (pSymInfo->NameLen == 0)
325 | return true;
326 | auto This = reinterpret_cast(UserContext);
327 |
328 | for (auto& kvp : This->Symbols) {
329 | if (std::string(pSymInfo->Name).find(kvp.first) == 0
330 | && ::strlen(pSymInfo->Name) == kvp.first.length()
331 | ) {
332 | kvp.second = pSymInfo->Address - pSymInfo->ModBase;
333 | printf(" - 0x%x : %s\r\n",
334 | (DWORD)(pSymInfo->Address - pSymInfo->ModBase),
335 | (LPSTR)pSymInfo->Name
336 | );
337 | }
338 | }
339 |
340 | return true;
341 | }
--------------------------------------------------------------------------------
/mpp/mpp-client/sym.hpp:
--------------------------------------------------------------------------------
1 | /*+================================================================================================
2 | Module Name: sym.hpp
3 | Author : Paul L. (@am0nsec)
4 | Origin : https://github.com/am0nsec/wkpe/
5 | Copyright : This project has been released under the GNU Public License v3 license.
6 |
7 | Abstract:
8 | Windows PDB symbols Extractor.
9 | Based on: https://github.com/Coldzer0/TinyPDBParser
10 | ================================================================================================+*/
11 |
12 | #ifndef __MPPCLIENT_SYM_H_GUARD__
13 | #define __MPPCLIENT_SYM_H_GUARD__
14 |
15 | #pragma comment(lib, "urlmon")
16 | #pragma comment(lib, "imagehlp")
17 |
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include