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}
POOL_TYPE SIZE_T NumberOfBytes
Definition Hooks.h:88
PVOID PlatformMemAllocateZeroedNonPagedPool(SIZE_T NumberOfBytes)
Allocates zeroed non-paged pool memory.
Definition PlatformMem.c:248
REQUEST_NEW_ALLOCATION * g_RequestNewAllocation
If sb wants allocation from vmx root, adds it's request to this structure.
Definition PoolManager.h:65
#define TRUE
Definition BasicTypes.h:114
#define FALSE
Definition BasicTypes.h:113

◆ PlmgrFreeRequestNewAllocation()

VOID PlmgrFreeRequestNewAllocation ( VOID )
38{
41}
PVOID PlatformMemFreePool(PVOID BufferAddress)
Frees a memory pool.
Definition PlatformMem.c:269
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
272{
273 for (SIZE_T i = 0; i < Count; i++)
274 {
275 POOL_TABLE * SinglePool = NULL;
276
278
279 if (!SinglePool)
280 {
281 LogError("Err, insufficient memory");
282 return FALSE;
283 }
284
285 //
286 // Allocate the buffer
287 //
288 SinglePool->Address = (UINT64)PlatformMemAllocateZeroedNonPagedPool(Size);
289
290 if (!SinglePool->Address)
291 {
292 PlatformMemFreePool(SinglePool);
293
294 LogError("Err, insufficient memory");
295 return FALSE;
296 }
297
298 SinglePool->Intention = Intention;
299 SinglePool->IsBusy = FALSE;
300 SinglePool->ShouldBeFreed = FALSE;
301 SinglePool->AlreadyFreed = FALSE;
302 SinglePool->Size = Size;
303
304 //
305 // Add it to the list
306 //
307 InsertHeadList(&g_ListOfAllocatedPoolsHead, &(SinglePool->PoolsList));
308 }
309
310 return TRUE;
311}
struct _POOL_TABLE POOL_TABLE
Table of holding pools detail structure.
LIST_ENTRY g_ListOfAllocatedPoolsHead
Create a list from all pools.
Definition PoolManager.h:101
#define LogError(format,...)
Log in the case of error.
Definition HyperDbgHyperLogIntrinsics.h:113
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
321{
322 BOOLEAN Result = TRUE;
323
324 //
325 // Make sure we're on vmx non-root and also we have new allocation
326 // and also pool manager is initialized, otherwise we shouldn't allocate or deallocate
327 //
329 {
330 //
331 // allocation's can't be done from vmx root
332 // or pool manager is not initialized yet
333 //
334 return FALSE;
335 }
336
337 //
338 // Make sure paging works properly
339 //
340 PAGED_CODE();
341
343
344 //
345 // Check for new allocation
346 //
348 {
349 for (SIZE_T i = 0; i < MaximumRequestsQueueDepth; i++)
350 {
352
353 if (CurrentItem->Size != 0)
354 {
355 Result = PoolManagerAllocateAndAddToPoolTable(CurrentItem->Size,
356 CurrentItem->Count,
357 CurrentItem->Intention);
358
359 //
360 // Free the data for future use
361 //
362 CurrentItem->Count = 0;
363 CurrentItem->Intention = 0;
364 CurrentItem->Size = 0;
365 }
366 }
367 }
368
369 //
370 // Check for deallocation
371 //
373 {
374 PLIST_ENTRY Link = g_ListOfAllocatedPoolsHead.Flink;
375
376 while (Link != &g_ListOfAllocatedPoolsHead)
377 {
378 PLIST_ENTRY Next = Link->Flink;
379
380 //
381 // Get the head of the record
382 //
383 PPOOL_TABLE PoolTable = (PPOOL_TABLE)CONTAINING_RECORD(Link, POOL_TABLE, PoolsList);
384
385 //
386 // Check whether this pool should be freed or not and
387 // also check whether it's already freed or not
388 //
389 if (PoolTable->ShouldBeFreed && !PoolTable->AlreadyFreed)
390 {
391 //
392 // Set the flag to indicate that we freed
393 //
394 PoolTable->AlreadyFreed = TRUE;
395
396 //
397 // This item should be freed
398 //
399 PlatformMemFreePool((PVOID)PoolTable->Address);
400
401 //
402 // Now we should remove the entry from the g_ListOfAllocatedPoolsHead
403 //
404 RemoveEntryList(Link);
405
406 //
407 // Free the structure pool
408 //
409 PlatformMemFreePool(PoolTable);
410 }
411
412 Link = Next;
413 }
414 }
415
416 //
417 // All allocation and deallocation are performed
418 //
421
423
424 return Result;
425}
BOOLEAN PoolManagerAllocateAndAddToPoolTable(SIZE_T Size, UINT32 Count, POOL_ALLOCATION_INTENTION Intention)
Allocate the new pools and add them to pool table.
Definition PoolManager.c:271
volatile LONG LockForReadingPool
Spinlock for reading pool.
Definition PoolManager.h:77
struct _REQUEST_NEW_ALLOCATION REQUEST_NEW_ALLOCATION
Manage the requests for new allocations.
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:89
BOOLEAN g_IsNewRequestForDeAllocation
We set it when there is a new allocation.
Definition PoolManager.h:95
BOOLEAN g_PoolManagerInitialized
Pool manager memory allocator initialized.
Definition PoolManager.h:83
VOID SpinlockLock(volatile LONG *Lock)
Tries to get the lock and won't return until successfully get the lock.
Definition Spinlock.c:53
VOID SpinlockUnlock(volatile LONG *Lock)
Release the lock.
Definition Spinlock.c:162
UCHAR BOOLEAN
Definition BasicTypes.h:35
void * PVOID
Definition BasicTypes.h:56
IMPORT_EXPORT_VMM BOOLEAN VmFuncVmxGetCurrentExecutionMode()
Get the current VMX operation state.
Definition Export.c:802
#define CONTAINING_RECORD(address, type, field)
Definition nt-list.h:36
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
155{
156 PLIST_ENTRY ListTemp = 0;
157 BOOLEAN Result = FALSE;
158 ListTemp = &g_ListOfAllocatedPoolsHead;
159
161
162 while (&g_ListOfAllocatedPoolsHead != ListTemp->Flink)
163 {
164 ListTemp = ListTemp->Flink;
165
166 //
167 // Get the head of the record
168 //
169 PPOOL_TABLE PoolTable = (PPOOL_TABLE)CONTAINING_RECORD(ListTemp, POOL_TABLE, PoolsList);
170
171 if (PoolTable->Address == AddressToFree)
172 {
173 //
174 // We found an entry that matched the detailed from
175 // previously allocated pools
176 //
177 PoolTable->ShouldBeFreed = TRUE;
178 Result = TRUE;
179
181 break;
182 }
183 }
184
186 return Result;
187}

◆ PoolManagerInitialize()

BOOLEAN PoolManagerInitialize ( )

Initializes the pool manager.

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 //
68 InitializeListHead(&g_ListOfAllocatedPoolsHead);
69
70 //
71 // Nothing to deallocate or allocate at the beginning
72 //
75
76 //
77 // Memory allocator is initialized
78 //
80
81 //
82 // Initialized successfully
83 //
84 return TRUE;
85}
BOOLEAN PlmgrAllocateRequestNewAllocation(SIZE_T NumberOfBytes)
Allocate global requesting variable.
Definition PoolManager.c:21

◆ 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
437{
438 BOOLEAN FoundAPlace = FALSE;
439
440 //
441 // ******** We check to find a free place to store ********
442 //
443
445
446 for (SIZE_T i = 0; i < MaximumRequestsQueueDepth; i++)
447 {
449
450 if (CurrentItem->Size == 0)
451 {
452 CurrentItem->Count = Count;
453 CurrentItem->Intention = Intention;
454 CurrentItem->Size = Size;
455
456 FoundAPlace = TRUE;
457
458 break;
459 }
460 }
461
462 if (!FoundAPlace)
463 {
465 return FALSE;
466 }
467
468 //
469 // Signals to show that we have new allocations
470 //
472
474 return TRUE;
475}
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
231{
232 UINT64 Address = 0;
233
237 if (PoolTable->Intention == Intention && PoolTable->IsBusy == FALSE)
238 {
239 PoolTable->IsBusy = TRUE;
240 Address = PoolTable->Address;
241 break;
242 }
243 });
244
245 //
246 // Check if we need additional pools e.g another pool or the pool
247 // will be available for the next use blah blah
248 //
249 if (RequestNewPool)
250 {
251 PoolManagerRequestAllocation(Size, 1, Intention);
252 }
253
254 //
255 // return Address might be null indicating there is no valid pools
256 //
257 return Address;
258}
#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:436
#define ScopedSpinlock(LockObject, CodeToRun)
Definition Spinlock.h:39

◆ PoolManagerShowPreAllocatedPools()

VOID PoolManagerShowPreAllocatedPools ( )

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

Returns
VOID
196{
197 PLIST_ENTRY ListTemp = 0;
198 ListTemp = &g_ListOfAllocatedPoolsHead;
199
200 while (&g_ListOfAllocatedPoolsHead != ListTemp->Flink)
201 {
202 ListTemp = ListTemp->Flink;
203
204 //
205 // Get the head of the record
206 //
207 PPOOL_TABLE PoolTable = (PPOOL_TABLE)CONTAINING_RECORD(ListTemp, POOL_TABLE, PoolsList);
208
209 LogInfo("Pool details, Pool intention: %x | Pool address: %llx | Pool state: %s | Should be freed: %s | Already freed: %s\n",
210 PoolTable->Intention,
211 PoolTable->Address,
212 PoolTable->IsBusy ? "used" : "free",
213 PoolTable->ShouldBeFreed ? "true" : "false",
214 PoolTable->AlreadyFreed ? "true" : "false");
215 }
216}
#define LogInfo(format,...)
Define log variables.
Definition HyperDbgHyperLogIntrinsics.h:71

◆ PoolManagerUninitialize()

VOID PoolManagerUninitialize ( )

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

Returns
VOID
94{
95 PLIST_ENTRY Link;
96
97 //
98 // Pool manager is not initialized anymore
99 //
101
103
104 Link = g_ListOfAllocatedPoolsHead.Flink;
105
106 while (Link != &g_ListOfAllocatedPoolsHead)
107 {
108 PLIST_ENTRY Next = Link->Flink;
109
110 //
111 // Get the head of the record
112 //
113 PPOOL_TABLE PoolTable = (PPOOL_TABLE)CONTAINING_RECORD(Link, POOL_TABLE, PoolsList);
114
115 //
116 // Free the alloocated buffer (if not already changed)
117 //
118 if (!PoolTable->AlreadyFreed)
119 {
120 PlatformMemFreePool((PVOID)PoolTable->Address);
121 }
122
123 //
124 // Unlink the PoolTable
125 //
126 RemoveEntryList(Link);
127
128 //
129 // Free the record itself
130 //
131 PlatformMemFreePool(PoolTable);
132
133 Link = Next;
134 }
135
136 InitializeListHead(&g_ListOfAllocatedPoolsHead);
139
141
143}
VOID PlmgrFreeRequestNewAllocation(VOID)
Definition PoolManager.c:37