Skip to content

Instantly share code, notes, and snippets.

@whit3rabbit
Last active September 11, 2024 20:01
Show Gist options
  • Select an option

  • Save whit3rabbit/3ff3fe8c5ec936e206f7904071223929 to your computer and use it in GitHub Desktop.

Select an option

Save whit3rabbit/3ff3fe8c5ec936e206f7904071223929 to your computer and use it in GitHub Desktop.
Find token
#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