Josh Graham

Oct 5, 2018

4 min read

Pentesting and .hta (bypass PowerShell Constrained Language Mode)

When I’m on an engagement and I’m given a SOE and a domain account, I usually want to use a tool like PowerShell Empire to remotely control the SOE and run all my other pentesting tools. When the client has strong security controls in place, it can be frustrating to get that initial foothold on the SOE. In these situations I find .hta files very useful. This blog post will have some of the interesting ways you can use .hta files in pentesting.

‘hta’ stands for ‘HTML Application’ and is basically the same as a regular HTML page except that it is run using mshta.exe and supports extra scripting languages. mshta.exe is a built in windows application and is often allowed through application whitelisting rules and we can do lots of interesting things using the extra scripting languages, specifically vbscript.

Lets say you’re in an environment where you don’t have access to the command prompt or PowerShell and you want to do something simple, like ping a PC. You could use a hta file with the following contents:

The above hta file isn’t great…The command opens in another window and disappears immediately after it is finished making it difficult to read the output. We can make this a bit better by capturing the output of the command and displaying inside the HTML application something like this:

Simple command runner code:

This hta file runs commands using the ‘WScript.Shell’ scripting object which is not the same as using cmd.exe’s command prompt. Built in functions like dir don’t work and you can’t do compound commands (i.e. ping && pause) so lets try to do better.

To run PowerShell commands with powershell.exe blocked we can use C#’s Pipeline class. To run arbitrary C# commands on a locked down system we will use a technique I learned at NOTSOSECURE’s Advanced Infrastructure Hacking course. The bypass works by using InstallUtil.exe (built in windows binary) to run an uninstall function in an arbitrary executable. We are going to create said executable using another built in windows binary, csc.exe, which can be used to compile arbitrary C# code (this resource is useful for application whitelist bypasses). Doing this manually is a pain and too hard to remember so we use a .hta to wrap the mundane steps. The hta will perform the following steps:

  1. Write some C# to a file, the C# contains an uninstall hook
  2. Compile the C# from step 1 into a .exe using csc.exe
  3. Write the PowerShell commands you want to run to a file. The C# uninstall hook will read these commands and execute them inside a Pipeline
  4. Execute uninstallUtil.exe on the exe from step 2 using a WScript.Shell object
  5. Display the output from uninstallUtil in the HTML application.

The full code is for this PowerShell .hta runner is available here:

One thing that is worth noting here, running PowerShell through C# pipelines bypasses constrained language mode. So you can use powershell.hta to run a tool like bloodhound that would otherwise be blocked ;-)

I don’t usually need to be stealthy but if you need to be, you can use run a hta with a hidden window with the following payload:

Although there won’t be a visible window, the mshta.exe process will be present in the task manager which should stick out like a sore thumb…

You don’t even need a hta file at all! mshta.exe understands JavaScript URIs so you can use a command similar to the one below to run your pentesting tools without a file ever hitting disk.

mshta.exe javascript:"<script language=vbscript>createobject(\"WScript.Shell\").run(\"calc\")\r\nclose()</script>

In Windows 10 (and Windows Server 2016 I think), Windows restarts a selection of applications that were running before you shut down the computer. It runs these applications the next time you log onto the system. It does this by writing an entry to the run-once registry key just before the system shuts down.

mshta.exe is one of the programs that utilises this feature. You could abuse this to have windows take care of persistence for you! Unfortunately, Windows won’t restore mshta.exe when it is run using the ‘WScript.Shell’ scripting object so you can’t easily do stealthy persistence (i.e. run your mshta.exe invisibly) but it does work with javascript URI’s so you can achieve sorta stealthy file-less persistence (the run-once registry key will only be present during the time between the system starting up and the user logging in).

I hope that this helps you all in your pen testing life. Keep an eye on my twitter for more fun obscure stuff @JPG1nc