Skip to main content

Blast from the past picoCTF 2024 Solution

A forensics challenge focused on image metadata. Manipulate timestamps embedded in a photo file to satisfy a validation check.

Published: April 3, 2024Updated: August 25, 2026

Description

The judge for these pictures is a real fan of antiques. Can you age this photo to the specifications? Set the timestamps on this picture to 1970:01:01 00:00:00.001+00:00 with as much precision as possible for each timestamp. In this example, +00:00 is a timezone adjustment. Any timezone is acceptable as long as the time is equivalent. As an example, this timestamp is acceptable as well: 1969:12:31 19:00:00.001-05:00. For timestamps without a timezone adjustment, put them in GMT time (+00:00). The checker program provides the timestamp needed for each.

EXIF editing

Download original.jpg, rename it to original_modified.jpg, and keep a backup.

Install exiftool and a hex editor (Bless works well on Linux).

bash
wget https://artifacts.picoctf.net/c_mimas/91/original.jpg -O original_modified.jpg

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1Set EXIF sub-second fields
    Observation
    The checker wants millisecond precision, the .001 part, in every timestamp. exiftool's -AllDates does not reach that, so set the SubSec tags explicitly.
    Use exiftool to set SubSecCreateDate, SubSecDateTimeOriginal, and SubSecModifyDate to 1970:01:01 00:00:00.001. The checker verifies each field independently.
    bash
    exiftool -SubSecCreateDate='1970:01:01 00:00:00.001' \
      -SubSecDateTimeOriginal='1970:01:01 00:00:00.001' \
      -SubSecModifyDate='1970:01:01 00:00:00.001' original_modified.jpg
    What didn't work first

    Tried: Use exiftool -AllDates='1970:01:01 00:00:00.001' to set all timestamps in one flag.

    -AllDates writes only the three standard EXIF fields and skips the sub-second tags entirely. The checker validates each SubSec field separately, so they keep their original values and every one of them fails.

    Tried: Set the timestamp without the millisecond component: exiftool -SubSecCreateDate='1970:01:01 00:00:00' .

    Sub-seconds are stored as a fractional suffix on the time string. Leave off the .001 and the field ends up blank or zero, which the checker reports as unset or mismatched even though the date itself is right.

    Learn more

    EXIF (Exchangeable Image File Format) embeds metadata inside JPEG, TIFF, and other image formats. Every camera and smartphone writes dozens of fields (shutter speed, GPS, camera model, multiple timestamps) into the file before the pixel data.

    Timestamps live in several fields: DateTimeOriginal (when the shutter fired), CreateDate (file creation), and ModifyDate (last edit). The -AllDates flag covers these standard EXIF fields in one shot, but it skips Samsung-proprietary blocks like Image_UTC_Data, which is why hex editing is needed in the next step.

    In digital forensics, timestamps are crucial evidence. Investigators compare EXIF timestamps against file-system timestamps (mtime, atime, ctime) and network logs to build timelines. Knowing how to manipulate (and detect manipulation of) these fields is a core skill on both sides.

  2. Step 2Patch Samsung:TimeStamp
    Observation
    One timestamp still fails after every standard SubSec field is set. A vendor block outside the EXIF IFD, Samsung's Image_UTC_Data, holds its own millisecond Unix timestamp, and only a hex editor reaches it.
    Open the JPEG in Bless. Search for the ASCII string Image_UTC_Data; the 13-digit number that follows it (e.g. 1700513181420) is the millisecond timestamp. Replace the digits with 0000000000001 (epoch + 1 ms), keeping the byte length identical.
    Learn more

    Many Android manufacturers embed proprietary metadata blocks in JPEG files that sit outside the standard EXIF IFD structure. Samsung's Image_UTC_Data block stores a Unix timestamp in milliseconds as a plain decimal ASCII string embedded in the file's bytes.

    To find the field in a hex editor, search for the ASCII string Image_UTC_Data. The 13-digit decimal number immediately after the label is the millisecond timestamp. Overwrite just those digits in place so the file size stays identical; otherwise the JPEG offsets shift and the structure breaks.

    The target value 0000000000001 is 1 millisecond past Unix epoch (1970-01-01 00:00:00.001 UTC), matching the EXIF fields you set in the previous step. Tools like grep -b (byte-offset grep) or Python's bytes.find() can locate the pattern programmatically if you prefer scripting to a GUI hex editor.

  3. Step 3Submit and verify
    Observation
    There are two ports, one for upload and one for the checker. Pipe the raw file bytes to the upload port with netcat, then connect separately to the checker to see whether every timestamp matched.
    Pipe the modified file to the uploader port, then connect to the checker. Once every timestamp reads 1970:01:01 00:00:00.001, the checker prints the flag.
    bash
    nc -w 2 mimas.picoctf.net <UPLOAD_PORT_FROM_INSTANCE> < original_modified.jpg \
      && nc -d mimas.picoctf.net <CHECKER_PORT_FROM_INSTANCE>

    Expected output

    picoCTF{71m3_7r4v311ng_p1c7ur3_12e0...}
    What didn't work first

    Tried: Upload the original.jpg file directly to the checker port instead of original_modified.jpg.

    The checker reads timestamps from whichever file you send it. Send the untouched original and every field still holds the camera's shoot date, so all of them come back wrong. Apply the rename and the edits to the file you actually pipe over.

    Tried: Connect to the upload port and the checker port simultaneously in one netcat command using a pipe.

    The upload port takes raw file bytes; the checker port is a separate service that reports back afterwards. Chain them with a pipe and the checker's response bytes flow back into the upload socket and corrupt it. Run two netcat calls instead, one redirecting the file in, then a read-only connection to the checker.

    Learn more

    netcat (nc) is the Swiss army knife of networking. The < redirection feeds the file's raw bytes directly into the TCP stream, which is how binary upload services typically work over a raw socket.

    -w 2 sets a 2-second idle timeout so netcat doesn't hang after the server stops sending data. -d on the checker connection disables stdin entirely from the outset, so netcat does not block waiting for terminal input that will never come.

    Using two separate netcat connections (one to upload, one to check) is a common CTF pattern where submission and verification run on different ports. The same raw socket pattern shows up in real assessments when probing custom protocols or pushing files to embedded devices.

Interactive tools
  • Image Metadata ViewerRead EXIF, XMP, JPEG comments, and PNG tEXt / iTXt / zTXt chunks from images entirely in the browser. Highlights flag-like values.

Flag

Reveal flag

picoCTF{71m3_7r4v311ng_p1c7ur3_12e0...}

Once every timestamp reads 1970:01:01 00:00:00.001, the checker returns the flag above.

Key takeaway

An image carries far more than its pixels. EXIF, IPTC, XMP, and vendor blocks hold timestamps, GPS coordinates, camera settings, and arbitrary key-value fields that no ordinary viewer shows. Forensics leans on them for timelines and tamper detection precisely because each layer can be set independently and the layers can contradict each other. exiftool covers the standard structure; vendor extensions need a hex editor, which is what happens whenever a format grows past its original specification.

Related reading

Useful tools for Forensics

Where to go next