This exploit abuses the way "WinSxS" is managed by "dccw.exe" by means of a derivative Leo's Davidson "Bypass UAC" method so as to obtain an administrator shell without prompting for consent. It supports "x86" and "x64" architectures. Moreover, it has been successfully tested on Windows 8.1 9600, Windows 10 14393, Windows 10 15031 and Windows 10 15062.
1. Development of a New Bypass UAC
1.1. Vulnerability Search
To develop a new bypass UAC, first we have to find a vulnerability on the system and, to be more precise, a vulnerability in an auto-elevate process. To get a list of such processes we used the Sysinternals' tool called Strings. After that, we could see some auto-elevate processes like "sysprep.exe", "cliconfig.exe", "inetmgr.exe", "consent.exe" or "CompMgmtLauncher.exe" that had (some of them still have) vulnerabilities that allow the execution of a "bypass UAC". So, we started to study how other auto-elevate processes worked with the Sysinternals' application called Process Monitor (ProcMon), but focusing on "dccw.exe" process.
However, before starting with ProcMon, first we checked the manifest of such applications with another Sysinternals' application called Sigcheck, and, of course, in our case "dccw.exe" is an auto-elevate process.
Then, we could start to follow the execution flow of "dccw.exe" with ProcMon to see fn something strange occurs, something we checked immediately. At some point, if we have executed "dccw.exe" as a 64 bits process in a 64 bits Windows machine it looks for the directory "C:\Windows\System32\dccw.exe.Local\" to load a specific DLL called "GdiPlus.dll", the same as it were executed in a 32 bits Windows machine, whereas if we execute it as a 32 bits in the same machine, the process will look for the directory "C:\Windows\SysWOW64\dccw.exe.Local\". Then, due to the fact that it does not exist, the process always looks for a folder in the path "C:\Windows\WinSxS\" to get the desired DLL, this folder has a name with the following structure:[architecture]_microsoft.windows.gdiplus_[sequencial_code]_[Windows_version]_none_[sequencial_number]
If we take a look into "WinSxS" directory, we could see more than one folder that matches with this structure, this means that "dccw.exe" can load the desired DLL from any of these folders. The only thing we are sure is that if the application is invoked as a x86 process, the folder name will start with the string "x86", while if we execute it as a x64 process, its name will start with the string "amd64".
This situation can be abused to perform a DLL hijacking and then execute code with high integrity without prompting for consent.
1.2. Vulnerability Verification
Once we have found one error during the execution of an auto-elevate process, we need to verify whether it can be abused or not. To do this, we just created the folder "dccw.exe.Local" in the desired path and, into that folder, we created the folders located in "WinSxS" that could be invoked by the process to load "GdiPlus.dll", but without such DLL.
Now, if we execute "dccw.exe" we will see that the process has found the folder "dccw.exe.Local" and one of the "WinSxS" folders, but not the desired DLL, something that throws an error. This is what we expected, due to that situation can be exploited by an attacker as we mentioned before.
1.3. Exploit Development
At this point, we already know that we can perform a bypass UAC on Windows 10 abusing "dccw.exe", but how?
The most used method to bypass UAC is that one developed by Leo Davidson. However, it performs a process injection to invoke the IFileOperation COM object, which can be detected by some antivirus software, so a better approach to use it is that one called Masquerade PEB used by Cn33liz in its own bypass UAC.
Also, we have to modify the way IFileOperation is invoked in newer Windows 10 versions, since Leo Davidson method triggers UAC from build 15002. So, the way we have to invoke such operation is the same as the original, but without the operation flags "FOF_SILENT", "FOFX_SHOWELEVATIONPROMPT" and "FOF_NOERRORUI".
Before executing the exploit, it is important to check some aspects to not execute it unsuccessfully and therefore trigger some alarms. The first thing we check is the Windows build version, since some versions are not vulnerable to our exploit (those with a build version lower than 7600). After that, we verify that we do not have administrator rights yet, if it is not the case, there is no reason to execute the script. Then, we check the UAC settings so as to confirm that it is not set to "Always notify", since if it were set to that value, our exploit would be useless. Finally, we verify if the user belongs to the administrators group, because, if not, the exploit would be unsuccessful.
When an exploit is developed is important that can work in as many systems as possible, this includes 32 bits Windows systems. To achieve this, we need to compile our exploit for such systems, since we can also execute it in 64 bits systems.
When our 32 bits exploit is executed in a 64 bits Windows machine, the way "dccw.exe" operates is a bit different due to the invocation of WOW64 (Windows subsystem that allows 64 bits machines to run 32 bits applications). This means the folder "dccw.exe.Local" will be looked for in "C:\Windows\SysWOW64\" directory, instead of "C:\Windows\System32\", but also the targeted "GdiPlus.dll" will be a 32 bits DLL, which implies that it will be looked for in a folder that matches with that name pattern "C:\Windows\WinSxS\x86_microsoft.windows.gdiplus_*". However, if it is executed in a 32 bits Windows system, the exploit will work as expected.
Finally, it is important to remark that we need to consider all the paths that matches with the pattern "C:\Windows\WinSxS\x86_microsoft.windows.gdiplus_*" when the DLL hijack is performed in order to assure a 100% of effectiveness.
1.3.4. Malicious DLL
To execute a process with high integrity we need to develop a DLL that will be invoked via DLL hijacking. However, it is not as simple as it looks, because if we only do that, neither "dccw.exe" nor our code will be executed. This is because "dccw.exe" depends on some functions of "GdiPlus.dll", so we need to implement or forward the execution of such functions to the legit DLL.
The best option is forwarding the execution to the legit DLL, because in this way the size of our DLL will be lower. To do so, we used the program ExportsToC++ to port all exports of "GdiPlus.dll" to C++ language. Now, the problem is the huge number of exports "GdiPlus.dll" have, 631 to be precise, Nevertheless, "dccw.exe" does not import all of them, but a few. To know which functions are imported by "dccw.exe" from "GdiPlus.dll" we reversed engineering it with "IDA Pro". Finally, only 15 functions are imported from "GdiPlus.dll", so we only need to include those in our DLL.
Now, it seems that the problem has been fixed, but if we forward the execution to a specific "GdiPlus.dll" in C:\Windows\WinSxS\", the DLL will work only in some systems, since the name of the internal folders of "WinSxS" changes every Windows build. To overcome this problem, we came up with the idea of forwarding the execution to "C:\Windows\System32\GdiPlus.dll", due to the fact that the path is the same in all Windows 10 systems
The last thing we have to do is stopping the execution of "dccw.exe" after executing our malicious code so as to avoid the window opening of that process.
Now, once we have developed our malicious DLL, we need to drop it in the targeted machine. To do so, our DLL has been compressed and "base64" encoded into the exploit, so that can be decoded and decompressed at runtime to drop it as expected.
Finally, our crafted "GdiPlus.dll" is copied to the targeted location using IFileOperation COM object as previously mentioned.
1.3.5. Detection Avoidance
When an attacker compromises a system, it wants to stay undetected as much time as possible, this means removing every trace of the actions that it performs. Because of that, all the temporary files that are created during the execution of the exploit are removed when they are not needed anymore.
Finally, we need to determine which process we want to execute at high integrity. In our case, we chose the application "cmd.exe" because it allows us to perform as many operations at high integrity as we want once we will have administrator rights, but, in fact, we can execute whatever application we want.
To get a successfully execution of the exploit the targeted machine must comply the following requirements: 2. Requirements
- It must be a Windows 8 or 10, no matter what build version.
- The UAC settings must not be set to "Always notify".
- The compromised user must belong to the "Administrators group".
To execute the exploit you must be sure that the targeted machine meets the requirements. Then, you simply have to execute the exploit like any other command-line script:- C:\Users\L3cr0f> DccwBypassUAC.exe
4. Metasploit Module
The Metasploit module of this PoC use DLL injection instead of Masquerading PEB and it is available in:- Metasploit Framework: https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/windows/local/bypassuac_injection_winsxs.rb
- L3cr0f's Metasploit modules repository: https://github.com/L3cr0f/Metasploit-modules#bypassuac_injection_winsxs
This exploit has been developed to show how an attacker could gain privileges into a system, not to use it for malicious purposes. This means that I do not take any responsibility if someone uses it to perform criminal activities.
6. Microsoft Position
User Access Control (UAC) is a technology introduced with Windows Vista that provides a method of separating standard user privileges and tasks from those that require Administrator access. If a Standard User is using the system and attempts to perform an action for which the user has no authorization, a prompt from Windows appears and asks the Administrator account’s password. If an Administrator is using the system and attempts to do the same task, there is only a warning prompt. That prompt is known as a "Consent Prompt" because the administrator is only asked to agree to the action before proceeding. A weakness that would allow to bypass the "Consent Prompt" is not considered a security vulnerability, since that is not considered a security boundary.
However, Microsoft also states that "User Account Control (UAC) is a fundamental component of Microsoft's overall security vision".
To develop the exploit, I have based on those created by: 7. Acknowledgements
- Fuzzysecurity: https://github.com/FuzzySecurity/PowerShell-Suite/tree/master/Bypass-UAC.
- Cn33liz: https://github.com/Cn33liz/TpmInitUACBypass.
- hFireF0X: https://github.com/hfiref0x/UACME.
Many thanks to you!