NTSTATUS
TriggerUninitializedMemoryPagedPool(
_In_ PVOID UserBuffer
)
{
ULONG_PTR UserValue
=
0
;
ULONG_PTR MagicValue
=
0xBAD0B0B0
;
NTSTATUS Status
=
STATUS_SUCCESS;
PUNINITIALIZED_MEMORY_POOL UninitializedMemory
=
NULL;
PAGED_CODE();
__try
{
/
/
/
/
Verify
if
the
buffer
resides
in
user mode
/
/
ProbeForRead(UserBuffer, sizeof(UNINITIALIZED_MEMORY_POOL), (ULONG)__alignof(UCHAR));
/
/
/
/
Allocate Pool chunk
/
/
UninitializedMemory
=
(PUNINITIALIZED_MEMORY_POOL)ExAllocatePoolWithTag(
PagedPool,
sizeof(UNINITIALIZED_MEMORY_POOL),
(ULONG)POOL_TAG
);
if
(!UninitializedMemory)
{
/
/
/
/
Unable to allocate Pool chunk
/
/
DbgPrint(
"[-] Unable to allocate Pool chunk\n"
);
Status
=
STATUS_NO_MEMORY;
return
Status;
}
else
{
DbgPrint(
"[+] Pool Tag: %s\n"
, STRINGIFY(POOL_TAG));
DbgPrint(
"[+] Pool Type: %s\n"
, STRINGIFY(PagedPool));
DbgPrint(
"[+] Pool Size: 0x%X\n"
, sizeof(UNINITIALIZED_MEMORY_POOL));
DbgPrint(
"[+] Pool Chunk: 0x%p\n"
, UninitializedMemory);
}
/
/
/
/
Get the value
from
user mode
/
/
UserValue
=
*
(PULONG_PTR)UserBuffer;
DbgPrint(
"[+] UserValue: 0x%p\n"
, UserValue);
DbgPrint(
"[+] UninitializedMemory Address: 0x%p\n"
, &UninitializedMemory);
/
/
/
/
Validate the magic value
/
/
if
(UserValue
=
=
MagicValue) {
UninitializedMemory
-
>Value
=
UserValue;
UninitializedMemory
-
>Callback
=
&UninitializedMemoryPagedPoolObjectCallback;
/
/
/
/
Fill the
buffer
with ASCII
'A'
/
/
RtlFillMemory(
(PVOID)UninitializedMemory
-
>
Buffer
,
sizeof(UninitializedMemory
-
>
Buffer
),
0x41
);
/
/
/
/
Null terminate the char
buffer
/
/
UninitializedMemory
-
>
Buffer
[(sizeof(UninitializedMemory
-
>
Buffer
)
/
sizeof(ULONG_PTR))
-
1
]
=
'\0'
;
}
else
{
DbgPrint(
"[+] Freeing UninitializedMemory Object\n"
);
DbgPrint(
"[+] Pool Tag: %s\n"
, STRINGIFY(POOL_TAG));
DbgPrint(
"[+] Pool Chunk: 0x%p\n"
, UninitializedMemory);
/
/
/
/
Free the allocated Pool chunk
/
/
ExFreePoolWithTag((PVOID)UninitializedMemory, (ULONG)POOL_TAG);
/
/
/
/
Secure Note: This
is
secure because the developer
is
setting
'UninitializedMemory'
/
/
to NULL
and
checks
for
NULL pointer before calling the callback
/
/
/
/
/
/
Set
to NULL to avoid dangling pointer
/
/
UninitializedMemory
=
NULL;
}
/
/
/
/
Vulnerability Note: This
is
a vanilla Uninitialized Heap Variable vulnerability
/
/
because the developer
is
not
setting
'Value'
&
'Callback'
to definite known value
/
/
before calling the
'Callback'
/
/
DbgPrint(
"[+] Triggering Uninitialized Memory in PagedPool\n"
);
/
/
/
/
Call the callback function
/
/
if
(UninitializedMemory)
{
DbgPrint(
"[+] UninitializedMemory->Value: 0x%p\n"
, UninitializedMemory
-
>Value);
DbgPrint(
"[+] UninitializedMemory->Callback: 0x%p\n"
, UninitializedMemory
-
>Callback);
UninitializedMemory
-
>Callback();
/
/
Here!
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
Status
=
GetExceptionCode();
DbgPrint(
"[-] Exception Code: 0x%X\n"
, Status);
}
return
Status;
}