Created
October 8, 2024 13:07
-
-
Save Acebond/61792987cd9cdac9c6a62c7d906f5e1f to your computer and use it in GitHub Desktop.
Find vulnerable handle example
This file contains 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 <Windows.h> | |
#include <stdio.h> | |
#define SystemHandleInformation 16 | |
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) | |
#ifndef NT_SUCCESS | |
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) | |
#endif | |
typedef struct _SYSTEM_HANDLE { | |
ULONG ProcessId; | |
UCHAR ObjectTypeNumber; | |
UCHAR Flags; | |
USHORT Handle; | |
PVOID Object; | |
ACCESS_MASK GrantedAccess; | |
} SYSTEM_HANDLE, * PSYSTEM_HANDLE; | |
typedef struct _SYSTEM_HANDLE_INFORMATION { | |
ULONG HandleCount; | |
SYSTEM_HANDLE Handles[1]; | |
} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION; | |
NTSTATUS(NTAPI* NtQuerySystemInformation)( | |
ULONG SystemInformationClass, | |
PVOID SystemInformation, | |
ULONG SystemInformationLength, | |
PULONG ReturnLength); | |
HANDLE FindVulnHandle(DWORD dwTargetPID) { | |
HMODULE ntdll = LoadLibraryA("ntdll.dll"); | |
if (!ntdll) { | |
printf("Failed to load ntdll.dll\n"); | |
return NULL; | |
} | |
NtQuerySystemInformation = (NTSTATUS(NTAPI*)(ULONG, PVOID, ULONG, PULONG))GetProcAddress(ntdll, "NtQuerySystemInformation"); | |
if (!NtQuerySystemInformation) { | |
printf("Failed to get NtQuerySystemInformation address\n"); | |
return NULL; | |
} | |
ULONG handleInfoSize = 0x10000; | |
PSYSTEM_HANDLE_INFORMATION handleInfo; | |
ULONG returnLength; | |
NTSTATUS status; | |
do { | |
handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); | |
if (!handleInfo) { | |
printf("Failed to get malloc %d\n", handleInfoSize); | |
return NULL; | |
} | |
status = NtQuerySystemInformation(SystemHandleInformation, handleInfo, handleInfoSize, &returnLength); | |
if (status == STATUS_INFO_LENGTH_MISMATCH) { | |
free(handleInfo); | |
handleInfoSize *= 2; | |
} | |
else if (!NT_SUCCESS(status)) { | |
printf("NtQuerySystemInformation failed with status: 0x%08X\n", status); | |
free(handleInfo); | |
return NULL; | |
} | |
} while (status == STATUS_INFO_LENGTH_MISMATCH); | |
printf("Number of handles: %lu\n", handleInfo->HandleCount); | |
const UCHAR type = 0x9; // THREAD | |
const UCHAR flags = 0x2; // inherited | |
for (ULONG i = 0; i < handleInfo->HandleCount; i++) { | |
SYSTEM_HANDLE handle = handleInfo->Handles[i]; | |
// Check it belongs to our process (we run this code inside the process with the leaked handle) | |
if (handle.ProcessId == dwTargetPID) { | |
// Find only threads, that have been inherited. This should give us the leaked thread handle. | |
if (handle.ObjectTypeNumber == type && (handle.Flags & flags)) { | |
printf("FOUND: Handle: 0x%08X, Process ID: %lu, Object Type: %u, Flags: 0x%02X, Addr: 0x%02X\n", | |
handle.Handle, handle.ProcessId, handle.ObjectTypeNumber, handle.Flags, handle.Object); | |
free(handleInfo); | |
FreeLibrary(ntdll); | |
return (HANDLE)handle.Handle; | |
} | |
} | |
} | |
free(handleInfo); | |
FreeLibrary(ntdll); | |
return NULL; | |
} | |
int main(void) { | |
HANDLE hTargetHandle = FindVulnHandle(GetCurrentProcessId()); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment