Hello everyone. Today, we are going to do the HEVD BufferOverflowNonPagedPoolNx from Low Integrity , which means we cannot use Windows API like NtQuerySystemInformation to leak the base address of ntoskrnl.exe. I am doing this writeup on windows 10 22H2 machine .
Original Author : @ommadawn46 has explained this same exploit in his GitHub repo here: repo . I am trying to explain that more briefly in my way in this post. Thanks a lot to @ommadawn46 .
Good To Know: As far as I know, This is the best paper for learning modern windows Heap i.e., Segment Heap . paper If you have some time ,please read this paper but I will obviously try to explain as much as I can.
Source Code Review
You can download the source code from and compile the win10-klfh branch , then you can use OSR tool to load the driver.
We are analyzing the BufferOverflowNonPagedPoolNx.c file which has the vulnerability
NTSTATUS
BufferOverflowNonPagedPoolNxIoctlHandler(
_In_ PIRP Irp,
_In_ PIO_STACK_LOCATION IrpSp
)
{
SIZE_T Size = 0;
PVOID UserBuffer = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
UNREFERENCED_PARAMETER(Irp);
PAGED_CODE();
UserBuffer = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
Size = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
if (UserBuffer)
{
Status = TriggerBufferOverflowNonPagedPoolNx(UserBuffer, Size);
}
return Status;
}
So, first here is the BufferOverflowNonPagedPoolNxIoctlHandler which takes the user supplied input and send the UserBuffer and Size to a function TriggerBufferOverflowNonPagedPoolNx .
NTSTATUS
TriggerBufferOverflowNonPagedPoolNx(
_In_ PVOID UserBuffer,
_In_ SIZE_T Size
)
{
PVOID KernelBuffer = NULL;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
__try
{
DbgPrint("[+] Allocating Pool chunk\n");
//
// Allocate Pool chunk
//
KernelBuffer = ExAllocatePoolWithTag(
NonPagedPoolNx,
(SIZE_T)POOL_BUFFER_SIZE,
(ULONG)POOL_TAG
);
In this function, first it allocates buffer on NonPagedPoolNx and size is 16 Bytes with PoolTag as Hack.
if (!KernelBuffer)
{
//
// 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(NonPagedPoolNx));
DbgPrint("[+] Pool Size: 0x%X\n", (SIZE_T)POOL_BUFFER_SIZE);
DbgPrint("[+] Pool Chunk: 0x%p\n", KernelBuffer);
}
//
// Verify if the buffer resides in user mode
//
ProbeForRead(UserBuffer, (SIZE_T)POOL_BUFFER_SIZE, (ULONG)__alignof(UCHAR));
DbgPrint("[+] UserBuffer: 0x%p\n", UserBuffer);
DbgPrint("[+] UserBuffer Size: 0x%X\n", Size);
DbgPrint("[+] KernelBuffer: 0x%p\n", KernelBuffer);
DbgPrint("[+] KernelBuffer Size: 0x%X\n", (SIZE_T)POOL_BUFFER_SIZE);
#ifdef SECURE
//
// Secure Note: This is secure because the developer is passing a size
// equal to size of the allocated Pool chunk to RtlCopyMemory()/memcpy().
// Hence, there will be no overflow
//
RtlCopyMemory(KernelBuffer, UserBuffer, (SIZE_T)POOL_BUFFER_SIZE);
#else
DbgPrint("[+] Triggering Buffer Overflow in NonPagedPoolNx\n");
//
// Vulnerability Note: This is a vanilla Pool Based Overflow vulnerability
// because the developer is passing the user supplied value directly to
// RtlCopyMemory()/memcpy() without validating if the size is greater or
// equal to the size of the allocated Pool chunk
//
RtlCopyMemory(KernelBuffer, UserBuffer, Size);
#endif
if (KernelBuffer)
{
DbgPrint("[+] Freeing Pool chunk\n");
DbgPrint("[+] Pool Tag: %s\n", STRINGIFY(POOL_TAG));
DbgPrint("[+] Pool Chunk: 0x%p\n", KernelBuffer);
//
// Free the allocated Pool chunk
//
ExFreePoolWithTag(KernelBuffer, (ULONG)POOL_TAG);
KernelBuffer = NULL;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
Status = GetExceptionCode();
DbgPrint("[-] Exception Code: 0x%X\n", Status);
}
return Status;
}
Then, It does the basic checks that the buffer resides in Usermode that we send using the IOCTL. In the Vulnerable part , there is the bug : It copies the our usermode supplied buffer to kernel mode buffer that is allocated previously with our user supplied Size.
This is a Heap Buffer Overflow in NonPagedPoolNx.
To be Continued.....
No comments:
Post a Comment