Steganography CTF: stegide, zsteg and binwalk

Depov

Moderator
Staff member
MODERATOR
ULTIMATE
SUPREME
PREMIUM
MEMBER
Joined
Feb 18, 2025
Messages
590
Reaction score
1,129
Deposit
0$
Stego-Task Disassembly Algorithm: From File to Flag

The main mistake in solving tasks for steganography in CTF is a chaotic selection of tools. Run stegide on PNG (it doesn't support PNG), then zsteg on JPEG (it doesn't support JPEG), lose time and nerves. Familiar?

Workflow, which I use on every stego-tasque:

file – define a real format (the expansion can lie)
strings | grep -i flag – looking for a flag in an open text
exiftool – check the metadata for hidden comments
binwalk – looking for nested files
Format-specific tool: zsteg for PNG/BMP, steghide for JPEG/WAV, spectrogram for audio
Hex editor — manual analysis if the automation is silent

Order is not accidental. Steps 1-3 take seconds and solve the simplest tasks. Step 4 catches the mattress files. And only if nothing came up, we turn to heavy artillery. According to the Trail of Bits CTF Field Guide, forensics needs three skills for taxing: format recognition, binary data work, and Python knowledge. The algorithm above is built on them.
Intelligence: file, strings and file metadata analysis
Magic bytes and format definition

The first rule of CTF steganography is not to trust the file extension. At the competition I met JPEG, renamed .txt, PNG with the expansion of .docx and ELF-binary under the guise of pictures. The utility file reads magic bytes — signature bytes in the title — and shows the real format.

file suspicious.png can return JPEG image data, JFIF standard 1.01 – and it is immediately clear that the expansion is replaced. Next, you need to work with JPEG tools, not with PNG.

The next step is strings. The utility pulls out all readable ASCII sequences from the binary file. Combination strings image.png | grep -i flag catches flags that the author of the tack at the end of the file or in the text chanks PNG. Parameter -o adds offset: strings -o screenshot.png – useful for manual extraction through dd.

It is worth checking the base64 separately. If among the conclusion strings got a long alphabetical-digital line with = or == at the end – try echo "строка" | base64 -d. It happens that the whole tack is reduced to this.
exiftool: hidden data in metadata

Metadata is a frequent candidate for the storage of a hidden message in a file. Exiftool reads EXIF, IPTC, XMP and PNG text chunks (tEXt, zTXt, iTXt). In forensic CTF tasks flags hide in the fields of Comment, Artist, Copyright, Description and even in GPS-coordinates (yes, and such happens).

Launch: exiftool image.jpg. If the output is voluminous, filter: exiftool image.jpg | grep -i -E "comment|flag|hint|description".

Nuance with PNG: Windows does not show EXIF PNG data through standard file properties. The PNG format does not technically support the EXIF standard (unlike JPEG) but can store metadata in text wools. Exiftool correctly reads these chanks on any platform – do not rely on the “File Properties” in the explorer.

For completeness of the picture it is worth to launch pngcheck -v file.png. The utility checks the integrity of all chanks and shows CRC errors – a sure sign of the modified IHDR header (PNG-padding technique, about it below).
LSB steganography in PNG: zsteg and Stegsolve

Least Significant Bit is the most common steganography technique in the CTF. The lower score of each byte of the color channel is replaced by a hidden message bit. Visually, the change is invisible - the difference in the color of the pixel is 1 out of 256 gradations. But if you put all the younger bits together, we get the hidden data.

As noted by SANReN CSC in the forensics-guide, LSB steganography works because the values of 255 (11111111) and 254 (1111110) for the human eye are indistinguishable, and the last bit already contains other information. One bit on the pixel is not enough. But in the picture 1920×1080 it is 2 073 600 bits, that is, about 253 KB of hidden data. Enough for the eyes.
zsteg is a quick analysis tool for PNG and BMP

zsteg is a Ruby utility that automatically checks PNG and BMP for LSB steganography across all channels and beat planes. This is the first thing to run on a PNG file after basic exploration.

Basic challenge: zsteg image.png – checks the standard LSB combinations (RGB, BGR, bypass on rows and columns). Advanced analysis: zsteg image.png --all – goes through all possible combinations of channels, bit order and bypass directions.

Example of real output:

b1,r,lsb,xy .. text: "flag{lsb_is_easy_peasy}"
b1,rgb,lsb,xy .. file: PNG image data, 200 x 50
b2,g,msb,xy .. text: "\x03\x8a random noise"

Read: b1,r,lsb,xy – first bit, red channel, least significant bit, bypassing on the lines (xy). Pay attention to the lines with meaningful text or file signatures. file: PNG image data – a sign of the nested image in LSB.

The trap: zsteg --all in noisy images generates dozens of false positives. Filter: zsteg image.png --all | grep -v "^b[2-8]" – cuts off the older bit planes, where the data is rarely hidden. Another option is to send a output to the file (zsteg --all image.png > results.txt) and look for meaningful hands.
Stegsolve: visual analysis of layers

Stepsolve is a Java application with GUI that shows an image over individual bit planes of each channel. Where zsteg searches for text automatically, Stegsolve visualizes the result—sometimes a hidden message is literally drawn in one layer.

Launch: java -jar Stegsolve.jar, then File → Open. Switch filters with arrows: Red plane 0, Green plane 0, Blue plane 0 is the LSB of each channel.

Three modes to know:

Data Extract – select specific bits of specific channels to extract data. If zsteg showed that the data in b1,rgb,lsb – mark bit 0 in channels R, G, B and get the file.

Image Combiner - overlays two images with operations XOR, AND, SUB. It is used when the original and modified copy are given in the task: XOR of two pictures will show only the changed pixels.

Frame Browser – disassembles GIF and APNG into separate frames. The symbols of the flag can be scattered on different frames of animation.

When zsteg finds nothing meaningful, and the task clearly indicates LSB – open Stegsolve and sort through the planes manually. Automation does not always catch data recorded in a non-standard order (on columns instead of rows or in the alpha channel).
steghide CTF: extracting data from JPEG and audio

steghide is one of the most popular tools for steganography in CTF. Works with JPEG, BMP, WAV and AU. Unlike the LSB utility, steghide uses its own embedding algorithm with optional password protection.

Main teams: steghide info cover.jpg – checks the availability of nested data and shows the size. steghide extract -sf cover.jpg - extracts. If the password is not set (empty passphrase, just Enter) - the data is delivered instantly.

And here the rake is laid a whole alley: steghide does NOT work with PNG. If you have PNG, use zsteg or Stegsolve. Launching steghide extract -sf image.png, get a format error and waste time. On every second CTF, someone from the team comes to this.
Brutforce password steghide

When steghide requires a password, and the hint in the task does not help - two ways.

The first is a manual overkill of the obvious: an empty password (Enter), the name of the file, the words from the description of the task, "password", "123456". In CTF, the authors often hide the password right in the condition of the tack - read more carefully.

The second is automatic overkill. stegcracker (pip install stegcracker) – a wrapper over steghide, sorting through passwords from the dictionary:

stegcracker cover.jpg /usr/share/wordlists/rockyou.txt

On typical CTF-passes of the middle level, the password is usually in a minute - the authors use dictionary words.

If stegcracker is not installed – minimum bash script:

while read pass; do
steghide extract -sf cover.jpg -p "$pass" -xf out.txt 2>/dev/null
if [ $? -eq 0 ]; then
echo "Found: $pass"
break
fi
done < wordlist.txt

Not the fastest way, but works without addiction.
binwalk: extracting nested files

binwalk scans the file for signatures of known formats inside it. This is a key tool for tasks like "file doll" - when a ZIP archive is hidden inside the picture, another picture inside the archive, and a flag in it. According to Trail of Bits CTF Field Guide, files-within-files are one of the most frequent designs in forensics.

Scan: binwalk image.jpg will show a list of signatures with their offsets. If there are lines like “Zip archive data” or “gzip compressed data” with a shift of more than zero in the output, another file sits inside the file.

Extraction: binwalk -e image.jpg automatically get the found in the directory _image.jpg.extracted/. After extracting, check the content through ls -la and every file through file Make sure the recovered is not beaten.

Manual extraction through dd: if -e fails – dd if=image.jpg of=extracted.zip bs=1 skip=45678, where 45678 – offset from the output binwalk (DECIMAL column).
Binwalk traps and false positives

First trap: binwalk only recognizes headline signatures. If the author of the tack inserted the file without a standard title or with a broken signature, the binwalk will miss it. Here saves hex-editor (xxd, HxD, Bless) and manual search of characteristic bytes.

Second: nested archives. Flag binwalk -e pulls out the first level, but there may be more archives inside. Run each extracted file through the entire algorithm again — file, strings, binwalk. Don't be lazy.

Third: false signatures. binwalk can mistake a random byte sequence by the header gzip or LZMA. If the extracted file turned out to be garbage (zero size, unreadable contents) is a phantom. Don't waste your time.

The alternative is the utility, which extracts files on headlines and footers. Sometimes the idear finds what the binwalk misses. Keep both in the arsenal.
Steganography in audio files

Audio steganography in CTF is less common than pictures, but the tasks for it are consistently caught in the category of forensics. The main formats are WAV and MP3. Two main techniques are spectrograms and LSBs in WAV samples.
Spectrograms in Audacity and Sonic Visualiser

The most common method of steganography in audio files on CTF is text or image drawn in a spectrogram. The file sounds like noise or distorted music, but you open it in the spectral analyzer - and you see the flag. It's beautiful when you know where to look.

Audacity is a free audio editor. Open the file, click on the track name on the left and select Spectrogram. By default, a range of up to 8 kHz is displayed – this is often not enough. In the spectrogram settings, increase the maximum frequency to 22050 Hz, and Window Size to 2048 or 4096 for the best resolution. Sometimes the message is hidden above 16 kHz - without the correct settings you simply will not see it.

Sonic Visualiser is a specialized tool for audio analysis. Layer → Add Spectrogram — and you get a spectrogram with more flexible settings. For complex audio-tasks it is more convenient Audicity.

Basic checks for audio are the same: strings audio.wav | grep flag, exiftool audio.wav, binwalk audio.wav – the flag can be in metadata or finished after audio data with plain text. stegide works with WAV and AU: steghide extract -sf audio.wav Do not forget to try an empty password.
LSB in WAV files

Similar to images, data can be written in junior bits of audio samples. For WAV, there is no one-size-fits-all tool like zsteg—often having to write a short Python script:

from scipy.io.wavfile import read
rate, samples = read('stego.wav')
bits = [s & 1 for s in samples.flatten()]
msg = ''.join(chr(int(''.join(map(str, bits[i:i+8])), 2))
for i in range(0, min(len(bits), 800), 8))
print(msg)

The script pulls the LSB out of each sample, collects bits into bytes, and decodes like ASCII. Limiting up to 800 bits (100 characters) – not to wait for the entire file to be processed. On a real tack, you may need to adapt: stereo vs mono, 16-bit vs 8-bit samples, another order of bits. But for the start enough for the eyes.
Checklist tools for CTF steganography

The table below is a compact cheat sheet. The file format defines the starter set of tools for extracting data from PNG, JPG, WAV and other formats.
Format The instrument Team What's looking for
PNG/BMP zsteg zsteg file.png LSB data in all channels
PNG/BMP Stegsolve GUI, Data Extract Visual analysis of bit planes
JPEG/BMP steghide steghide extract -sf file.jpg Built-in data (with or without password)
WAV/AU steghide steghide extract -sf file.wav Built-in data
WAV/MP3 Audacity Spectrogram view Text/image in the spectrumc
GIF/APNG Stegsolve Frame Browser Data in separate frames
Anybody Binwalk binwalk -e file Input files
Anybody exiftool exiftool file Hidden metadata
Anybody strings strings file \| grep flag Text in the open
Anybody File file unknown_file Real file format

The order in the table is a priority: first a format-specific tool, then universal.
 
Top Bottom