The 30-second answer
You were handed an image. The flag is not in the picture you can see; it is in the data wrapped around the picture. That data is the metadata, and the single command that pulls almost all of it out is:
exiftool image.jpg# see everything, including duplicate and unknown tags, grouped by family:exiftool -a -u -g1 image.jpg
Read every line of the output. Flags love to sit in the Comment, Artist, UserComment, ImageDescription, or Copyright fields, and in the GPS block. If exiftool comes up empty, drop to strings image.jpg | grep -i pico and, for PNG specifically, look at the text chunks (tEXt, zTXt, iTXt). The rest of this post is the why and the edge cases, but those three moves solve the large majority of beginner metadata challenges.
-a -u -g1. The -a keeps duplicate tags, -u shows tags exiftool would normally hide as unknown, and -g1 groups by the location the tag lives in so you can see whether a value came from EXIF, XMP, or IPTC. Authors hide flags exactly where the default view would skip them.What metadata actually is, and where it lives
An image file is not just pixels. It is a container, and alongside the compressed pixel data it carries labelled records describing the photo: when it was taken, what camera took it, the GPS coordinates, a copyright string, a caption, a thumbnail. Those records are the metadata. A CTF author can type anything they like into one of those fields, which is why metadata is one of the first places a flag goes.
There are three common metadata standards you will meet, often in the same file:
- EXIF (Exchangeable Image File Format) is the camera-centric one: exposure, ISO, timestamps, GPS, camera make and model, and free-text fields like
UserCommentandImageDescription. It is stored in the APP1 segment of a JPEG. The spec is published by the CIPA EXIF standard. - XMP (Extensible Metadata Platform) is an XML blob, so it is human-readable if you open the file in a text editor. It holds titles, descriptions, ratings, and arbitrary custom namespaces. A flag dropped into XMP is often visible with plain
stringsbecause it is just text. - IPTC is the news and stock-photo standard: caption, keywords, byline, credit, headline. Editorial tools write here, so do CTF authors who want a slightly less obvious field than
Comment.
The picture is the decoy. The metadata is the message. Most forensics newcomers stare at the pixels for an hour before they read the wrapper.
PNG files do not use EXIF the same way. Instead they carry text in dedicated chunks, which we cover below. The mental model that carries across all formats: a flag in metadata is a labelled string sitting next to the image, not woven into it.
exiftool is always the first move
ExifTool by Phil Harvey reads and writes metadata for hundreds of formats. It is the single most useful tool in image forensics and it should be the first thing you run on any image, every time, before you think about anything cleverer.
# install (Debian / Ubuntu / Kali)sudo apt install libimage-exiftool-perl# the default dump: clean, human-groupedexiftool image.jpg# the thorough dump: ALL tags, unknown tags, grouped by family 1exiftool -a -u -g1 image.jpg# pull one field by name (case-insensitive, fuzzy)exiftool -Comment image.jpgexiftool -UserComment image.jpg# machine-readable output if you want to grep hardexiftool -j image.jpg # JSONexiftool -s -G image.jpg # short tag names with group prefix
The default exiftool image.jpg is enough to win many challenges on its own. When it is not, -a -u -g1 is the escalation: it refuses to hide anything. Authors who know players run the default sometimes tuck the flag into a duplicate tag or a vendor-specific MakerNote that only shows up with -u.
Comment: exiftool -Comment -r ./photos/ | grep -i pico.The fields where flags actually hide
Once you have the full dump, you are scanning for a value that does not belong. Camera fields contain camera-shaped data; a flag stands out because it reads like English, like base64, or literally like picoCTF{...}. These are the usual homes:
CommentandUserCommentare the classics. A flag pasted straight in, or base64-encoded, lives here more often than anywhere else.Artist,Copyright,ImageDescription, and IPTCCaption-Abstractare the second tier: free-text fields a normal photo would leave blank or fill with a name.- GPS coordinates can be a flag by themselves. Sometimes the latitude and longitude point at a landmark whose name is the answer; sometimes the numbers decode to ASCII. Always read
GPSLatitudeandGPSLongitude, and try the coordinates on a map. Software,DocumentName, and the XMPdc:descriptionnamespace catch the overflow when an author wants something less obvious.
exiftool -Comment -b image.jpg | base64 -d. The -b flag outputs the raw binary value with no formatting, which is what you want to pipe into a decoder.PNG text chunks: tEXt, zTXt, and iTXt
PNG stores text differently from JPEG. Instead of an EXIF block it uses dedicated text chunks defined in the PNG specification. There are three, and a flag can sit in any of them:
tEXtis uncompressed Latin-1 text, a keyword plus a value. Visible tostringsand to exiftool.zTXtis the same idea but zlib-compressed, sostringswill not see it. exiftool decompresses it for you.iTXtis international UTF-8 text, optionally compressed. Same story: exiftool reads it, rawstringsmay not.
The reliable way to read all three at once is exiftool, but it helps to confirm the chunks exist:
# exiftool decodes every text chunk type, compressed or notexiftool -a -u -g1 image.png# list the raw chunk structure to SEE which chunks are presentpngcheck -t -v image.png# zTXt is compressed, so plain strings misses it; exiftool catches itexiftool -Comment -Description -Title image.png
zTXt chunk is the single most common reason a PNG challenge looks empty to strings but is not. If strings finds nothing and the challenge is clearly about metadata, you almost certainly have a compressed text chunk. Reach for exiftool or pngcheck -t -v immediately.The embedded thumbnail trick
Many cameras and editors store a small thumbnail copy of the image inside the EXIF block. Here is the trap: when someone crops or paints over the main image, the embedded thumbnail is often left untouched. The visible photo hides the flag with a black box; the thumbnail still shows it. This is a genuine, recurring CTF move.
Extract the thumbnail as a separate file and open it:
# pull the embedded thumbnail out to its own fileexiftool -b -ThumbnailImage image.jpg > thumb.jpg# some files store a larger preview insteadexiftool -b -PreviewImage image.jpg > preview.jpgexiftool -b -JpgFromRaw image.cr2 > full.jpg# then look at itxdg-open thumb.jpg
Compare the thumbnail to the main image side by side. If they differ, the difference is almost always the answer. This is the metadata equivalent of finding an earlier draft of a document in its revision history.
strings and binwalk: the backstop
When exiftool does not surface a flag, the data may not be in a labelled field at all. It might be appended after the image data, stuffed into a comment marker exiftool does not parse, or hidden in a second file concatenated onto the first. Two blunt tools cover this:
# every printable run of 4+ chars; grep for the flag formatstrings -n 6 image.jpg | grep -i 'pico\|flag\|ctf'# include the byte offset so you know WHERE the string sitsstrings -t x image.jpg | grep -i pico# is there a second file hidden inside or appended?binwalk image.jpgbinwalk -e image.jpg # extract anything it recognises
strings is the catch-all that finds plain-text flags wherever they sit. binwalk is for the case where the image is actually a carrier: a ZIP, a second JPEG, or a script appended after the real image ends. If binwalk reports an embedded archive, that is usually the real puzzle and the metadata was a misdirection.
strings only finds printable, uncompressed text. A base64 blob shows up; a zlib-compressed zTXt chunk or genuinely encrypted data does not. A negative strings result never proves the flag is not there; it only proves it is not sitting in plaintext.Metadata is not the same as pixel steganography
This is the distinction that decides which tools you reach for. Metadata lives in the container around the image, in labelled fields you can read with exiftool. Pixel-level steganography hides data inside the pixel values themselves, typically in the least significant bits, where no field name exists and exiftool sees nothing unusual.
Metadata (this post)
Flag sits in EXIF, XMP, IPTC, or a PNG text chunk. Tools: exiftool, strings, pngcheck. Fast to check, always check first.
Pixel stego (other post)
Flag is encoded in the pixel bits. Tools: zsteg, steghide, stegsolve, LSB extractors. exiftool will not find it.
The workflow is sequential: run exiftool and strings first because they are seconds of effort, and only escalate to pixel analysis when the metadata is clean. For the pixel-level half of the picture, see the CTF Steganography guide. When the image turns out to be a carrier for an entirely different file, the Hex Dumps for CTF and Disk Forensics posts cover reading and carving raw bytes.
zsteg and steghide before you have run exiftool, you are skipping the cheap check for the expensive one. Metadata first, pixels second. Always.Writing and adding metadata yourself
You occasionally need to write metadata, not just read it: to confirm how a field is stored, to craft a test image, or because a challenge asks you to round-trip a value. exiftool writes as easily as it reads.
# set a comment (exiftool keeps a _original backup by default)exiftool -Comment='picoCTF{test}' image.jpg# overwrite in place with no backup fileexiftool -overwrite_original -Artist='me' image.jpg# write a PNG text chunkexiftool -PNG:Comment='hello' image.png# strip ALL metadata (useful to prove a field is gone)exiftool -all= image.jpg# copy every tag from one file to anotherexiftool -tagsFromFile source.jpg -all:all dest.jpg
The practical reason to learn the write side is verification. If you are not sure whether a value belongs in EXIF or XMP, write it both ways into a scratch file and re-run exiftool -a -u -g1 to see exactly where it lands. The tool that hides the flag is the same tool that reveals it.
If you would rather not install anything, this site has a browser-based metadata viewer that reads EXIF and common tags client-side, which is handy for a quick first look before you drop to the command line.
picoCTF challenges that are pure metadata
picoCTF leans on metadata for its entry-level forensics, which makes these two the ideal place to drill the workflow above:
- picoCTF 2021 information hands you an image whose flag is reachable through its metadata. It is the canonical "run exiftool, read the fields, decode the value" challenge, and it rewards the
-a -u -g1habit. - picoCTF 2019 Glory of the Garden is the
stringsbackstop in challenge form: the flag is appended to the image rather than living in a named field, so exiftool alone is not enough andstringscloses it out.
Do them in that order. The first teaches you to read labelled fields; the second teaches you that metadata tools have a blind spot and strings covers it.
Quick reference
exiftool cheat sheet
exiftool image.jpg # default dump, always start hereexiftool -a -u -g1 image.jpg # ALL tags, unknown included, groupedexiftool -Comment -b image.jpg | base64 -d # raw field value into a decoderexiftool -b -ThumbnailImage f.jpg > t.jpg # extract embedded thumbnailexiftool -b -PreviewImage f.jpg > p.jpg # extract larger preview if presentexiftool -Comment -r ./photos/ # walk a folder of imagesexiftool -j image.jpg # JSON output for scriptingexiftool -all= image.jpg # strip every tagexiftool -Comment='picoCTF{x}' image.jpg # write a fieldpngcheck -t -v image.png # list PNG chunks (tEXt/zTXt/iTXt)strings -t x image.jpg | grep -i pico # plaintext backstop with offsetsbinwalk -e image.jpg # carve an appended/embedded file
Decision order for a metadata challenge
exiftool image.jpg, thenexiftool -a -u -g1 image.jpg. Read every line.- Scan
Comment,UserComment,Artist,Copyright, IPTC caption, and the GPS block for anything English-shaped or base64-shaped. - PNG? Read the text chunks (exiftool,
pngcheck -t -v). SuspectzTXtifstringsis empty. - Extract the embedded thumbnail and compare it to the visible image.
stringsandbinwalkfor appended or embedded files.- Still nothing? It is probably pixel stego, not metadata. Switch to the steganography toolkit.
Read the wrapper before you study the picture: in a metadata challenge the flag is a labelled string sitting right next to the pixels, and exiftool -a -u -g1 shows you all of them.