Once cleanmgr.exe creates the temporary folder, it then copies multiple DLLs along with “dismhost.exe” into the new folder:
After copying DismHost.exe and its DLLs to “C:\Users<username>\AppData\Temp<guid>”, cleanmgr.exe then starts “dismhost.exe” out of the newly created path as a high integrity process:
Since dismhost.exe launches out of “C:\Users<username>\AppData\Local\Temp<guid>”, it begins to load DLLs out of the same folder in a certain order:
Because the current medium integrity process has write access to the user’s %TEMP% directory, it is possible to hijack a DLL loaded by dismhost.exe and obtain code execution in a high integrity process. This is commonly known as a “BypassUAC” attack.
Since this particular situation is a race condition, we have to replace the target DLL before dismhost.exe loads it. We examined the entire process more closely and determined that “LogProvider.dll” is the last DLL loaded by dismhost.exe, giving us the best chance for a hijack opportunity. With this information, we can use a WMI event to monitor for the creation of “C:\Users<username>\AppData\Local\Temp<guid>” and then assign that WMI event an action of hijacking “LogProvider.dll” by copying our “malicious” DLL into “C:\Users<username>\AppData\Local\Temp<guid>” and naming it “LogProvider.dll”. Since this action happens before dismhost.exe loads it, it will load our DLL instead of the intended one.
Once dismhost.exe loads the DLL, it will load as high integrity, allowing us to bypass User Access Control and obtain code execution as a high integrity process.
After additional testing, this technique does not apply to standard user accounts as cleanmgr.exe does not extract any files to %TEMP%. When executed as a standard user in low or medium integrity, the task runs as medium integrity and never elevates past that.
Matt Graeber (@mattifestation) wrote an excellent PoC PowerShell script that will register a WMI event to monitor for the creation of the GUID folder by cleanmgr.exe and once detected, it will take the specified DLL and copy it to the GUID folder with the name of “LogProvider.dll”. Once dismhost.exe goes to load “LogProvider.dll”, it will be our malicious DLL instead of the legitimate one, thus bypassing UAC and giving us code execution in High Integrity context. You can find the script here: https://gist.github.com/mattifestation/b4072a066574caccfa07fcf723952d54
To test this, you simply need the PoC script and a DLL with a standard export of dllmain. For testing, you can either create your own DLL or use a simple MessageBox one located here: https://github.com/enigma0x3/MessageBox
This technique differs from the other public techniques by having a few benefits that can be handy:
This was disclosed to Microsoft Security Response Center (MSRC) on 07/20/2016. As expected, they responded by noting that UAC isn’t a security boundary, so this doesn’t classify as a security vulnerability, as stated here. While not a vulnerability, it does allow an attacker an alternate method to move to high integrity that differs from previous bypasses and introduces one more location or chokepoint that must be monitored to observe attacker behavior.
This particular technique can be remediated or fixed by disabling the task or removing the requirement for running with highest privileges. Further, if you would like to monitor for this attack, you could utilize methods/signatures to look for new WMI events as it is required to monitor for new folder creation for this attack to succeed. Combining this with App/DLL whitelisting and monitoring for abnormal modules being loaded (e.g. Sysmon event ID 7) would also limit the success of such an attack.