Introduction

While running through one of the labs for our PowerShell course, I stumbled upon a Microsoft-signed PowerShell host process in System32 — runscripthelper.exe. This program was just introduced in Windows 10 RS3 and all it does is read in PowerShell code from a specific directory and execute it. As a byproduct of the way in which it executes PowerShell code, it makes for a great constrained language mode bypass (i.e. generic application whitelisting bypass).

Here is the decompiled entry point method of runscripthelper.exe:

Entry point of runscripthelper.exe

As you can see, the program accepts three command line arguments:

Argument #1 must be “surfacecheck” in order to execute the ProcessSurfaceCheckScript method which is passed the 2nd and 3rd command line arguments. Argument #2 is comprised of a full path to a script and is compared against the “ k_utcScriptPath” global variable: \\?\%ProgramData%\Microsoft\Diagnosis\scripts Argument #3 is expected to be a path to a directory that exists. Command output is expected to be logged to this directory.

So right off the bat, it appears as though a constraint for execution is that a script must be located in the %ProgramData%\Microsoft\Diagnosis\scripts directory. By default (at least on my system), a standard user doesn’t have write access to that directory. Ideally, I would much rather attempt a bypass as a non-elevated user. So if I could somehow control the contents of %ProgramData% when runscripthelper.exe starts, I could have the program execute a script from a directory I control. Back to this soon but let’s first look at the ProcessSurfaceCheckScript method to see what it executes:

PowerShell invocation method in runscripthelper.exe

So literally all the ProcessSurfaceCheckScript method does is read the contents of a script (regardless of file extension, by the way) and execute it. On a system running AppLocker or Device Guard (now Windows Defender Application control), since it is likely that this program will be whitelisted as part of a Microsoft publisher rule, any PowerShell code executed in the process will execute in full language mode, hence bypassing the restrictions imposed on an attacker in constrained language mode.