Last active
September 11, 2024 20:01
-
-
Save whit3rabbit/3ff3fe8c5ec936e206f7904071223929 to your computer and use it in GitHub Desktop.
Find token
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 <windows.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <psapi.h> | |
| #pragma comment(lib, "psapi.lib") | |
| #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) | |
| #define STATUS_INFO_LENGTH_MISMATCH 0xC0000004 | |
| typedef LONG NTSTATUS; | |
| typedef NTSTATUS (NTAPI *PFN_NTQUERYSYSTEMINFORMATION)( | |
| ULONG SystemInformationClass, | |
| PVOID SystemInformation, | |
| ULONG SystemInformationLength, | |
| PULONG ReturnLength | |
| ); | |
| 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; | |
| const char* GetObjectTypeName(UCHAR objectTypeNumber) { | |
| switch(objectTypeNumber) { | |
| case 1: return "Type"; | |
| case 2: return "Directory"; | |
| case 3: return "SymbolicLink"; | |
| case 4: return "Token"; | |
| case 5: return "Process"; | |
| case 6: return "Thread"; | |
| case 7: return "Job"; | |
| case 8: return "Event"; | |
| case 9: return "Mutant"; | |
| case 10: return "Semaphore"; | |
| case 11: return "Timer"; | |
| case 12: return "IRTimer"; | |
| case 13: return "WindowStation"; | |
| case 14: return "Desktop"; | |
| case 15: return "Composition"; | |
| case 16: return "RawInputManager"; | |
| case 17: return "TpWorkerFactory"; | |
| case 18: return "Adapter"; | |
| case 19: return "Controller"; | |
| case 20: return "Device"; | |
| case 21: return "Driver"; | |
| case 22: return "IoCompletion"; | |
| case 23: return "File"; | |
| case 24: return "TmTm"; | |
| case 25: return "TmTx"; | |
| case 26: return "TmRm"; | |
| case 27: return "TmEn"; | |
| case 28: return "Section"; | |
| case 29: return "Session"; | |
| case 30: return "Key"; | |
| default: return "Unknown"; | |
| } | |
| } | |
| const char* GetAccessRightsDescription(ACCESS_MASK access) { | |
| static char buffer[256]; | |
| buffer[0] = '\0'; | |
| if (access & GENERIC_READ) strcat_s(buffer, sizeof(buffer), "Read, "); | |
| if (access & GENERIC_WRITE) strcat_s(buffer, sizeof(buffer), "Write, "); | |
| if (access & GENERIC_EXECUTE) strcat_s(buffer, sizeof(buffer), "Execute, "); | |
| if (access & GENERIC_ALL) strcat_s(buffer, sizeof(buffer), "All, "); | |
| if (access & DELETE) strcat_s(buffer, sizeof(buffer), "Delete, "); | |
| if (access & READ_CONTROL) strcat_s(buffer, sizeof(buffer), "ReadControl, "); | |
| if (access & WRITE_DAC) strcat_s(buffer, sizeof(buffer), "WriteDac, "); | |
| if (access & WRITE_OWNER) strcat_s(buffer, sizeof(buffer), "WriteOwner, "); | |
| if (access & SYNCHRONIZE) strcat_s(buffer, sizeof(buffer), "Synchronize, "); | |
| if (buffer[0] != '\0') { | |
| buffer[strlen(buffer) - 2] = '\0'; // Remove trailing comma and space | |
| } else { | |
| strcpy_s(buffer, sizeof(buffer), "No specific rights"); | |
| } | |
| return buffer; | |
| } | |
| const char* GetTokenAccessRightsDescription(ACCESS_MASK access) { | |
| static char buffer[512]; | |
| buffer[0] = '\0'; | |
| if (access & TOKEN_ASSIGN_PRIMARY) strcat_s(buffer, sizeof(buffer), "AssignPrimary, "); | |
| if (access & TOKEN_DUPLICATE) strcat_s(buffer, sizeof(buffer), "Duplicate, "); | |
| if (access & TOKEN_IMPERSONATE) strcat_s(buffer, sizeof(buffer), "Impersonate, "); | |
| if (access & TOKEN_QUERY) strcat_s(buffer, sizeof(buffer), "Query, "); | |
| if (access & TOKEN_QUERY_SOURCE) strcat_s(buffer, sizeof(buffer), "QuerySource, "); | |
| if (access & TOKEN_ADJUST_PRIVILEGES) strcat_s(buffer, sizeof(buffer), "AdjustPrivileges, "); | |
| if (access & TOKEN_ADJUST_GROUPS) strcat_s(buffer, sizeof(buffer), "AdjustGroups, "); | |
| if (access & TOKEN_ADJUST_DEFAULT) strcat_s(buffer, sizeof(buffer), "AdjustDefault, "); | |
| if (access & TOKEN_ADJUST_SESSIONID) strcat_s(buffer, sizeof(buffer), "AdjustSessionId, "); | |
| if (buffer[0] != '\0') { | |
| buffer[strlen(buffer) - 2] = '\0'; // Remove trailing comma and space | |
| } else { | |
| strcpy_s(buffer, sizeof(buffer), "No specific token rights"); | |
| } | |
| return buffer; | |
| } | |
| int EnumerateHandles(DWORD targetPid, int displayInfo) { | |
| HMODULE hNtdll; | |
| PFN_NTQUERYSYSTEMINFORMATION NtQuerySystemInformation; | |
| NTSTATUS status; | |
| PSYSTEM_HANDLE_INFORMATION handleInfo; | |
| ULONG bufferSize = 0x100000; // Start with 1MB buffer | |
| ULONG i; | |
| int tokenCount = 0; | |
| int totalHandlesForProcess = 0; | |
| const char* accessRights; | |
| const char* typeName; | |
| const char* tokenAccessRights; | |
| hNtdll = LoadLibraryA("ntdll.dll"); | |
| if (hNtdll == NULL) { | |
| printf("Failed to load ntdll.dll. Error: %lu\n", GetLastError()); | |
| return 0; | |
| } | |
| NtQuerySystemInformation = (PFN_NTQUERYSYSTEMINFORMATION)GetProcAddress(hNtdll, "NtQuerySystemInformation"); | |
| if (NtQuerySystemInformation == NULL) { | |
| printf("Failed to get NtQuerySystemInformation function. Error: %lu\n", GetLastError()); | |
| FreeLibrary(hNtdll); | |
| return 0; | |
| } | |
| handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(bufferSize); | |
| if (handleInfo == NULL) { | |
| printf("Failed to allocate memory\n"); | |
| FreeLibrary(hNtdll); | |
| return 0; | |
| } | |
| status = NtQuerySystemInformation(16, handleInfo, bufferSize, NULL); | |
| if (!NT_SUCCESS(status)) { | |
| printf("NtQuerySystemInformation failed with status 0x%X\n", status); | |
| free(handleInfo); | |
| FreeLibrary(hNtdll); | |
| return 0; | |
| } | |
| if (displayInfo) { | |
| printf("Enumerating handles for PID %lu:\n\n", targetPid); | |
| } | |
| for (i = 0; i < handleInfo->HandleCount; i++) { | |
| if (handleInfo->Handles[i].ProcessId == targetPid) { | |
| totalHandlesForProcess++; | |
| if (handleInfo->Handles[i].ObjectTypeNumber == 4) { // Token | |
| tokenCount++; | |
| if (displayInfo) { | |
| typeName = GetObjectTypeName(handleInfo->Handles[i].ObjectTypeNumber); | |
| accessRights = GetAccessRightsDescription(handleInfo->Handles[i].GrantedAccess); | |
| tokenAccessRights = GetTokenAccessRightsDescription(handleInfo->Handles[i].GrantedAccess); | |
| printf("Token Handle: 0x%04X\n", handleInfo->Handles[i].Handle); | |
| printf(" Object Address: 0x%p\n", handleInfo->Handles[i].Object); | |
| printf(" Access Rights: %s\n", accessRights); | |
| printf(" Token-specific Access Rights: %s\n", tokenAccessRights); | |
| printf(" Raw Access Mask: 0x%08X\n", handleInfo->Handles[i].GrantedAccess); | |
| if (handleInfo->Handles[i].GrantedAccess & (TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES)) { | |
| printf(" [!] This token has high-privilege access rights and might be suitable for escalation.\n"); | |
| } | |
| printf("\n"); | |
| } | |
| } | |
| } | |
| } | |
| if (displayInfo) { | |
| printf("Total handles found for PID %lu: %d\n", targetPid, totalHandlesForProcess); | |
| printf("Total token handles found: %d\n", tokenCount); | |
| } | |
| free(handleInfo); | |
| FreeLibrary(hNtdll); | |
| return tokenCount; | |
| } | |
| void EnumerateProcessesWithTokens() { | |
| DWORD pids[1024], cbNeeded, cProcesses; | |
| unsigned int i; | |
| if (!EnumProcesses(pids, sizeof(pids), &cbNeeded)) { | |
| printf("Failed to enumerate processes\n"); | |
| return; | |
| } | |
| cProcesses = cbNeeded / sizeof(DWORD); | |
| printf("Searching for processes with token handles:\n\n"); | |
| for (i = 0; i < cProcesses; i++) { | |
| if (pids[i] != 0) { | |
| int tokenCount = EnumerateHandles(pids[i], 0); | |
| if (tokenCount > 0) { | |
| HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pids[i]); | |
| if (hProcess != NULL) { | |
| char szProcessName[MAX_PATH] = "<unknown>"; | |
| HMODULE hMod; | |
| DWORD cbNeeded; | |
| if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) { | |
| GetModuleBaseNameA(hProcess, hMod, szProcessName, sizeof(szProcessName)); | |
| } | |
| printf("Process ID: %lu, Name: %s, Token Handles: %d\n", pids[i], szProcessName, tokenCount); | |
| EnumerateHandles(pids[i], 1); | |
| printf("--------------------\n\n"); | |
| } | |
| CloseHandle(hProcess); | |
| } | |
| } | |
| } | |
| } | |
| int main() { | |
| printf("Token Handle Finder\n\n"); | |
| EnumerateProcessesWithTokens(); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment