
Flash CTF - Carry On
Carry On Writeup
Carry On is a 100 point forensics challenge. The handout is a PNG floor plan of an airport screening hall. The drawing opens in any viewer and has nothing to do with the answer. A Zip archive is attached to the end of the PNG, and the note inside it carries the flag.
Grepping the handout for the flag directly comes up empty:
$ strings checkpoint-plan.png | grep -i skillbit
$
The file is 65163 bytes for a flat line drawing, which is more than a drawing like this needs. The end of the same strings output shows where the rest of it went:
$ strings checkpoint-plan.png | tail -6
note.txtMS
7'?{
Y^_$
[U 4n
b9nm
note.txtPK
A PNG does not store filenames, and PK is the Zip magic. There is a second file sitting at the end of this one.
binwalk checkpoint-plan.png reports the same archive in one line, if you have it installed. It is not needed here.
The join between the two files is visible in a hexdump:
$ grep -abo IEND checkpoint-plan.png
64397:IEND
$ xxd -s 64393 -l 32 checkpoint-plan.png
0000fb89: 0000 0000 4945 4e44 ae42 6082 504b 0304 ....IEND.B`.PK..
0000fb99: 1400 0000 0800 00bd 375d 3bcf d749 8402 ........7];..I..
grep -abo gives the byte offset, which the hexdump needs because IEND can straddle two rows. 49 45 4e 44 ae 42 60 82 is the IEND chunk and its CRC, the last twelve bytes of any PNG. 50 4b 03 04 starts on the next byte and is the local file header of a Zip entry. The image ends at offset 64405 and the archive starts there.
Zip readers work backwards from the end of the file, so the carrier does not need to be stripped off first. unzip reads the PNG as it is:
$ unzip -l checkpoint-plan.png
Archive: checkpoint-plan.png
warning [checkpoint-plan.png]: 64405 extra bytes at beginning or within zipfile
(attempting to process anyway)
Length Date Time Name
--------- ---------- ----- ----
1078 2026-09-23 23:40 note.txt
--------- -------
1078 1 file
The warning names the size of the image it skipped over.
The archive can also be carved out by hand, which gives the same thing as a standalone file:
$ grep -abo $'PK\x03\x04' checkpoint-plan.png
64405:PK
$ dd if=checkpoint-plan.png bs=1 skip=64405 of=payload.zip
758+0 records in
758+0 records out
758 bytes copied, 0.00150303 s, 504 kB/s
$ file payload.zip
payload.zip: Zip archive data, at least v2.0 to extract, compression method=deflate
compression method=deflate is why strings found nothing. The note is compressed, so none of its text exists as text inside the carrier.
Extracting it gives the flag:
$ unzip -o checkpoint-plan.png
Archive: checkpoint-plan.png
warning [checkpoint-plan.png]: 64405 extra bytes at beginning or within zipfile
(attempting to process anyway)
inflating: note.txt
$ grep -o 'SkillBit{[^}]*}' note.txt
SkillBit{0n3_f1l3_c4n_c4rry_4n0th3r}
note.txt contains a lot of text, including the flag.