Determine the real type of file: file utility and magic bytes
The first rule of CTF steganography is not to trust the extension. File challenge.txt may be a PNG image, and photo.jpg – ZIP archive with flag inside. The authors of the Tasks replace the extensions constantly - cheap and angry, but inexperienced this slows down on a flat spot.
The utility file determines the format for magical bytes - signature sequences at the beginning of the file. Launch elementary: file challenge.txt. If the answer is PNG image data, 800 x 600, 8-bit/color RGBA instead of the expected text - the extension is changed, work with the picture.
When file shows simply data without a specific type – the file is either damaged or the title is changed intentionally. Lezem in hex: xxd challenge.txt | head -5. Magic bytes of the main formats that are worth knowing by heart:
89 50 4E 47 – PNG
FF D8 FF – JPEG
52 49 46 46 – WAV and other RIFF containers
50 4B 03 04 – ZIP archive
42 4D – BMP
47 49 46 38 – GIF
If the signature does not match any known format, but the context of the task indicates the image – the title is damaged intentionally. This is a separate subcategory of stego-tasks: restore magic bytes through the hex-editor (HxD on Windows, hexedit on Linux) and continue the analysis. On one CTF I got PNG with the first four bytes rubbed — file showed data, but xxd immediately issued IHDR chank on the right shift. He wrote 89 50 4E 47 - and the picture opened.
When the file shows an incomplete picture
file analyzes only the beginning of the file. If after the correct PNG (for the marker IEND) completed by ZIP archive — file will show PNG image data and keep quiet about ZIP. With JPEG the same story: data after the marker FF D9 (the end of the JPEG flow) does not enter the analysis. Therefore one file not enough – binwalk will scan the entire file on the nested structures in the next steps. But the first step always file: without knowledge of the real format it is impossible to choose the right tool further.
File metadata analysis: exiftool and hidden fields
Metadata is the first place where flags are hidden on the entry-level CTF. EXIF-tags in JPEG, text chanks tEXt, zTXt, iTXt in PNG, ID3-tags in MP3 - all these are containers where you can write arbitrary text, and standard viewing tools will not show it.
exiftool reads metadata of almost any format: exiftool challenge.jpg. In the output, look for non-standard fields: Comment, Artist, Description, User Comment, XP Comment, GPS Position. On forensics CTF assignments the flag regularly turns out to be in Comment or in the custom tag that the authors added manually.
GPS-geolocation - a separate class of tasks at the interface of steganography and OSINT. If there are metadata GPS Latitude and GPS Longitude – coordinates indicate a specific place whose name is the flag. A classic example is the EXIF-Metadata tack on root-me.org: a picture is given, you need to define the city by GPS coordinates. Coordinates are in the Google Maps or OpenStreetMap – and ready.
Nuance that knocks down beginners: the PNG format does not technically support the EXIF standard. Windows does not show metadata in PNG file properties. But PNG stores similar data in text chanks (tEXt for unpressed text, zTXt for the compressed, iTXt for Unicode) – and exiftool They are pulled out without problems. Do not pass exiftool just because the file is PNG.
To quickly search for a flag in metadata - a conveyor with grep: exiftool challenge.png | grep -iE "flag|ctf|key|secret|hint|pass". This cuts off dozens of lines of technical information and leaves only fields with typical keywords. Alternative to Exiftool – Utility exiv2, works similarly: exiv2 challenge.jpg.
Lines and hex analysis: how to find hidden data in a file
strings extracts all readable text sequences from binary files. Basic challenge: strings challenge.png | grep -i flag. The flag can be finished at the end of the file by the usual ASCII text, inserted between the PNG chanks, or added to the unused JPEG area. The simplest kind of data hiding in files, but on the entry-level CTF is constantly found.
Default strings outputs sequences from four characters. For short flags, lower the threshold: strings -n 3 challenge.png. Be prepared for garbage - there are a lot of false coincidences on three-character strings. In the opposite direction — strings -n 8 show only the lines from the eight characters, cutting off most of the noise.
If strings nothing gave – look at the hex-presentation: xxd challenge.png | tail -20. Data complied after the end-of-file marker (IEND in PNG, FF D9 in JPEG), seen in the hex dump as text or as signatures of other formats. Immediately discovered lines in Base64 (Characteristic sets A-Za-z0-9+/=) and non-standard patterns: repetitive bytes, suspiciously long zero areas.
When strings give a false sense of security
strings works line-by-line - looking for printable sequences of printable characters, separated by unprintable bytes. If the file is generated programmatically without translations of strings, all the information may be in one giant line with debris. In such cases, take grep -a "flag" challenge.png – direct search for a substring in a binary file without a line-by-line breakdown. It's stupid, but it works.
Binwalk: extracting nested files and analyzing archives
binwalk is a key tool for detecting hidden information nested inside files. It scans the binary file by signatures of known formats and shows all the found structures with their offsets (offset).
Launch: binwalk challenge.png. A typical output for PNG with nested ZIP: binwalk finds a PNG header on offset 0 and the ZIP archive signature further by file. Extraction: binwalk -e challenge.png – the utility creates a directory _challenge.png.extracted with the files found.
binwalk challenge.png
binwalk -e challenge.png
binwalk -eM challenge.png
ls _challenge.png.extracted/
A warning that will save nerves: binwalk gives false positives. Especially on JPEG – the internal structure of JPEG contains markers that binwalk interprets as signatures of other formats. If the binwalk shows dozens of “invested files” in a regular JPEG, it’s almost certainly false positives. Check the extracted files: zero size or inability to open – garbage.
Alternative – foremost, recovers files by titles and feet: foremost -i challenge.png. . works better when binwalk finds the signature, but can’t define the boundaries of the file – looking for a pair of “header + footer” and cuts the data between them.
Protected archives and recursive analysis
On CTF of medium complexity, the authors put files recursively: PNG → ZIP → PNG → ZIP → flag.txt. The doll. Flag -eM in binwalk processes such cases automatically - extracts nested files to the last level.
If the archive is protected by a password, fcrackzip -u -D -p wordlist.txt extracted.zip for the dictionary. Distributed reception of authors: the password from the archive is hidden in the metadata of the original file. A step with an exiftool early on can give an answer that will only be needed here – record all suspicious lines from metadata. I was burned on this: I leafed through the exiftool conclusion, reached the steamed ZIP and had to return.
LSB-steganography in CTF images: zsteg and stegsolve
LSB (Least Significant Bit) is the most common method of steganography in CTF images. The lower bits of color channels (R, G, B) are replaced by hidden message bits. Visually, the image does not change - the eye does not distinguish the difference in one bit of pixel brightness.
For detection of LSB steganography in PNG and BMP — zsteg. Ruby-utility, put through gem install zsteg. Main team: zsteg -a challenge.png – launches all available analysis methods. zsteg checks different order of bits (LSB and MSB), different channels (RGB, BGR, RBG and so on), different directions of pixel circumvention (on rows, by columns).
If zsteg has detected payload, we extract specific data: zsteg -E "b1,rgb,lsb,xy" challenge.png > extracted.txt. Parameters: b1 – the first (younger) bit, rgb – order of channels, lsb – from the younger bat, xy – bypassing pixels on the lines from left to right.
Principle Limitation: zsteg only works with PNG and BMP. On JPEG LSB analysis via zsteg is useless – loss compression destroys the younger bits at each resake. If steganography is suspected in JPEG, this is the territory of steghide, about it below.
Stegsolve: visual analysis of bit planes
Stegsolve is a Java application for manual image analysis for individual bit layers. Launch: java -jar stegsolve.jar. The program allows you to switch between the bit planes of each channel. If a QR code or text is hidden in the zero bit of the red channel, when viewing the layer Red plane 0 he'll show up.
Key stegsolve modes for finding a flag in a CTF image:
Data Extract is a manual selection of specific bits and channels. Allows you to try non-standard combinations that zsteg could miss.
Image Combiner – XOR or other operations on two images. It works when the original and stego version are given in the dug: the difference will show exactly those pixels that are modified to hide the data.
Frame Browser is a frame-by-frame view of GIF animations. The flag can be hidden in one frame flashing too fast for the eye.
Stegsolve is indispensable when zsteg finds nothing: manual viewing of bit planes detects patterns that automatic analysis passes. Especially if the data is recorded in MSB instead of LSB or use a non-standard order of channels.
Steghide: data extraction and the password brutforce
steghide — C++-utility for embedding and extracting data in JPEG, BMP, WAV and AU. In CTF, it is the primary steganography tool for JPEG – virtually the only popular option that works correctly with this format.
Verification of the availability of nested data: steghide info challenge.jpg. The utility will tell you if there is a built-in file and request a password. The first action is an attempt to extract with an empty password: steghide extract -sf challenge.jpg -p "". On entry-level CTF, the authors often leave stegide without protection. An empty password is literally the first thing to try, to any brutforce.
If the password is not empty, two tools to choose from:
StegCracker – Python wrapper over steghide, moves passwords from the dictionary. Put through pip install stegcracker, but works slowly: each password is checked through the steghide call as a separate process.
StegseekStegseek - written in C++, works on orders of magnitude faster StegCracker due to direct access to steghide data without re-running the process. If you have a choice, take a stegseek.
stegseek challenge.jpg /usr/share/wordlists/rockyou.txt
Typical errors in this step: forget to try an empty password before running a long brothforce and use a small dictionary. On CTF passwords for stegide are usually taken from standard lists like rockyou.txt - there is no point in inventing something exotic.
Hidden data in audio: spectrograms and LSB-coding
Audio steganography is less common on CTF images, but it brings more points – the authors find it more difficult. Two main methods: visual information in the spectrogram and LSB-coding in WAV samples.
Spectrogram: hidden images in the frequency spectrum
The text or image is embedded in the frequency spectrum of the audio file. With ordinary listening - noise, hum or ordinary music. But when switching to a spectrogram in the audio editor, a hidden picture is manifested: QR code, text with a flag or a hint.
In Audacity: open the WAV file, click on the track name on the left → select “Spectrogram” instead of “Waveform.” Adjust the frequency range – the data is sometimes hidden in ultrasound above 15–18 kHz, where the ear does not hear anything. Sonic Visualiser gives more flexible control: Layer → Add Spectrogram with FFT window setting, color palette and frequency scale.
LSB in WAV files
The principle is the same as in the images: the younger bits of audio samples are replaced by bits of secret message. For extraction – WavSteg: python3 WavSteg.py -r -s challenge.wav -o output.txt. The utility reads the LSB of each sample and collects the original message from them.
Basic checks for audio files are the same as for images: file, strings, exiftool, binwalk. In the WAV file, you can invest ZIP through the save, hide the flag in the ID3 metadata, or finish the ASCII string after the main data. steghide supports WAV and AU — check through steghide info challenge.wav.
For MP3, the situation is different: loss compression makes LSB-stego impossible (as in JPEG). If the tack contains MP3, convert via ffmpeg -i challenge.mp3 challenge.wav and analyze the WAV. But in practice, in MP3-tasks, data is more often hidden in a spectrogram or metadata, rather than in LSB.
Steganography in Real Attacks: Communication with MITRE ATT&CK
Steganography is not only a CTF category. In real attacks, it is used to circumvent the means of protection and concealment of communications. In the MITRE ATT&CK matrix, steganography appears in at least two techniques:
Steganography (T1001.002, Command and Control) – Control commands hide inside images or audio files transmitted through legitimate channels. Network monitoring tools see the usual HTTPS traffic with pictures and do not notice C2 instructions encoded in pixels.
Steganography (T1027.003, Defense Evasion) - payload of the malware is embedded in the image and extracted already on the infected host. The file looks like a normal picture when statically scanned with an antivirus – nothing suspicious.
After extracting hidden data, the malwar decodes them on the host – this stage is described by Deobfuscate/Decode Files or Information (T1140, Defense Evasion) technique. Bundle T1027.003 + T1140 — standard chain for delivering payloads through steganography in real incidents.
Understanding these techniques turns CTF skills into practical: if you know how to extract data through zsteg and steghide, you understand how the attackers hide communications. This is the basis for building the detection rules.
The first rule of CTF steganography is not to trust the extension. File challenge.txt may be a PNG image, and photo.jpg – ZIP archive with flag inside. The authors of the Tasks replace the extensions constantly - cheap and angry, but inexperienced this slows down on a flat spot.
The utility file determines the format for magical bytes - signature sequences at the beginning of the file. Launch elementary: file challenge.txt. If the answer is PNG image data, 800 x 600, 8-bit/color RGBA instead of the expected text - the extension is changed, work with the picture.
When file shows simply data without a specific type – the file is either damaged or the title is changed intentionally. Lezem in hex: xxd challenge.txt | head -5. Magic bytes of the main formats that are worth knowing by heart:
89 50 4E 47 – PNG
FF D8 FF – JPEG
52 49 46 46 – WAV and other RIFF containers
50 4B 03 04 – ZIP archive
42 4D – BMP
47 49 46 38 – GIF
If the signature does not match any known format, but the context of the task indicates the image – the title is damaged intentionally. This is a separate subcategory of stego-tasks: restore magic bytes through the hex-editor (HxD on Windows, hexedit on Linux) and continue the analysis. On one CTF I got PNG with the first four bytes rubbed — file showed data, but xxd immediately issued IHDR chank on the right shift. He wrote 89 50 4E 47 - and the picture opened.
When the file shows an incomplete picture
file analyzes only the beginning of the file. If after the correct PNG (for the marker IEND) completed by ZIP archive — file will show PNG image data and keep quiet about ZIP. With JPEG the same story: data after the marker FF D9 (the end of the JPEG flow) does not enter the analysis. Therefore one file not enough – binwalk will scan the entire file on the nested structures in the next steps. But the first step always file: without knowledge of the real format it is impossible to choose the right tool further.
File metadata analysis: exiftool and hidden fields
Metadata is the first place where flags are hidden on the entry-level CTF. EXIF-tags in JPEG, text chanks tEXt, zTXt, iTXt in PNG, ID3-tags in MP3 - all these are containers where you can write arbitrary text, and standard viewing tools will not show it.
exiftool reads metadata of almost any format: exiftool challenge.jpg. In the output, look for non-standard fields: Comment, Artist, Description, User Comment, XP Comment, GPS Position. On forensics CTF assignments the flag regularly turns out to be in Comment or in the custom tag that the authors added manually.
GPS-geolocation - a separate class of tasks at the interface of steganography and OSINT. If there are metadata GPS Latitude and GPS Longitude – coordinates indicate a specific place whose name is the flag. A classic example is the EXIF-Metadata tack on root-me.org: a picture is given, you need to define the city by GPS coordinates. Coordinates are in the Google Maps or OpenStreetMap – and ready.
Nuance that knocks down beginners: the PNG format does not technically support the EXIF standard. Windows does not show metadata in PNG file properties. But PNG stores similar data in text chanks (tEXt for unpressed text, zTXt for the compressed, iTXt for Unicode) – and exiftool They are pulled out without problems. Do not pass exiftool just because the file is PNG.
To quickly search for a flag in metadata - a conveyor with grep: exiftool challenge.png | grep -iE "flag|ctf|key|secret|hint|pass". This cuts off dozens of lines of technical information and leaves only fields with typical keywords. Alternative to Exiftool – Utility exiv2, works similarly: exiv2 challenge.jpg.
Lines and hex analysis: how to find hidden data in a file
strings extracts all readable text sequences from binary files. Basic challenge: strings challenge.png | grep -i flag. The flag can be finished at the end of the file by the usual ASCII text, inserted between the PNG chanks, or added to the unused JPEG area. The simplest kind of data hiding in files, but on the entry-level CTF is constantly found.
Default strings outputs sequences from four characters. For short flags, lower the threshold: strings -n 3 challenge.png. Be prepared for garbage - there are a lot of false coincidences on three-character strings. In the opposite direction — strings -n 8 show only the lines from the eight characters, cutting off most of the noise.
If strings nothing gave – look at the hex-presentation: xxd challenge.png | tail -20. Data complied after the end-of-file marker (IEND in PNG, FF D9 in JPEG), seen in the hex dump as text or as signatures of other formats. Immediately discovered lines in Base64 (Characteristic sets A-Za-z0-9+/=) and non-standard patterns: repetitive bytes, suspiciously long zero areas.
When strings give a false sense of security
strings works line-by-line - looking for printable sequences of printable characters, separated by unprintable bytes. If the file is generated programmatically without translations of strings, all the information may be in one giant line with debris. In such cases, take grep -a "flag" challenge.png – direct search for a substring in a binary file without a line-by-line breakdown. It's stupid, but it works.
Binwalk: extracting nested files and analyzing archives
binwalk is a key tool for detecting hidden information nested inside files. It scans the binary file by signatures of known formats and shows all the found structures with their offsets (offset).
Launch: binwalk challenge.png. A typical output for PNG with nested ZIP: binwalk finds a PNG header on offset 0 and the ZIP archive signature further by file. Extraction: binwalk -e challenge.png – the utility creates a directory _challenge.png.extracted with the files found.
binwalk challenge.png
binwalk -e challenge.png
binwalk -eM challenge.png
ls _challenge.png.extracted/
A warning that will save nerves: binwalk gives false positives. Especially on JPEG – the internal structure of JPEG contains markers that binwalk interprets as signatures of other formats. If the binwalk shows dozens of “invested files” in a regular JPEG, it’s almost certainly false positives. Check the extracted files: zero size or inability to open – garbage.
Alternative – foremost, recovers files by titles and feet: foremost -i challenge.png. . works better when binwalk finds the signature, but can’t define the boundaries of the file – looking for a pair of “header + footer” and cuts the data between them.
Protected archives and recursive analysis
On CTF of medium complexity, the authors put files recursively: PNG → ZIP → PNG → ZIP → flag.txt. The doll. Flag -eM in binwalk processes such cases automatically - extracts nested files to the last level.
If the archive is protected by a password, fcrackzip -u -D -p wordlist.txt extracted.zip for the dictionary. Distributed reception of authors: the password from the archive is hidden in the metadata of the original file. A step with an exiftool early on can give an answer that will only be needed here – record all suspicious lines from metadata. I was burned on this: I leafed through the exiftool conclusion, reached the steamed ZIP and had to return.
LSB-steganography in CTF images: zsteg and stegsolve
LSB (Least Significant Bit) is the most common method of steganography in CTF images. The lower bits of color channels (R, G, B) are replaced by hidden message bits. Visually, the image does not change - the eye does not distinguish the difference in one bit of pixel brightness.
For detection of LSB steganography in PNG and BMP — zsteg. Ruby-utility, put through gem install zsteg. Main team: zsteg -a challenge.png – launches all available analysis methods. zsteg checks different order of bits (LSB and MSB), different channels (RGB, BGR, RBG and so on), different directions of pixel circumvention (on rows, by columns).
If zsteg has detected payload, we extract specific data: zsteg -E "b1,rgb,lsb,xy" challenge.png > extracted.txt. Parameters: b1 – the first (younger) bit, rgb – order of channels, lsb – from the younger bat, xy – bypassing pixels on the lines from left to right.
Principle Limitation: zsteg only works with PNG and BMP. On JPEG LSB analysis via zsteg is useless – loss compression destroys the younger bits at each resake. If steganography is suspected in JPEG, this is the territory of steghide, about it below.
Stegsolve: visual analysis of bit planes
Stegsolve is a Java application for manual image analysis for individual bit layers. Launch: java -jar stegsolve.jar. The program allows you to switch between the bit planes of each channel. If a QR code or text is hidden in the zero bit of the red channel, when viewing the layer Red plane 0 he'll show up.
Key stegsolve modes for finding a flag in a CTF image:
Data Extract is a manual selection of specific bits and channels. Allows you to try non-standard combinations that zsteg could miss.
Image Combiner – XOR or other operations on two images. It works when the original and stego version are given in the dug: the difference will show exactly those pixels that are modified to hide the data.
Frame Browser is a frame-by-frame view of GIF animations. The flag can be hidden in one frame flashing too fast for the eye.
Stegsolve is indispensable when zsteg finds nothing: manual viewing of bit planes detects patterns that automatic analysis passes. Especially if the data is recorded in MSB instead of LSB or use a non-standard order of channels.
Steghide: data extraction and the password brutforce
steghide — C++-utility for embedding and extracting data in JPEG, BMP, WAV and AU. In CTF, it is the primary steganography tool for JPEG – virtually the only popular option that works correctly with this format.
Verification of the availability of nested data: steghide info challenge.jpg. The utility will tell you if there is a built-in file and request a password. The first action is an attempt to extract with an empty password: steghide extract -sf challenge.jpg -p "". On entry-level CTF, the authors often leave stegide without protection. An empty password is literally the first thing to try, to any brutforce.
If the password is not empty, two tools to choose from:
StegCracker – Python wrapper over steghide, moves passwords from the dictionary. Put through pip install stegcracker, but works slowly: each password is checked through the steghide call as a separate process.
StegseekStegseek - written in C++, works on orders of magnitude faster StegCracker due to direct access to steghide data without re-running the process. If you have a choice, take a stegseek.
stegseek challenge.jpg /usr/share/wordlists/rockyou.txt
Typical errors in this step: forget to try an empty password before running a long brothforce and use a small dictionary. On CTF passwords for stegide are usually taken from standard lists like rockyou.txt - there is no point in inventing something exotic.
Hidden data in audio: spectrograms and LSB-coding
Audio steganography is less common on CTF images, but it brings more points – the authors find it more difficult. Two main methods: visual information in the spectrogram and LSB-coding in WAV samples.
Spectrogram: hidden images in the frequency spectrum
The text or image is embedded in the frequency spectrum of the audio file. With ordinary listening - noise, hum or ordinary music. But when switching to a spectrogram in the audio editor, a hidden picture is manifested: QR code, text with a flag or a hint.
In Audacity: open the WAV file, click on the track name on the left → select “Spectrogram” instead of “Waveform.” Adjust the frequency range – the data is sometimes hidden in ultrasound above 15–18 kHz, where the ear does not hear anything. Sonic Visualiser gives more flexible control: Layer → Add Spectrogram with FFT window setting, color palette and frequency scale.
LSB in WAV files
The principle is the same as in the images: the younger bits of audio samples are replaced by bits of secret message. For extraction – WavSteg: python3 WavSteg.py -r -s challenge.wav -o output.txt. The utility reads the LSB of each sample and collects the original message from them.
Basic checks for audio files are the same as for images: file, strings, exiftool, binwalk. In the WAV file, you can invest ZIP through the save, hide the flag in the ID3 metadata, or finish the ASCII string after the main data. steghide supports WAV and AU — check through steghide info challenge.wav.
For MP3, the situation is different: loss compression makes LSB-stego impossible (as in JPEG). If the tack contains MP3, convert via ffmpeg -i challenge.mp3 challenge.wav and analyze the WAV. But in practice, in MP3-tasks, data is more often hidden in a spectrogram or metadata, rather than in LSB.
Steganography in Real Attacks: Communication with MITRE ATT&CK
Steganography is not only a CTF category. In real attacks, it is used to circumvent the means of protection and concealment of communications. In the MITRE ATT&CK matrix, steganography appears in at least two techniques:
Steganography (T1001.002, Command and Control) – Control commands hide inside images or audio files transmitted through legitimate channels. Network monitoring tools see the usual HTTPS traffic with pictures and do not notice C2 instructions encoded in pixels.
Steganography (T1027.003, Defense Evasion) - payload of the malware is embedded in the image and extracted already on the infected host. The file looks like a normal picture when statically scanned with an antivirus – nothing suspicious.
After extracting hidden data, the malwar decodes them on the host – this stage is described by Deobfuscate/Decode Files or Information (T1140, Defense Evasion) technique. Bundle T1027.003 + T1140 — standard chain for delivering payloads through steganography in real incidents.
Understanding these techniques turns CTF skills into practical: if you know how to extract data through zsteg and steghide, you understand how the attackers hide communications. This is the basis for building the detection rules.