DOCUMENTATION
Learn why command obfuscation techniques work and when to use them effectively in CTF challenges and authorized security testing.
Introduction
Command obfuscation is the practice of modifying commands while preserving their functionality to bypass security filters, Web Application Firewalls (WAFs), and input validation mechanisms. This is commonly needed in:
- CTF Competitions - Bypassing intentionally weak filters in challenges
- Penetration Testing - Testing the effectiveness of security controls
- Security Research - Understanding filter bypass techniques
- Red Team Operations - Evading detection during authorized assessments
Legal Disclaimer
These techniques should only be used in authorized security testing environments, CTF competitions, or educational contexts. Unauthorized access to computer systems is illegal.
How It Works
Command obfuscation exploits the difference between how security filters parse input and how the shell interprets commands. Filters often use simple pattern matching (regex, blacklists) while shells have complex parsing rules.
How Filters Typically Work
- Blacklist matching - Block known dangerous commands like cat, wget, curl
- Regex patterns - Match patterns like /etc/passwd
- Character filtering - Remove or block special characters
How Shells Actually Parse
- Quote removal - Empty quotes "" and '' are removed
- Variable expansion - $var is replaced with its value
- Glob expansion - [a] matches the character 'a'
- Escape processing - \c becomes just 'c'
When to Use Each Technique
Pro Tip
Different filters block different things. Start with simple techniques (quotes, backslashes) and escalate to encoding if needed. The simplest bypass that works is usually the best.
| If Blocked... | Try This Technique | Example |
|---|---|---|
| Command names (cat, ls, id) | Quotes, Backslash, Glob | c'a't, c\at, c[a]t |
| File paths (/etc/passwd) | Wildcards, Glob, Encoding | /e*/passwd, /etc/pass[w]d |
| Spaces | IFS, Brace expansion, Tabs | cat${IFS}/etc/passwd |
| Entire command string | Base64, Hex, Concatenation | echo Y2F0...|base64 -d|bash |
| Special characters | Variable expansion, Encoding | $'\x63\x61\x74' |
Glob Patterns
Glob patterns are shell wildcards used for filename matching. When used strategically, they can bypass string-based filters while the shell still correctly interprets the command.
Why It Works
The bracket expression [x] matches exactly one character from the set inside the brackets. When there's only one character, it matches exactly that character. Filters see [a] but bash resolves it to a.
Syntax Variants
When It Works
- Filter blocks exact strings like "cat" or "passwd"
- Filter doesn't understand shell glob syntax
- bash, sh, zsh, and most POSIX shells
When It Fails
- Filter strips or blocks bracket characters
- Command runs in a context without glob expansion
- The glob doesn't match any existing file (for path globs)
Quote Insertion
Inserting empty quote pairs breaks up blocked strings while the shell removes them during parsing, resulting in the original command.
Why It Works
In shell parsing, adjacent strings are concatenated. Empty quotes "" or '' produce empty strings that don't change the final result. The filter sees broken strings but the shell concatenates them.
Single vs Double Quotes
- Single quotes '' - No expansion, everything literal (safer)
- Double quotes "" - Allows variable expansion ($VAR works inside)
- Best practice - Use single quotes when possible
Shell Concatenation Rule
Adjacent words in shell are concatenated: "hel""lo" becomes hello. This is documented POSIX behavior.
Backslash Escape
Backslash escapes the following character, preserving its literal value. For most alphanumeric characters, this has no effect but breaks pattern matching.
Why It Works
Backslash makes the next character literal. For regular letters, \c equals c. Filters see the backslash but bash strips it during quote removal phase.
Important Notes
- Works for letters: \a = a
- Special chars stay escaped: \$ = literal $
- Newline after backslash = line continuation
Variable Expansion
Shell variables that are undefined or empty expand to nothing. Inserting these between characters breaks the string for filters but produces the same output.
Why It Works
Undefined variables expand to empty strings by default. Special variables like $@ and $* are empty in interactive shells. The filter sees $@ but bash expands it to nothing.
Best Variables to Use
| Variable | What It Is | Reliability |
|---|---|---|
| $@ | All positional parameters | High |
| ${x} | Undefined variable | High |
| $() | Empty subshell | High |
| $* | Positional params as string | Medium |
Variable Concatenation
Building commands by storing parts in variables and concatenating them at execution time.
Why It Works
Variables are expanded at runtime. Filters scan the input text but don't execute it, so they see variable assignments, not the final command.
When It Works
- Filter doesn't interpret shell variable syntax
- Multiple commands allowed (semicolons not blocked)
- bash or compatible shell
Encoding Techniques
Encode the command and decode it at runtime. This completely obscures the command from filters.
Why It Works
Base64 converts binary/text to ASCII letters and numbers. The filter sees innocent-looking base64 text. At runtime, it's decoded and executed.
Encoding Your Commands
Why It Works
Bash's $'...' ANSI-C quoting interprets escape sequences including hex (\xNN) and octal (\NNN).
ASCII Hex Reference Table
| Character | Hex | Octal | Decimal |
|---|---|---|---|
| space | \x20 | \040 | 32 |
| / | \x2f | \057 | 47 |
| a-z | \x61-\x7a | \141-\172 | 97-122 |
| A-Z | \x41-\x5a | \101-\132 | 65-90 |
| 0-9 | \x30-\x39 | \060-\071 | 48-57 |
| - | \x2d | \055 | 45 |
| . | \x2e | \056 | 46 |
| _ | \x5f | \137 | 95 |
Quick Conversion
Use: printf '%x\n' "'a" to get hex value of 'a' (61), or echo -n "cat" | xxd -p for full string (636174).
Wildcard Paths
Using shell wildcards in paths to avoid typing exact filenames that might be filtered.
Why It Works
Wildcards expand to matching filenames. * matches any string, ? matches any single character. If only one file matches, it expands to that exact path.
Ambiguity Warning
Wildcards expand to ALL matching files. If /e* matches multiple directories, you might get unexpected results. Be specific enough to match only your target.
IFS Manipulation
IFS (Internal Field Separator) defines what characters separate words. Manipulating it allows bypassing space filters.
Why It Works
$IFS defaults to space, tab, newline. When expanded in an unquoted context, it effectively produces a word separator. You can also redefine IFS to use different separators.
When Spaces Are Blocked
If the filter blocks spaces but allows $, IFS is your best friend. It's a standard shell variable that produces the exact characters you need.
Caret Escape (Windows)
The caret ^ is the CMD.exe escape character, similar to backslash in Unix shells.
Why It Works
In CMD, ^ escapes the next character. For regular letters, ^w equals w. This breaks string matching while CMD strips the carets.
Limitations
- Only works in CMD.exe, not PowerShell
- Some contexts require doubled carets ^^
- Escaping some special chars changes meaning
Environment Variable Substrings
CMD allows extracting substrings from environment variables. You can build commands character by character from existing variables.
Why It Works
CMD's %VAR:~start,length% syntax extracts substrings. Since %COMSPEC% typically equals C:\Windows\system32\cmd.exe, you can extract any letter you need.
Verified Character Mappings
| Character | Extraction | Source |
|---|---|---|
| C | %COMSPEC:~0,1% | C:\... |
| c | %COMSPEC:~-7,1% | cmd.exe |
| m | %COMSPEC:~-6,1% | cmd.exe |
| d | %COMSPEC:~-5,1% | cmd.exe |
| e | %COMSPEC:~-1,1% | .exe |
| x | %COMSPEC:~-2,1% | .exe |
| W | %WINDIR:~3,1% | Windows |
| i | %WINDIR:~4,1% | Windows |
| n | %WINDIR:~5,1% | Windows |
| o | %WINDIR:~7,1% | Windows |
| w | %WINDIR:~8,1% | Windows |
| s | %WINDIR:~-1,1% | Windows |
Useful Environment Variables
- %COMSPEC% - C:\Windows\system32\cmd.exe
- %WINDIR% - C:\Windows
- %SYSTEMROOT% - C:\Windows (same as WINDIR)
- %PATH% - Contains many diverse characters
- %PATHEXT% - .COM;.EXE;.BAT... (useful for punctuation)
PowerShell Techniques
PowerShell offers powerful encoding and execution options for Windows command obfuscation.
Base64 Encoded Commands
PowerShell's -EncodedCommand (or -e, -enc) accepts Base64-encoded UTF-16LE strings.
UTF-16LE Encoding
PowerShell expects UTF-16LE (Little Endian) encoding, not plain ASCII Base64. Each character becomes 2 bytes. The generator handles this automatically.
Character Array Execution
Technique Comparison
| Technique | Linux | Windows | Complexity | Detectability |
|---|---|---|---|---|
| Quote Insertion | Yes | Yes | Low | Low |
| Escape Characters | \ (backslash) | ^ (caret) | Low | Low |
| Glob Patterns | Yes | No | Low | Medium |
| Variable Expansion | Yes | Yes | Medium | Medium |
| Concatenation | Yes | Yes | Medium | Medium |
| Base64 Encoding | Yes | PowerShell | High | High |
| Hex Encoding | Yes | Limited | High | High |
| IFS Manipulation | Yes | No | Medium | Medium |
| Env Substrings | No | CMD | High | High |
Troubleshooting
Payload Not Working?
- Check the shell - bash vs sh vs zsh have different features
- Check execution context - CGI, PHP exec(), Python subprocess all handle quoting differently
- Test locally first - Verify the payload works before using in target
- Watch for double-escaping - Quotes and backslashes might need escaping for the transport layer
Common Mistakes
- Glob doesn't match - Wildcards in non-existent paths fail
- Wrong encoding - PowerShell needs UTF-16LE, not UTF-8
- Missing interpreter - |bash fails if only sh exists
- Blocked pipe/semicolon - Many payloads need | or ;
Testing Tips
Context-Specific Issues
| Context | Common Issues | Solution |
|---|---|---|
| PHP exec()/system() | Quotes need escaping | Use hex encoding or base64 |
| Python subprocess | Shell=False by default | Ensure shell=True or use direct path |
| URL parameters | Special chars URL encoded | Double-encode or use alternatives |
| JSON payloads | Backslashes doubled | Account for JSON escaping |
| WAF blocking | Pattern matching | Try multiple techniques, combine them |