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

The pool manager used in vmx root. More...

#include "pch.h"

Functions

BOOLEAN PlmgrAllocateRequestNewAllocation (SIZE_T NumberOfBytes)
 Allocate global requesting variable.
 
VOID PlmgrFreeRequestNewAllocation (VOID)
 
BOOLEAN PoolManagerInitialize ()
 Initializes the pool manager.
 
VOID PoolManagerUninitialize ()
 Uninitialize the pool manager (free the buffers, etc.)
 
BOOLEAN PoolManagerFreePool (UINT64 AddressToFree)
 This function set a pool flag to be freed, and it will be freed on the next IOCTL when it's safe to remove.
 
VOID PoolManagerShowPreAllocatedPools ()
 Shows list of pre-allocated pools available (used for debugging purposes)
 
UINT64 PoolManagerRequestPool (POOL_ALLOCATION_INTENTION Intention, BOOLEAN RequestNewPool, UINT32 Size)
 This function should be called from vmx-root in order to get a pool from the list.
 
BOOLEAN PoolManagerAllocateAndAddToPoolTable (SIZE_T Size, UINT32 Count, POOL_ALLOCATION_INTENTION Intention)
 Allocate the new pools and add them to pool table.
 
BOOLEAN PoolManagerCheckAndPerformAllocationAndDeallocation ()
 This function performs allocations from VMX non-root based on g_RequestNewAllocation.
 
BOOLEAN PoolManagerRequestAllocation (SIZE_T Size, UINT32 Count, POOL_ALLOCATION_INTENTION Intention)
 Request to allocate new buffers.
 

Detailed Description

The pool manager used in vmx root.

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

As we cannot allocate pools in vmx root, we need a pool manager to manage the pools

Version
0.1
Date
2020-04-11

Function Documentation

◆ PlmgrAllocateRequestNewAllocation()

BOOLEAN PlmgrAllocateRequestNewAllocation ( SIZE_T NumberOfBytes)

Allocate global requesting variable.

Parameters
NumberOfBytes
Returns
22{
23 //
24 // Allocate global requesting variable
25 //
27
29 {
30 return FALSE;
31 }
32
33 return TRUE;
34}
#define TRUE
Definition BasicTypes.h:55
#define FALSE
Definition BasicTypes.h:54
POOL_TYPE SIZE_T NumberOfBytes
Definition Hooks.h:167
PVOID PlatformMemAllocateZeroedNonPagedPool(SIZE_T NumberOfBytes)
Allocate a non-paged buffer (zeroed)
Definition Mem.c:69
REQUEST_NEW_ALLOCATION * g_RequestNewAllocation
If sb wants allocation from vmx root, adds it's request to this structure.
Definition PoolManager.h:65

◆ PlmgrFreeRequestNewAllocation()

VOID PlmgrFreeRequestNewAllocation ( VOID )
38{
41}
VOID PlatformMemFreePool(PVOID BufferAddress)
Free (dellocate) a non-paged buffer.
Definition Mem.c:86
NULL()
Definition test-case-generator.py:530

◆ PoolManagerAllocateAndAddToPoolTable()

BOOLEAN PoolManagerAllocateAndAddToPoolTable ( SIZE_T Size,
UINT32 Count,
POOL_ALLOCATION_INTENTION Intention )

Allocate the new pools and add them to pool table.

This function doesn't need lock as it just calls once from PASSIVE_LEVEL

Parameters
SizeSize of each chunk
CountCount of chunks
IntentionThe Intention of the buffer (buffer tag)
Returns
BOOLEAN If the allocation was successful it returns true and if it was unsuccessful then it returns false
254{
255 for (size_t i = 0; i < Count; i++)
256 {
257 POOL_TABLE * SinglePool = NULL;
258
260
261 if (!SinglePool)
262 {
263 LogError("Err, insufficient memory");
264 return FALSE;
265 }
266
267 //
268 // Allocate the buffer
269 //
271
272 if (!SinglePool->Address)
273 {
274 PlatformMemFreePool(SinglePool);
275
276 LogError("Err, insufficient memory");
277 return FALSE;
278 }
279
280 SinglePool->Intention = Intention;
281 SinglePool->IsBusy = FALSE;
282 SinglePool->ShouldBeFreed = FALSE;
283 SinglePool->AlreadyFreed = FALSE;
284 SinglePool->Size = Size;
285
286 //
287 // Add it to the list
288 //
290 }
291
292 return TRUE;
293}
unsigned __int64 UINT64
Definition BasicTypes.h:21
#define LogError(format,...)
Log in the case of error.
Definition HyperDbgHyperLogIntrinsics.h:113
LIST_ENTRY g_ListOfAllocatedPoolsHead
Create a list from all pools.
Definition PoolManager.h:95
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ PLIST_ENTRY Entry)
Definition Windows.h:115
Table of holding pools detail structure.
Definition PoolManager.h:34
UINT64 Address
Definition PoolManager.h:35
BOOLEAN ShouldBeFreed
Definition PoolManager.h:40
BOOLEAN AlreadyFreed
Definition PoolManager.h:41
BOOLEAN IsBusy
Definition PoolManager.h:39
POOL_ALLOCATION_INTENTION Intention
Definition PoolManager.h:37
LIST_ENTRY PoolsList
Definition PoolManager.h:38
SIZE_T Size
Definition PoolManager.h:36

◆ PoolManagerCheckAndPerformAllocationAndDeallocation()

BOOLEAN PoolManagerCheckAndPerformAllocationAndDeallocation ( )

This function performs allocations from VMX non-root based on g_RequestNewAllocation.

Returns
BOOLEAN If the pool manager allocates buffer or there was no buffer to allocate then it returns true, if there was any error then it returns false
303{
304 BOOLEAN Result = TRUE;
305 PLIST_ENTRY ListTemp = 0;
306
307 //
308 // let's make sure we're on vmx non-root and also we have new allocation
309 //
311 {
312 //
313 // allocation's can't be done from vmx root
314 //
315 return FALSE;
316 }
317
318 //
319 // Make sure paging works properly
320 //
321 PAGED_CODE();
322
323 //
324 // Check for new allocation
325 //
327 {
328 for (SIZE_T i = 0; i < MaximumRequestsQueueDepth; i++)
329 {
331
332 if (CurrentItem->Size != 0)
333 {
334 Result = PoolManagerAllocateAndAddToPoolTable(CurrentItem->Size,
335 CurrentItem->Count,
336 CurrentItem->Intention);
337
338 //
339 // Free the data for future use
340 //
341 CurrentItem->Count = 0;
342 CurrentItem->Intention = 0;
343 CurrentItem->Size = 0;
344 }
345 }
346 }
347
348 //
349 // Check for deallocation
350 //
352 {
353 ListTemp = &g_ListOfAllocatedPoolsHead;
354
356
357 while (&g_ListOfAllocatedPoolsHead != ListTemp->Flink)
358 {
359 ListTemp = ListTemp->Flink;
360
361 //
362 // Get the head of the record
363 //
364 PPOOL_TABLE PoolTable = (PPOOL_TABLE)CONTAINING_RECORD(ListTemp, POOL_TABLE, PoolsList);
365
366 //
367 // Check whether this pool should be freed or not and
368 // also check whether it's already freed or not
369 //
370 if (PoolTable->ShouldBeFreed && !PoolTable->AlreadyFreed)
371 {
372 //
373 // Set the flag to indicate that we freed
374 //
375 PoolTable->AlreadyFreed = TRUE;
376
377 //
378 // This item should be freed
379 //
380 PlatformMemFreePool((PVOID)PoolTable->Address);
381
382 //
383 // Now we should remove the entry from the g_ListOfAllocatedPoolsHead
384 //
385 RemoveEntryList(&PoolTable->PoolsList);
386
387 //
388 // Free the structure pool
389 //
390 PlatformMemFreePool(PoolTable);
391 }
392 }
393
395 }
396
397 //
398 // All allocation and deallocation are performed
399 //
402
403 return Result;
404}
UCHAR BOOLEAN
Definition BasicTypes.h:39
BOOLEAN PoolManagerAllocateAndAddToPoolTable(SIZE_T Size, UINT32 Count, POOL_ALLOCATION_INTENTION Intention)
Allocate the new pools and add them to pool table.
Definition PoolManager.c:253
volatile LONG LockForReadingPool
Spinlock for reading pool.
Definition PoolManager.h:77
struct _POOL_TABLE * PPOOL_TABLE
#define MaximumRequestsQueueDepth
Maximum Pool Requests (while not allocated)
Definition PoolManager.h:22
BOOLEAN g_IsNewRequestForAllocationReceived
We set it when there is a new allocation.
Definition PoolManager.h:83
BOOLEAN g_IsNewRequestForDeAllocation
We set it when there is a new allocation.
Definition PoolManager.h:89
void SpinlockLock(volatile LONG *Lock)
Tries to get the lock and won't return until successfully get the lock.
Definition Spinlock.c:52
void SpinlockUnlock(volatile LONG *Lock)
Release the lock.
Definition Spinlock.c:158
BOOLEAN VmxGetCurrentExecutionMode()
Check current execution mode (vmx-root and non-root)
Definition Vmx.c:222
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition Windows.h:56
Manage the requests for new allocations.
Definition PoolManager.h:50
UINT32 Count
Definition PoolManager.h:52
SIZE_T Size
Definition PoolManager.h:51
POOL_ALLOCATION_INTENTION Intention
Definition PoolManager.h:53

◆ PoolManagerFreePool()

BOOLEAN PoolManagerFreePool ( UINT64 AddressToFree)

This function set a pool flag to be freed, and it will be freed on the next IOCTL when it's safe to remove.

Parameters
AddressToFreeThe pool address that was previously obtained from the pool manager
Returns
BOOLEAN If the address was already in the list of allocated pools by pool manager then it returns TRUE; otherwise, FALSE
137{
138 PLIST_ENTRY ListTemp = 0;
139 BOOLEAN Result = FALSE;
140 ListTemp = &g_ListOfAllocatedPoolsHead;
141
143
144 while (&g_ListOfAllocatedPoolsHead != ListTemp->Flink)
145 {
146 ListTemp = ListTemp->Flink;
147
148 //
149 // Get the head of the record
150 //
151 PPOOL_TABLE PoolTable = (PPOOL_TABLE)CONTAINING_RECORD(ListTemp, POOL_TABLE, PoolsList);
152
153 if (PoolTable->Address == AddressToFree)
154 {
155 //
156 // We found an entry that matched the detailed from
157 // previously allocated pools
158 //
159 PoolTable->ShouldBeFreed = TRUE;
160 Result = TRUE;
161
163 break;
164 }
165 }
166
168 return Result;
169}

◆ PoolManagerInitialize()

BOOLEAN PoolManagerInitialize ( )

Initializes the pool manager.

Initializes the Pool Manager and pre-allocate some pools.

Returns
BOOLEAN
54{
55 //
56 // Allocate global requesting variable
57 //
58 SIZE_T BufferSize = MaximumRequestsQueueDepth * sizeof(REQUEST_NEW_ALLOCATION);
59 if (!PlmgrAllocateRequestNewAllocation(BufferSize))
60 {
61 LogError("Err, insufficient memory");
62 return FALSE;
63 }
64
65 //
66 // Initialize list head
67 //
69
70 //
71 // Nothing to deallocate
72 //
74
75 //
76 // Initialized successfully
77 //
78 return TRUE;
79}
BOOLEAN PlmgrAllocateRequestNewAllocation(SIZE_T NumberOfBytes)
Allocate global requesting variable.
Definition PoolManager.c:21
struct _REQUEST_NEW_ALLOCATION REQUEST_NEW_ALLOCATION
Manage the requests for new allocations.
FORCEINLINE VOID InitializeListHead(_Out_ PLIST_ENTRY ListHead)
Definition Windows.h:41

◆ PoolManagerRequestAllocation()

BOOLEAN PoolManagerRequestAllocation ( SIZE_T Size,
UINT32 Count,
POOL_ALLOCATION_INTENTION Intention )

Request to allocate new buffers.

Parameters
SizeRequest new buffer to allocate
CountCount of chunks
IntentionThe intention of chunks (buffer tag)
Returns
BOOLEAN If the request is save it returns true otherwise it returns false
416{
417 BOOLEAN FoundAPlace = FALSE;
418
419 //
420 // ******** We check to find a free place to store ********
421 //
422
424
425 for (SIZE_T i = 0; i < MaximumRequestsQueueDepth; i++)
426 {
428
429 if (CurrentItem->Size == 0)
430 {
431 CurrentItem->Count = Count;
432 CurrentItem->Intention = Intention;
433 CurrentItem->Size = Size;
434
435 FoundAPlace = TRUE;
436
437 break;
438 }
439 }
440
441 if (!FoundAPlace)
442 {
444 return FALSE;
445 }
446
447 //
448 // Signals to show that we have new allocations
449 //
451
453 return TRUE;
454}
volatile LONG LockForRequestAllocation
Request allocation Spinlock.
Definition PoolManager.h:71

◆ PoolManagerRequestPool()

UINT64 PoolManagerRequestPool ( POOL_ALLOCATION_INTENTION Intention,
BOOLEAN RequestNewPool,
UINT32 Size )

This function should be called from vmx-root in order to get a pool from the list.

If RequestNewPool is TRUE then Size is used, otherwise Size is useless Note : Most of the times this function called from vmx root but not all the time

Parameters
IntentionThe intention why we need this pool for (buffer tag)
RequestNewPoolCreate a request to allocate a new pool with the same size, next time that it's safe to allocate (this way we never ran out of pools for this "Intention")
SizeIf the RequestNewPool is true the we should specify a size for the new pool
Returns
UINT64 Returns a pool address or returns null if there was an error
213{
214 UINT64 Address = 0;
215
219 if (PoolTable->Intention == Intention && PoolTable->IsBusy == FALSE)
220 {
221 PoolTable->IsBusy = TRUE;
222 Address = PoolTable->Address;
223 break;
224 }
225 });
226
227 //
228 // Check if we need additional pools e.g another pool or the pool
229 // will be available for the next use blah blah
230 //
231 if (RequestNewPool)
232 {
233 PoolManagerRequestAllocation(Size, 1, Intention);
234 }
235
236 //
237 // return Address might be null indicating there is no valid pools
238 //
239 return Address;
240}
UINT64 Address
Definition HyperDbgScriptImports.h:67
#define LIST_FOR_EACH_LINK(_head, _struct_type, _member, _var)
Definition MetaMacros.h:34
BOOLEAN PoolManagerRequestAllocation(SIZE_T Size, UINT32 Count, POOL_ALLOCATION_INTENTION Intention)
Request to allocate new buffers.
Definition PoolManager.c:415
#define ScopedSpinlock(LockObject, CodeToRun)
Definition Spinlock.h:39

◆ PoolManagerShowPreAllocatedPools()

VOID PoolManagerShowPreAllocatedPools ( )

Shows list of pre-allocated pools available (used for debugging purposes)

Returns
VOID
178{
179 PLIST_ENTRY ListTemp = 0;
180 ListTemp = &g_ListOfAllocatedPoolsHead;
181
182 while (&g_ListOfAllocatedPoolsHead != ListTemp->Flink)
183 {
184 ListTemp = ListTemp->Flink;
185
186 //
187 // Get the head of the record
188 //
189 PPOOL_TABLE PoolTable = (PPOOL_TABLE)CONTAINING_RECORD(ListTemp, POOL_TABLE, PoolsList);
190
191 LogInfo("Pool details, Pool intention: %x | Pool address: %llx | Pool state: %s | Should be freed: %s | Already freed: %s\n",
192 PoolTable->Intention,
193 PoolTable->Address,
194 PoolTable->IsBusy ? "used" : "free",
195 PoolTable->ShouldBeFreed ? "true" : "false",
196 PoolTable->AlreadyFreed ? "true" : "false");
197 }
198}
#define LogInfo(format,...)
Define log variables.
Definition HyperDbgHyperLogIntrinsics.h:71

◆ PoolManagerUninitialize()

VOID PoolManagerUninitialize ( )

Uninitialize the pool manager (free the buffers, etc.)

De-allocate all the allocated pools.

Returns
VOID
88{
89 PLIST_ENTRY ListTemp = 0;
91
93
94 while (&g_ListOfAllocatedPoolsHead != ListTemp->Flink)
95 {
96 ListTemp = ListTemp->Flink;
97
98 //
99 // Get the head of the record
100 //
101 PPOOL_TABLE PoolTable = (PPOOL_TABLE)CONTAINING_RECORD(ListTemp, POOL_TABLE, PoolsList);
102
103 //
104 // Free the alloocated buffer (if not already changed)
105 //
106 if (!PoolTable->AlreadyFreed)
107 {
108 PlatformMemFreePool((PVOID)PoolTable->Address);
109 }
110
111 //
112 // Unlink the PoolTable
113 //
114 RemoveEntryList(&PoolTable->PoolsList);
115
116 //
117 // Free the record itself
118 //
119 PlatformMemFreePool(PoolTable);
120 }
121
123
125}
VOID PlmgrFreeRequestNewAllocation(VOID)
Definition PoolManager.c:37