HyperDbg Debugger
Loading...
Searching...
No Matches
UserAccess.c File Reference

Access and parse user-mode components of binaries. More...

#include "pch.h"

Functions

BOOLEAN UserAccessAllocateAndGetImagePathFromProcessId (HANDLE ProcessId, PUNICODE_STRING ProcessImageName, UINT32 SizeOfImageNameToBeAllocated)
 Get the image path from process Id.
 
BOOLEAN UserAccessGetPebFromProcessId (HANDLE ProcessId, PUINT64 Peb)
 Get the process's PEB from process Id.
 
BOOLEAN UserAccessGetBaseAndEntrypointOfMainModuleIfLoadedInVmxRoot (PPEB PebAddress, BOOLEAN Is32Bit, PUINT64 BaseAddress, PUINT64 Entrypoint)
 If the target process's main module is loaded, it fills the Entrypoint and the BaseAddress.
 
BOOLEAN UserAccessPrintLoadedModulesX64 (PEPROCESS Proc, BOOLEAN OnlyCountModules, PUINT32 ModulesCount, PUSERMODE_LOADED_MODULE_SYMBOLS ModulesList, UINT32 SizeOfBufferForModulesList)
 Gets the loaded modules details from PEB.
 
BOOLEAN UserAccessPrintLoadedModulesX86 (PEPROCESS Proc, BOOLEAN OnlyCountModules, PUINT32 ModulesCount, PUSERMODE_LOADED_MODULE_SYMBOLS ModulesList, UINT32 SizeOfBufferForModulesList)
 Gets the loaded modules details from PEB (x86)
 
BOOLEAN UserAccessPrintLoadedModulesX86_2 (PEPROCESS Proc)
 Print loaded modules details from PEB.
 
BOOLEAN UserAccessIsWow64ProcessByEprocess (PEPROCESS SourceProcess, PBOOLEAN Is32Bit)
 Detects whether process is 32-bit or 64-bit by using EPROCESS pointer.
 
BOOLEAN UserAccessIsWow64Process (HANDLE ProcessId, PBOOLEAN Is32Bit)
 Detects whether process is 32-bit or 64-bit.
 
BOOLEAN UserAccessGetLoadedModules (PUSERMODE_LOADED_MODULE_DETAILS ProcessLoadedModuleRequest, UINT32 BufferSize)
 Get details about loaded modules.
 
BOOLEAN UserAccessCheckForLoadedModuleDetails (UINT32 CoreId)
 Checks whether the loaded module is available or not.
 

Detailed Description

Access and parse user-mode components of binaries.

Author
Sina Karvandi (sina@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)

Access to Portable Executables

Version
0.1
Date
2021-12-24

Function Documentation

◆ UserAccessAllocateAndGetImagePathFromProcessId()

BOOLEAN UserAccessAllocateAndGetImagePathFromProcessId ( HANDLE ProcessId,
PUNICODE_STRING ProcessImageName,
UINT32 SizeOfImageNameToBeAllocated )

Get the image path from process Id.

This function should be called in vmx non-root for size 512 is enough, if the size is not enough it returns FALSE it's up to the user to deallocate ProcessImageName.Buffer

Parameters
ProcessId
ProcessImageName
SizeOfImageNameToBeAllocated
Returns
BOOLEAN
31{
32 NTSTATUS Status;
33 ULONG ReturnedLength;
34 ULONG BufferLength;
35 HANDLE ProcessHandle;
36 PVOID Buffer;
37 PEPROCESS EProcess;
38 PUNICODE_STRING ImageName;
39
40 //
41 // This eliminates the possibility of the IDLE Thread/Process
42 //
43 PAGED_CODE();
44
45 Status = PsLookupProcessByProcessId(ProcessId, &EProcess);
46
47 if (NT_SUCCESS(Status))
48 {
49 Status = ObOpenObjectByPointer(EProcess, 0, NULL, 0, 0, KernelMode, &ProcessHandle);
50
51 if (!NT_SUCCESS(Status))
52 {
53 LogError("Err, cannot get the process object (%08x)", Status);
54 return FALSE;
55 }
56
57 ObDereferenceObject(EProcess);
58 }
59 else
60 {
61 //
62 // Probably, the process id is wrong!
63 //
64 return FALSE;
65 }
66
68 {
69 return FALSE;
70 }
71
72 //
73 // Query the actual size of the process path
74 //
75 Status = g_ZwQueryInformationProcess(ProcessHandle,
76 ProcessImageFileName,
77 NULL, // Buffer
78 0, // Buffer size
79 &ReturnedLength);
80
81 if (Status != STATUS_INFO_LENGTH_MISMATCH)
82 {
83 //
84 // ZwQueryInformationProcess failed
85 //
86 return FALSE;
87 }
88
89 //
90 // Check there is enough space to store the actual process path when it is found
91 // If not return FALSE
92 //
93 BufferLength = ReturnedLength - sizeof(UNICODE_STRING);
94
95 if (SizeOfImageNameToBeAllocated < BufferLength)
96 {
97 return FALSE;
98 }
99
100 //
101 // Allocate a temporary buffer to store the path name
102 //
103 Buffer = PlatformMemAllocateZeroedNonPagedPool(ReturnedLength);
104
105 if (Buffer == NULL)
106 {
107 return FALSE;
108 }
109
110 //
111 // Retrieve the process path from the handle to the process
112 //
113 Status = g_ZwQueryInformationProcess(ProcessHandle,
114 ProcessImageFileName,
115 Buffer,
116 ReturnedLength,
117 &ReturnedLength);
118
119 if (NT_SUCCESS(Status))
120 {
121 //
122 // Copy the path name
123 //
124 ImageName = (PUNICODE_STRING)Buffer;
125
126 //
127 // Allocate UNICODE_STRING
128 //
129 ProcessImageName->Length = 0;
130 ProcessImageName->MaximumLength = (USHORT)SizeOfImageNameToBeAllocated;
131 ProcessImageName->Buffer = (PWSTR)PlatformMemAllocateZeroedNonPagedPool(SizeOfImageNameToBeAllocated);
132
133 if (ProcessImageName->Buffer == NULL)
134 {
135 return FALSE;
136 }
137
138 RtlZeroMemory(ProcessImageName->Buffer, SizeOfImageNameToBeAllocated);
139
140 //
141 // Copy path to the buffer
142 //
143 RtlCopyUnicodeString(ProcessImageName, ImageName);
144
145 //
146 // Free the temp buffer which stored the path
147 //
148 PlatformMemFreePool(Buffer);
149
150 return TRUE;
151 }
152 else
153 {
154 //
155 // There was an error in ZwQueryInformationProcess
156 // Free the temp buffer which stored the path
157 //
158 PlatformMemFreePool(Buffer);
159 return FALSE;
160 }
161}
unsigned short USHORT
Definition BasicTypes.h:36
#define TRUE
Definition BasicTypes.h:55
#define FALSE
Definition BasicTypes.h:54
unsigned long ULONG
Definition BasicTypes.h:37
#define LogError(format,...)
Log in the case of error.
Definition HyperDbgHyperLogIntrinsics.h:113
VOID PlatformMemFreePool(PVOID BufferAddress)
Free (dellocate) a non-paged buffer.
Definition Mem.c:86
PVOID PlatformMemAllocateZeroedNonPagedPool(SIZE_T NumberOfBytes)
Allocate a non-paged buffer (zeroed)
Definition Mem.c:69
ZwQueryInformationProcess g_ZwQueryInformationProcess
Address of ZwQueryInformationProcess.
Definition UserAccess.h:187
struct _UNICODE_STRING * PUNICODE_STRING
struct _UNICODE_STRING UNICODE_STRING
Definition casting.cpp:25
USHORT Length
Definition casting.cpp:26
USHORT MaximumLength
Definition casting.cpp:27
PWSTR Buffer
Definition casting.cpp:28

◆ UserAccessCheckForLoadedModuleDetails()

BOOLEAN UserAccessCheckForLoadedModuleDetails ( UINT32 CoreId)

Checks whether the loaded module is available or not.

Parameters
CoreId
Returns
BOOLEAN
855{
856 PUSERMODE_DEBUGGING_PROCESS_DETAILS ProcessDebuggingDetail;
857 UINT64 BaseAddress = (UINT64)NULL;
858 UINT64 Entrypoint = (UINT64)NULL;
859 PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId];
860
861 //
862 // Check if the callback needs to be handled or not
863 //
865 {
866 return FALSE;
867 }
868
869 //
870 // Find the thread debugging detail structure
871 //
872 ProcessDebuggingDetail =
874
875 //
876 // Check if we find the debugging detail of the thread or not
877 //
878 if (ProcessDebuggingDetail == NULL)
879 {
880 return FALSE;
881 }
882
883 if (ProcessDebuggingDetail->EntrypointOfMainModule == (UINT64)NULL &&
884 ProcessDebuggingDetail->PebAddressToMonitor != (PVOID)NULL &&
885 CheckAccessValidityAndSafety((UINT64)ProcessDebuggingDetail->PebAddressToMonitor, sizeof(CHAR)) &&
887 ProcessDebuggingDetail->Is32Bit,
888 &BaseAddress,
889 &Entrypoint))
890 {
891 if (Entrypoint != (UINT64)NULL)
892 {
893 ProcessDebuggingDetail->BaseAddressOfMainModule = BaseAddress;
894 ProcessDebuggingDetail->EntrypointOfMainModule = Entrypoint;
895
896 // LogInfo("Base: %016llx \t EntryPoint: %016llx", BaseAddress, Entrypoint);
897
898 //
899 // Handle entrypoint interception
900 //
902
903 return TRUE;
904 }
905 }
906
907 //
908 // Not available
909 //
910 return FALSE;
911}
BOOLEAN CheckAccessValidityAndSafety(UINT64 TargetAddress, UINT32 Size)
Check the safety to access the memory.
Definition AddressCheck.c:156
PUSERMODE_DEBUGGING_PROCESS_DETAILS AttachingFindProcessDebuggingDetailsByProcessId(UINT32 ProcessId)
Find user-mode debugging details for threads by process Id.
Definition Attaching.c:187
VOID AttachingHandleEntrypointInterception(PROCESSOR_DEBUGGING_STATE *DbgState)
Handle the interception of finding the entrypoint on attaching to user-mode process.
Definition Attaching.c:436
unsigned __int64 UINT64
Definition BasicTypes.h:21
char CHAR
Definition BasicTypes.h:31
#define HANDLE_TO_UINT32(_var)
Definition MetaMacros.h:39
BOOLEAN UserAccessGetBaseAndEntrypointOfMainModuleIfLoadedInVmxRoot(PPEB PebAddress, BOOLEAN Is32Bit, PUINT64 BaseAddress, PUINT64 Entrypoint)
If the target process's main module is loaded, it fills the Entrypoint and the BaseAddress.
Definition UserAccess.c:245
PROCESSOR_DEBUGGING_STATE * g_DbgState
Save the state and variables related to debugging on each to logical core.
Definition Global.h:17
BOOLEAN g_IsWaitingForUserModeProcessEntryToBeCalled
Whether the thread attaching mechanism is waiting for #DB or not.
Definition Global.h:158
Saves the debugger state.
Definition State.h:165
Description of each active thread in user-mode attaching mechanism.
Definition Attaching.h:49
UINT64 BaseAddressOfMainModule
Definition Attaching.h:59
BOOLEAN Is32Bit
Definition Attaching.h:62
UINT64 EntrypointOfMainModule
Definition Attaching.h:58
PVOID PebAddressToMonitor
Definition Attaching.h:52

◆ UserAccessGetBaseAndEntrypointOfMainModuleIfLoadedInVmxRoot()

BOOLEAN UserAccessGetBaseAndEntrypointOfMainModuleIfLoadedInVmxRoot ( PPEB PebAddress,
BOOLEAN Is32Bit,
PUINT64 BaseAddress,
PUINT64 Entrypoint )

If the target process's main module is loaded, it fills the Entrypoint and the BaseAddress.

This function is safe to be called in vmx non-root

Parameters
PebAddress
Is32Bit
BaseAddress
Entrypoint
Returns
BOOLEAN
249{
250 if (Is32Bit)
251 {
252 PEB_LDR_DATA32 Ldr32 = {0};
253 PEB32 Peb32 = {0};
254 PPEB_LDR_DATA32 LdrAddress32 = NULL;
255
256 MemoryMapperReadMemorySafeOnTargetProcess((UINT64)PebAddress, &Peb32, sizeof(PEB32));
257
258 LdrAddress32 = (PPEB_LDR_DATA32)Peb32.Ldr;
259
260 if (!LdrAddress32)
261 {
262 return FALSE;
263 }
264
266
267 PLIST_ENTRY32 List = (PLIST_ENTRY32)Ldr32.InLoadOrderModuleList.Flink;
268
269 PLDR_DATA_TABLE_ENTRY32 EntryAddress = CONTAINING_RECORD(List, LDR_DATA_TABLE_ENTRY32, InLoadOrderLinks);
270 LDR_DATA_TABLE_ENTRY32 Entry = {0};
271
273
274 if (Entry.DllBase == NULL_ZERO || Entry.EntryPoint == NULL_ZERO)
275 {
276 return FALSE;
277 }
278 else
279 {
280 *BaseAddress = Entry.DllBase;
281 *Entrypoint = Entry.EntryPoint;
282
283 return TRUE;
284 }
285 }
286 else
287 {
288 PPEB_LDR_DATA LdrAddress = NULL;
289 PEB_LDR_DATA Ldr = {0};
290
291 PEB Peb = {0};
292
293 MemoryMapperReadMemorySafeOnTargetProcess((UINT64)PebAddress, &Peb, sizeof(PEB));
294
295 LdrAddress = (PPEB_LDR_DATA)Peb.Ldr;
296
297 if (!LdrAddress)
298 {
299 return FALSE;
300 }
301
303
304 PLIST_ENTRY List = (PLIST_ENTRY)Ldr.ModuleListLoadOrder.Flink;
305
306 PLDR_DATA_TABLE_ENTRY EntryAddress = CONTAINING_RECORD(List, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
307 LDR_DATA_TABLE_ENTRY Entry = {0};
308
310
311 // LogInfo("base: %llx | entry: %llx", Entry.DllBase, Entry.EntryPoint);
312
313 if (Entry.DllBase == NULL || Entry.EntryPoint == NULL)
314 {
315 return FALSE;
316 }
317 else
318 {
319 *BaseAddress = (UINT64)Entry.DllBase;
320 *Entrypoint = (UINT64)Entry.EntryPoint;
321
322 return TRUE;
323 }
324 }
325}
#define NULL_ZERO
Definition BasicTypes.h:51
_Use_decl_annotations_ BOOLEAN MemoryMapperReadMemorySafeOnTargetProcess(UINT64 VaAddressToRead, PVOID BufferToSaveMemory, SIZE_T SizeToRead)
Read memory safely by mapping the buffer on the target process memory (It's a wrapper)
Definition MemoryMapper.c:1120
struct _PEB_LDR_DATA32 * PPEB_LDR_DATA32
struct _PEB_LDR_DATA * PPEB_LDR_DATA
NULL()
Definition test-case-generator.py:530
LDR Data Table 32-bit.
Definition UserAccess.h:122
ULONG DllBase
Definition UserAccess.h:126
ULONG EntryPoint
Definition UserAccess.h:127
LDR Data Table 64-bit.
Definition UserAccess.h:143
PVOID EntryPoint
Definition UserAccess.h:148
PVOID DllBase
Definition UserAccess.h:147
PEB 32-bit.
Definition UserAccess.h:82
ULONG Ldr
Definition UserAccess.h:89
LDR Data 32-bit.
Definition UserAccess.h:108
LIST_ENTRY32 InLoadOrderModuleList
Definition UserAccess.h:112
PEB LDR Data.
Definition UserAccess.h:23
LIST_ENTRY ModuleListLoadOrder
Definition UserAccess.h:27
PEB 64-bit.
Definition UserAccess.h:55
PPEB_LDR_DATA Ldr
Definition UserAccess.h:60

◆ UserAccessGetLoadedModules()

BOOLEAN UserAccessGetLoadedModules ( PUSERMODE_LOADED_MODULE_DETAILS ProcessLoadedModuleRequest,
UINT32 BufferSize )

Get details about loaded modules.

This function should be called in vmx non-root

Parameters
ProcessLoadedModuleRequest
BufferSize
Returns
BOOLEAN
780{
781 PEPROCESS SourceProcess;
782 BOOLEAN Is32Bit;
783
784 if (PsLookupProcessByProcessId((HANDLE)ProcessLoadedModuleRequest->ProcessId, &SourceProcess) != STATUS_SUCCESS)
785 {
786 //
787 // if the process not found
788 //
789 ProcessLoadedModuleRequest->Result = DEBUGGER_ERROR_INVALID_PROCESS_ID;
790 return FALSE;
791 }
792
793 ObDereferenceObject(SourceProcess);
794
795 //
796 // check whether the target process is 32-bit or 64-bit
797 //
798 if (!UserAccessIsWow64Process((HANDLE)ProcessLoadedModuleRequest->ProcessId, &Is32Bit))
799 {
800 //
801 // Unable to detect whether it's 32-bit or 64-bit
802 //
804 return FALSE;
805 }
806
807 //
808 // Indicate that the process is x86
809 //
810 ProcessLoadedModuleRequest->Is32Bit = Is32Bit;
811
812 if (Is32Bit)
813 {
814 //
815 // x86 process, walk x86 module list
816 //
817 if (UserAccessPrintLoadedModulesX86(SourceProcess,
818 ProcessLoadedModuleRequest->OnlyCountModules,
819 &ProcessLoadedModuleRequest->ModulesCount,
820 (USERMODE_LOADED_MODULE_SYMBOLS *)((UINT64)ProcessLoadedModuleRequest + sizeof(USERMODE_LOADED_MODULE_DETAILS)),
821 BufferSize - sizeof(USERMODE_LOADED_MODULE_DETAILS)))
822 {
823 ProcessLoadedModuleRequest->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
824 return TRUE;
825 }
826 }
827 else
828 {
829 //
830 // x64 process, walk x64 module list
831 //
832 if (UserAccessPrintLoadedModulesX64(SourceProcess,
833 ProcessLoadedModuleRequest->OnlyCountModules,
834 &ProcessLoadedModuleRequest->ModulesCount,
835 (USERMODE_LOADED_MODULE_SYMBOLS *)((UINT64)ProcessLoadedModuleRequest + sizeof(USERMODE_LOADED_MODULE_DETAILS)),
836 BufferSize - sizeof(USERMODE_LOADED_MODULE_DETAILS)))
837 {
838 ProcessLoadedModuleRequest->Result = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
839 return TRUE;
840 }
841 }
842
844 return FALSE;
845}
UCHAR BOOLEAN
Definition BasicTypes.h:39
#define DEBUGGER_ERROR_UNABLE_TO_GET_MODULES_OF_THE_PROCESS
error, unable to get modules
Definition ErrorCodes.h:374
#define DEBUGGER_ERROR_INVALID_PROCESS_ID
error, the process id is invalid
Definition ErrorCodes.h:220
#define DEBUGGER_OPERATION_WAS_SUCCESSFUL
General value to indicate that the operation or request was successful.
Definition ErrorCodes.h:23
BOOLEAN UserAccessPrintLoadedModulesX86(PEPROCESS Proc, BOOLEAN OnlyCountModules, PUINT32 ModulesCount, PUSERMODE_LOADED_MODULE_SYMBOLS ModulesList, UINT32 SizeOfBufferForModulesList)
Gets the loaded modules details from PEB (x86)
Definition UserAccess.c:488
BOOLEAN UserAccessPrintLoadedModulesX64(PEPROCESS Proc, BOOLEAN OnlyCountModules, PUINT32 ModulesCount, PUSERMODE_LOADED_MODULE_SYMBOLS ModulesList, UINT32 SizeOfBufferForModulesList)
Gets the loaded modules details from PEB.
Definition UserAccess.c:339
BOOLEAN UserAccessIsWow64Process(HANDLE ProcessId, PBOOLEAN Is32Bit)
Detects whether process is 32-bit or 64-bit.
Definition UserAccess.c:753
Definition Symbols.h:47
UINT32 Result
Definition Symbols.h:52
UINT32 ModulesCount
Definition Symbols.h:51
UINT32 ProcessId
Definition Symbols.h:48
BOOLEAN Is32Bit
Definition Symbols.h:50
BOOLEAN OnlyCountModules
Definition Symbols.h:49
Definition Symbols.h:39

◆ UserAccessGetPebFromProcessId()

BOOLEAN UserAccessGetPebFromProcessId ( HANDLE ProcessId,
PUINT64 Peb )

Get the process's PEB from process Id.

This function should be called in vmx non-root

Parameters
ProcessId
Peb
Returns
BOOLEAN
173{
174 NTSTATUS Status;
175 ULONG ReturnedLength;
176 HANDLE ProcessHandle;
177 PEPROCESS EProcess;
178 PPEB ProcessPeb;
179 PROCESS_BASIC_INFORMATION ProcessBasicInfo = {0};
180
181 //
182 // This eliminates the possibility of the IDLE Thread/Process
183 //
184 PAGED_CODE();
185
186 Status = PsLookupProcessByProcessId(ProcessId, &EProcess);
187
188 if (NT_SUCCESS(Status))
189 {
190 Status = ObOpenObjectByPointer(EProcess, 0, NULL, 0, 0, KernelMode, &ProcessHandle);
191
192 if (!NT_SUCCESS(Status))
193 {
194 LogError("Err, cannot get the process object (%08x)", Status);
195 return FALSE;
196 }
197
198 ObDereferenceObject(EProcess);
199 }
200 else
201 {
202 //
203 // Probably, the process id is wrong!
204 //
205 return FALSE;
206 }
207
208 if (g_ZwQueryInformationProcess == NULL)
209 {
210 return FALSE;
211 }
212
213 //
214 // Retrieve the process path from the handle to the process
215 //
216 Status = g_ZwQueryInformationProcess(ProcessHandle,
217 ProcessBasicInformation,
218 &ProcessBasicInfo,
219 sizeof(PROCESS_BASIC_INFORMATION),
220 &ReturnedLength);
221
222 if (NT_SUCCESS(Status))
223 {
224 ProcessPeb = ProcessBasicInfo.PebBaseAddress;
225
226 *Peb = (UINT64)ProcessPeb;
227 return TRUE;
228 }
229
230 return FALSE;
231}

◆ UserAccessIsWow64Process()

BOOLEAN UserAccessIsWow64Process ( HANDLE ProcessId,
PBOOLEAN Is32Bit )

Detects whether process is 32-bit or 64-bit.

This function should be called in vmx non-root

Parameters
ProcessId
Is32Bit
Returns
BOOLEAN
754{
755 PEPROCESS SourceProcess;
756
757 if (PsLookupProcessByProcessId(ProcessId, &SourceProcess) != STATUS_SUCCESS)
758 {
759 //
760 // if the process not found
761 //
762 return FALSE;
763 }
764
765 ObDereferenceObject(SourceProcess);
766
767 return UserAccessIsWow64ProcessByEprocess(SourceProcess, Is32Bit);
768}
BOOLEAN UserAccessIsWow64ProcessByEprocess(PEPROCESS SourceProcess, PBOOLEAN Is32Bit)
Detects whether process is 32-bit or 64-bit by using EPROCESS pointer.
Definition UserAccess.c:711

◆ UserAccessIsWow64ProcessByEprocess()

BOOLEAN UserAccessIsWow64ProcessByEprocess ( PEPROCESS SourceProcess,
PBOOLEAN Is32Bit )

Detects whether process is 32-bit or 64-bit by using EPROCESS pointer.

This function should be called in vmx non-root

Parameters
SourceProcess
Is32Bit
Returns
BOOLEAN
712{
713 if (g_PsGetProcessWow64Process == NULL || g_PsGetProcessPeb == NULL)
714 {
715 return FALSE;
716 }
717
718 if (g_PsGetProcessWow64Process(SourceProcess))
719 {
720 //
721 // x86 process, walk x86 module list
722 //
723
724 *Is32Bit = TRUE;
725
726 return TRUE;
727 }
728 else if (g_PsGetProcessPeb(SourceProcess))
729 {
730 //
731 // x64 process, walk x64 module list
732 //
733 *Is32Bit = FALSE;
734
735 return TRUE;
736 }
737 else
738 {
739 return FALSE;
740 }
741}
PsGetProcessPeb g_PsGetProcessPeb
Address of PsGetProcessPeb.
Definition UserAccess.h:193
PsGetProcessWow64Process g_PsGetProcessWow64Process
Address of PsGetProcessWow64Process.
Definition UserAccess.h:199

◆ UserAccessPrintLoadedModulesX64()

BOOLEAN UserAccessPrintLoadedModulesX64 ( PEPROCESS Proc,
BOOLEAN OnlyCountModules,
PUINT32 ModulesCount,
PUSERMODE_LOADED_MODULE_SYMBOLS ModulesList,
UINT32 SizeOfBufferForModulesList )

Gets the loaded modules details from PEB.

This function should be called in vmx non-root

Parameters
Proc
OnlyCountModules
ModulesCount
ModulesList
SizeOfBufferForModulesList
Returns
BOOLEAN
344{
345 KAPC_STATE State;
346 PPEB Peb = NULL;
347 PPEB_LDR_DATA Ldr = NULL;
348 UINT32 CountOfModules = 0;
349 UINT32 CurrentSavedModules = 0;
350 UINT32 TempSize = 0;
351
352 if (g_PsGetProcessPeb == NULL)
353 {
354 return FALSE;
355 }
356
357 //
358 // Process PEB, function is unexported and undocumented
359 //
360 Peb = (PPEB)g_PsGetProcessPeb(Proc);
361
362 if (!Peb)
363 {
364 return FALSE;
365 }
366
367 KeStackAttachProcess(Proc, &State);
368
369 Ldr = (PPEB_LDR_DATA)Peb->Ldr;
370
371 if (!Ldr)
372 {
373 KeUnstackDetachProcess(&State);
374 return FALSE;
375 }
376
377 if (OnlyCountModules)
378 {
379 //
380 // loop the linked list (Computer the size)
381 //
382 for (PLIST_ENTRY List = (PLIST_ENTRY)Ldr->ModuleListLoadOrder.Flink;
383 List != &Ldr->ModuleListLoadOrder;
384 List = (PLIST_ENTRY)List->Flink)
385 {
386 /*
387 PLDR_DATA_TABLE_ENTRY Entry =
388 CONTAINING_RECORD(List, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
389
390 Log("Base: %016llx\tEntryPoint: %016llx\tModule: %ws\tPath: %ws\n",
391 Entry->DllBase,
392 Entry->EntryPoint,
393 Entry->BaseDllName.Buffer,
394 Entry->FullDllName.Buffer);
395 */
396
397 //
398 // Calculate count of modules
399 //
400 CountOfModules++;
401 }
402
403 *ModulesCount = CountOfModules;
404
405 KeUnstackDetachProcess(&State);
406 return TRUE;
407 }
408 else
409 {
410 //
411 // It's not counting the modules, so we compute the number of modules
412 // that can be stored in the buffer by using the size of the buffer
413 //
414 CountOfModules = SizeOfBufferForModulesList / sizeof(USERMODE_LOADED_MODULE_SYMBOLS);
415 }
416
417 //
418 // Walk again to save the buffer
419 //
420 Ldr = (PPEB_LDR_DATA)Peb->Ldr;
421
422 if (!Ldr)
423 {
424 KeUnstackDetachProcess(&State);
425 return FALSE;
426 }
427
428 //
429 // loop the linked list
430 //
431 for (PLIST_ENTRY List = (PLIST_ENTRY)Ldr->ModuleListLoadOrder.Flink;
432 List != &Ldr->ModuleListLoadOrder;
433 List = (PLIST_ENTRY)List->Flink)
434 {
436 CONTAINING_RECORD(List, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
437
438 if (CountOfModules == CurrentSavedModules)
439 {
440 //
441 // Won't continue as the buffer is now full
442 // Generally, we shouldn't be at this stage, only when
443 // a module is just loaded and we didn't allocate enough
444 // memory for it, so it's better to continue
445 //
446 KeUnstackDetachProcess(&State);
447 return TRUE;
448 }
449
450 //
451 // Save the details into the storage
452 //
453 ModulesList[CurrentSavedModules].Entrypoint = (UINT64)Entry->EntryPoint;
454 ModulesList[CurrentSavedModules].BaseAddress = (UINT64)Entry->DllBase;
455
456 //
457 // Copy the path
458 //
459 TempSize = Entry->FullDllName.Length;
460 if (TempSize >= MAX_PATH)
461 {
462 TempSize = MAX_PATH;
463 }
464
465 TempSize = TempSize * 2;
466 memcpy(&ModulesList[CurrentSavedModules].FilePath, Entry->FullDllName.Buffer, TempSize);
467
468 CurrentSavedModules++;
469 }
470
471 KeUnstackDetachProcess(&State);
472
473 return TRUE;
474}
unsigned int UINT32
Definition BasicTypes.h:48
struct _USERMODE_LOADED_MODULE_SYMBOLS USERMODE_LOADED_MODULE_SYMBOLS
struct _PEB * PPEB
UINT64 BaseAddress
Definition Symbols.h:40
UINT64 Entrypoint
Definition Symbols.h:41

◆ UserAccessPrintLoadedModulesX86()

BOOLEAN UserAccessPrintLoadedModulesX86 ( PEPROCESS Proc,
BOOLEAN OnlyCountModules,
PUINT32 ModulesCount,
PUSERMODE_LOADED_MODULE_SYMBOLS ModulesList,
UINT32 SizeOfBufferForModulesList )

Gets the loaded modules details from PEB (x86)

This function should be called in vmx non-root

Parameters
Proc
OnlyCountModules
ModulesCount
ModulesList
SizeOfBufferForModulesList
Returns
BOOLEAN
493{
494 KAPC_STATE State;
495 PPEB32 Peb = NULL;
496 PPEB_LDR_DATA32 Ldr = NULL;
497 UINT32 CountOfModules = 0;
498 UINT32 CurrentSavedModules = 0;
499 UINT32 TempSize = 0;
500
501 if (g_PsGetProcessWow64Process == NULL)
502 {
503 return FALSE;
504 }
505
506 //
507 // Process PEB, function is unexported and undocumented
508 //
510
511 if (!Peb)
512 {
513 return FALSE;
514 }
515
516 KeStackAttachProcess(Proc, &State);
517
518 Ldr = (PPEB_LDR_DATA32)Peb->Ldr;
519
520 if (!Ldr)
521 {
522 KeUnstackDetachProcess(&State);
523 return FALSE;
524 }
525
526 if (OnlyCountModules)
527 {
528 //
529 // loop the linked list (Computer the size)
530 //
531 for (PLIST_ENTRY32 List = (PLIST_ENTRY32)Ldr->InLoadOrderModuleList.Flink;
532 List != &Ldr->InLoadOrderModuleList;
533 List = (PLIST_ENTRY32)List->Flink)
534 {
535 /*
536 PLDR_DATA_TABLE_ENTRY32 Entry =
537 CONTAINING_RECORD(List, LDR_DATA_TABLE_ENTRY32, InLoadOrderLinks);
538 */
539
540 //
541 // Calculate count of modules
542 //
543 CountOfModules++;
544 }
545
546 *ModulesCount = CountOfModules;
547
548 KeUnstackDetachProcess(&State);
549 return TRUE;
550 }
551 else
552 {
553 //
554 // It's not counting the modules, so we compute the number of modules
555 // that can be stored in the buffer by using the size of the buffer
556 //
557 CountOfModules = SizeOfBufferForModulesList / sizeof(USERMODE_LOADED_MODULE_SYMBOLS);
558 }
559
560 //
561 // Walk again to save the buffer
562 //
563 Ldr = (PPEB_LDR_DATA32)Peb->Ldr;
564
565 if (!Ldr)
566 {
567 KeUnstackDetachProcess(&State);
568 return FALSE;
569 }
570
571 //
572 // loop the linked list
573 //
574 for (PLIST_ENTRY32 List = (PLIST_ENTRY32)Ldr->InLoadOrderModuleList.Flink;
575 List != &Ldr->InLoadOrderModuleList;
576 List = (PLIST_ENTRY32)List->Flink)
577 {
579 CONTAINING_RECORD(List, LDR_DATA_TABLE_ENTRY32, InLoadOrderLinks);
580
581 if (CountOfModules == CurrentSavedModules)
582 {
583 //
584 // Won't continue as the buffer is now full
585 // Generally, we shouldn't be at this stage, only when
586 // a module is just loaded and we didn't allocate enough
587 // memory for it, so it's better to continue
588 //
589 KeUnstackDetachProcess(&State);
590 return TRUE;
591 }
592
593 //
594 // Save the details into the storage
595 //
596 ModulesList[CurrentSavedModules].Entrypoint = Entry->EntryPoint;
597 ModulesList[CurrentSavedModules].BaseAddress = Entry->DllBase;
598
599 //
600 // Copy the path
601 //
602 TempSize = Entry->FullDllName.Length;
603 if (TempSize >= MAX_PATH)
604 {
605 TempSize = MAX_PATH;
606 }
607
608 TempSize = TempSize * 2;
609 memcpy(&ModulesList[CurrentSavedModules].FilePath, (const void *)Entry->FullDllName.Buffer, TempSize);
610
611 CurrentSavedModules++;
612 }
613
614 KeUnstackDetachProcess(&State);
615
616 return TRUE;
617}
struct _PEB32 * PPEB32
UNICODE_STRING32 FullDllName
Definition UserAccess.h:129

◆ UserAccessPrintLoadedModulesX86_2()

BOOLEAN UserAccessPrintLoadedModulesX86_2 ( PEPROCESS Proc)

Print loaded modules details from PEB.

This function should be called in vmx non-root

Parameters
Proc
Returns
BOOLEAN
628{
629 KAPC_STATE State;
630 PPEB32 Peb = NULL;
631 PPEB_LDR_DATA32 Ldr = NULL;
632
633 if (g_PsGetProcessWow64Process == NULL)
634 {
635 return FALSE;
636 }
637
638 //
639 // get process PEB for the x86 part, function is unexported and undocumented
640 //
642
643 if (!Peb)
644 {
645 return FALSE;
646 }
647
648 KeStackAttachProcess(Proc, &State);
649
650 Ldr = (PPEB_LDR_DATA32)Peb->Ldr;
651
652 if (!Ldr)
653 {
654 KeUnstackDetachProcess(&State);
655 return FALSE;
656 }
657
658 //
659 // loop the linked list
660 //
661 for (PLIST_ENTRY32 List = (PLIST_ENTRY32)Ldr->InLoadOrderModuleList.Flink;
662 List != &Ldr->InLoadOrderModuleList;
663 List = (PLIST_ENTRY32)List->Flink)
664 {
666 CONTAINING_RECORD(List, LDR_DATA_TABLE_ENTRY32, InLoadOrderLinks);
667
668 //
669 // since the PEB is x86, the DLL is x86, and so the base address is in x86 (4 byte as compared to 8 byte)
670 // and the UNICODE STRING is in 32 bit(UNICODE_STRING32), and because there is no viable conversion
671 // we are just going to force everything in
672 //
673 UNICODE_STRING ModuleName;
674 UNICODE_STRING ModulePath;
675 UINT64 BaseAddr = (UINT64)NULL;
676 UINT64 EntrypointAddress = (UINT64)NULL;
677
678 BaseAddr = Entry->DllBase;
679 EntrypointAddress = Entry->EntryPoint;
680
681 ModuleName.Length = Entry->BaseDllName.Length;
682 ModuleName.MaximumLength = Entry->BaseDllName.MaximumLength;
683 ModuleName.Buffer = (PWCH)Entry->BaseDllName.Buffer;
684
685 ModulePath.Length = Entry->FullDllName.Length;
686 ModulePath.MaximumLength = Entry->FullDllName.MaximumLength;
687 ModulePath.Buffer = (PWCH)Entry->FullDllName.Buffer;
688
689 Log("Base: %016llx\tEntryPoint: %016llx\tModule: %ws\tPath: %ws\n",
690 BaseAddr,
691 EntrypointAddress,
692 ModuleName.Buffer,
693 ModulePath.Buffer);
694 }
695
696 KeUnstackDetachProcess(&State);
697
698 return TRUE;
699}
#define Log(format,...)
Log without any prefix.
Definition HyperDbgHyperLogIntrinsics.h:129
UNICODE_STRING32 BaseDllName
Definition UserAccess.h:130