22nd Survey Division
Static Evasion Steganography Covert Channel Payload Delivery

Steganography: Covert Payload Delivery via LSB PNG + Zero-Width Unicode

George Wu June–July 2026 22nd Survey Division ring-stack Phase 8 / ghost-encoder
T1027.003
T1027.009
T1132
Plain English
A weapon has to travel from attacker to target somehow. If it looks like a weapon, it gets caught. Steganography makes it look like something innocent — a picture, a piece of text. The scanner checks the file, sees nothing suspicious, lets it through. The receiver unpacks the hidden payload on the other side.

Validated LSB PNG — XOR-encrypted shellcode embedded in image, Defender CLEAN, ring-stack Phase 8 confirmed.
Validated SSH pipe delivery — extractor never touches disk, AMSI never fires on file, calc.exe spawned.
Validated Zero-width Unicode — 0/72 VirusTotal, Kaspersky Premium clean, Discord CDN exfil confirmed June 2026.

Why Transit Is the Hardest Part

A fully FUD (Fully Undetectable) payload on disk is a solved problem with enough obfuscation. The harder problem is getting the payload from attacker machine to target without it being scanned in transit.

Email gateways scan attachments. Web proxies scan downloads. Endpoint AV scans anything written to disk. The payload doesn't need to be detected at execution — if it's detected on landing, it never runs.

Steganography solves the transit problem. The file that crosses the network contains the payload hidden in a legitimate carrier — an image, a text message, a document. The scanner sees the carrier, not the payload.

Technique 1: LSB PNG Steganography

Least Significant Bit encoding

Every pixel in a PNG image has three colour channels: Red, Green, Blue. Each channel is one byte (0–255). The least significant bit of a byte contributes a value of 1. Changing a colour value from 200 to 201 — one bit difference — is invisible to the human eye. We use those throwaway bits to store payload data.

Capacity: 1 bit per channel × 3 channels = 3 bits per pixel. A 1000×1000 image = 1,000,000 pixels × 3 bits = 375,000 bytes of payload capacity. A typical shellcode is 300–800 bytes. The capacity margin is enormous.

PNG PIXEL — BEFORE AND AFTER ENCODING ──────────────────────────────────────────────────────────────── Pixel at (x=0, y=0) — RGB values: Before: R=200 G=150 B=100 Binary: 11001000 10010110 01100100 ^ ^ ^ LSB=0 LSB=0 LSB=0 (original throwaway bits) Payload bit 1 = 1, bit 2 = 0, bit 3 = 1: After: R=201 G=150 B=101 Binary: 11001001 10010110 01100101 ^ ^ ^ LSB=1 LSB=0 LSB=1 (payload bits embedded) ──────────────────────────────────────────────────────────────── Visible colour change: 0.4%. Human eye: undetectable. AV scanner: sees a PNG with normal colour variation.

The first 4 bytes of the encoded data (consuming 32 pixels / 96 channel LSBs) store the payload length as a 32-bit little-endian integer. The extractor reads this first, then reads exactly that many bytes — no guesswork required.

PNG only — never JPEG. JPEG recompression changes colour values during save, corrupting the LSBs. PNG is lossless. The bits survive transfer intact.

Critical: Encrypt before encoding

Never embed raw shellcode. msfvenom output contains well-known byte sequences (shellcode stubs, syscall sequences, string constants). Defender will flag the PNG during download if the embedded bytes match signatures — even without understanding the image format.

XOR-encrypt the shellcode with a key before encoding. The encrypted form has no recognisable signature. Any constant key works; the ring-stack implementation uses 0x5A. The matching key is hardcoded in the extractor.

Delivery pipeline — ring-stack Phase 8 (validated)

1
Encrypt shellcode

XOR each byte of raw shellcode with key 0x5A. Output has no AV signatures — statistical distribution looks like noise.

2
Embed into carrier PNG

Python + Pillow: write 4-byte length header, then XOR-encrypted payload bytes into LSBs of carrier image pixels. Output: a valid PNG file, readable by any image viewer.

3
Transfer to target

SCP over SSH (already open in kill chain). Defender scans the landing: PNG header, valid image structure, no PE magic bytes (MZ), no shellcode signatures. CLEAN.

4
Extract and execute via SSH pipe — never touch disk

Pipe the extractor script via SSH stdin to PowerShell. The script never writes to disk on the target — Defender's file scanner never fires. AMSI bypass (HWBP technique) runs first in the same pipe, then the extractor reads the PNG, XOR-decrypts, allocates memory, and executes in-memory. Shell comes back.

Validated result — ring-stack Phase 8, Windows 11, Defender RTP enabled

Shellcode extracted from PNG in-memory. XOR-decrypted at key 0x5A. Allocated with VirtualAlloc, executed via CreateThread. calc.exe spawned. Reverse shell came back.

Defender scan of PNG during SCP transfer: CLEAN. Defender during in-memory execution (with HWBP AMSI bypass active): CLEAN. Phase 8 marked COMPLETE.

Critical fix noted during development: WaitForSingleObject(thread, 0xFFFFFFFF) — use [uint32]::MaxValue in PowerShell, not the literal. PS's Int32 parser overflows on 0xFFFFFFFF, causing PS to exit immediately and kill the shellcode thread before the shell connects.

Technique 2: Zero-Width Unicode (ghost-encoder)

A completely different carrier: plain text. Unicode contains dozens of zero-width characters — glyphs that render as invisible in every major application (Discord, email, browsers, terminals). They take up bytes in storage and transit but display as nothing to the human eye.

The 16-character alphabet

ghost-encoder uses 16 zero-width Unicode characters as an encoding alphabet — zero-width space (U+200B), zero-width non-joiner (U+200C), zero-width joiner (U+200D), zero-width no-break space (U+FEFF), and 12 more variants. Each byte of payload maps to 2 zero-width characters (4 bits each). The encoded payload is interspersed through visible carrier text.

Result: the text looks completely normal — but between every visible character there are invisible payload bytes. An observer seeing "Hello, how are you today?" sees 24 visible characters and nothing else. The actual string contains 152 characters. 128 are zero-width payload.

VISIBLE: "Hello, how are you today?" ACTUAL: H[ZW1][ZW3][ZW0][ZW2]e[ZW1][ZW1][ZW3][ZW2]l[ZW0][ZW3]... 24 visible chars + 128 zero-width chars = 152 total Entropy of output: 0.12 (normal text = 0.10–0.15) AV heuristic: sees text with near-zero entropy = normal content = CLEAN Raw shellcode entropy: ~7.8 (near-maximum = "definitely encrypted/compressed")

Entropy is the key metric antivirus uses to decide "does this look suspicious?" High entropy = probably encrypted payload = flag it. Zero-width characters have extremely low entropy from the AV's perspective because they're a limited, predictable alphabet. The combined text file looks like normal Unicode with typical low entropy.

Delivery: Discord CDN exfil (validated)

The ghost-encoder test delivered payload via a Discord message in a private channel. Discord CDN uploaded the carrier text, attacker downloaded it via CDN URL, extracted the payload — 100% recovery. Because the carrier was posted as text content, not as a file attachment, there was no file-scanning step.

Validated result — ghost-encoder, Kaspersky Premium 21.25 active, 2026-06-29

64-byte calc.exe shellcode encoded into "Hello, how are you today?" carrier text. Entropy 0.12. Uploaded to Discord CDN. Downloaded and decoded: 64/64 bytes recovered, 100%. Kaspersky: CLEAN. VirusTotal: 0/72. calc.exe spawned after extraction and execution.

Comparison: Which Carrier for Which Situation

PropertyLSB PNGZero-Width Unicode
Payload capacity375KB+ (1000×1000 image)~1KB per visible sentence
Carrier suspicionImage file — normalText message — normal
Delivery channelFile transfer (SCP, HTTP, email attachment)Chat, email body, document, comment field
Extraction methodPython Pillow extractor (pipe, no disk)Zero-width decoder (any language)
AV transit detectionZero (no PE bytes, low entropy after XOR)Zero (low entropy, no signatures)
Use in ring-stackPhase 8 — large payload deliveryghost_fud — covert exfil/delivery via messaging platforms

Where This Fits in the Kill Chain

Steganography is a transit-layer technique. It doesn't affect runtime detection — once the payload executes, AMSI and ETW are the relevant controls (see HWBP Zero-Write). What it solves is the gap between the attacker's machine and the target's disk: getting the payload across without triggering network inspection, email gateway scanning, or endpoint AV on file-write.

In the ring-stack kill chain, steganography (Phase 8) is used specifically with SSH pipe delivery to avoid ever writing the extractor or the payload to disk on the target. The PNG lands, passes the file scan as an image, and is never decompressed by AV. The extractor runs in memory, never as a file.

Further Reading