picoCTF

Riddle Registry

Metadata AnalysisExifToolBase64 DecodingPDF Forensics
Full writeup+

Thought process: find where the PDF could be tampered with.

  • Metadata
  • Hidden strings

For metadata I used ExifTool:

exiftool confidential.pdf
ExifTool Version Number         : 13.50
File Name                       : confidential.pdf
Directory                       : .
File Size                       : 183 kB
File Modification Date/Time     : 2026:02:23 19:05:32+08:00
File Access Date/Time           : 2026:02:23 19:14:25+08:00
File Inode Change Date/Time     : 2026:02:23 19:10:39+08:00
File Permissions                : -rw-r--r--
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.7
Linearized                      : No
Page Count                      : 1
Producer                        : PyPDF2
Author                          : cGljb0NURntwdXp6bDNkX20zdGFkYXRhX2YwdW5kIV8zNTc4NzM5YX0=

I noticed the Author value looked like Base64 (padded with =), so I decoded it:

echo "cGljb0NURntwdXp6bDNkX20zdGFkYXRhX2YwdW5kIV8zNTc4NzM5YX0=" | base64 --decode

This returned: picoCTF{puzzl3d_m3tadata_f0und!_3578739a}

Log Hunt

Log AnalysisString ExtractiongrepLinux CLI
Full writeup+

First thought: search for picoCTF in logs.

strings server.log | grep picoCTF
[1990-08-09 10:00:10] INFO FLAGPART: picoCTF{us3_
[1990-08-09 11:04:27] INFO FLAGPART: picoCTF{us3_
[1990-08-09 11:04:29] INFO FLAGPART: picoCTF{us3_
[1990-08-09 11:04:37] INFO FLAGPART: picoCTF{us3_
[1990-08-09 12:19:23] INFO FLAGPART: picoCTF{us3_
[1990-08-09 12:19:29] INFO FLAGPART: picoCTF{us3_
[1990-08-09 12:19:32] INFO FLAGPART: picoCTF{us3_

That only gave me the start. Next I searched for the closing brace to get the end:

strings server.log | grep '}'
[1990-08-09 10:10:54] INFO FLAGPART: cedfa5fb}
[1990-08-09 10:10:58] INFO FLAGPART: cedfa5fb}
[1990-08-09 10:11:06] INFO FLAGPART: cedfa5fb}
[1990-08-09 11:16:58] INFO FLAGPART: cedfa5fb}
[1990-08-09 11:16:59] INFO FLAGPART: cedfa5fb}
[1990-08-09 11:17:00] INFO FLAGPART: cedfa5fb}
[1990-08-09 12:28:45] INFO FLAGPART: cedfa5fb}
[1990-08-09 12:28:49] INFO FLAGPART: cedfa5fb}
[1990-08-09 12:28:52] INFO FLAGPART: cedfa5fb}

Combining those gave picoCTF{us3_cedfa5fb}, which was wrong. I realized I was missing the middle in snake_case, so I searched for underscores:

strings server.log | grep '_'
[1990-08-09 10:00:10] INFO FLAGPART: picoCTF{us3_
[1990-08-09 10:02:55] INFO FLAGPART: y0urlinux_
[1990-08-09 10:05:54] INFO FLAGPART: sk1lls_
[1990-08-09 10:05:55] INFO FLAGPART: sk1lls_
[1990-08-09 11:04:27] INFO FLAGPART: picoCTF{us3_
[1990-08-09 11:04:29] INFO FLAGPART: picoCTF{us3_
[1990-08-09 11:04:37] INFO FLAGPART: picoCTF{us3_
[1990-08-09 11:09:16] INFO FLAGPART: y0urlinux_
[1990-08-09 11:09:19] INFO FLAGPART: y0urlinux_
[1990-08-09 11:12:40] INFO FLAGPART: sk1lls_
[1990-08-09 11:12:45] INFO FLAGPART: sk1lls_
[1990-08-09 12:19:23] INFO FLAGPART: picoCTF{us3_
[1990-08-09 12:19:29] INFO FLAGPART: picoCTF{us3_
[1990-08-09 12:19:32] INFO FLAGPART: picoCTF{us3_
[1990-08-09 12:23:43] INFO FLAGPART: y0urlinux_
[1990-08-09 12:23:45] INFO FLAGPART: y0urlinux_
[1990-08-09 12:23:53] INFO FLAGPART: y0urlinux_
[1990-08-09 12:25:32] INFO FLAGPART: sk1lls_

Using timestamps, I reconstructed: picoCTF{us3_y0urlinux_sk1lls_cedfa5fb}.

In hindsight, searching directly for FLAGPART would have been easier.

Hidden In Plainsight

SteganographysteghideBase64 DecodingFile Analysis
Full writeup+

First, I verified the file type:

file img.jpg
img.jpg: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, comment: "c3RlZ2hpZGU6Y0VGNmVuZHZjbVE9", baseline, precision 8, 640x640, components 3

The comment looked suspicious, so I decoded it:

echo "c3RlZ2hpZGU6Y0VGNmVuZHZjbVE9" | base64 --decode
steghide:cEF6endvcmQ=

That hinted at using steghide. I decoded the second Base64 string:

echo "cEF6endvcmQ=" | base64 --decode
pAzzword

I used it as the extraction password:

steghide extract -sf img.jpg -p pAzzword

Recovered flag: picoCTF{h1dd3n_1n_1m4g3_1c55ccd0}.

I also tried binwalk, but it returned nothing because this challenge hides encrypted data in pixels rather than embedded file signatures.

Flag in Flame

Binary AnalysisHex InspectionFile CarvingImage Forensics
Full writeup+

I first checked if the file was really text:

file logs.txt
logs.txt: ASCII text, with very long lines (65536), with no line terminators

Searching for a direct flag string did not work:

strings logs.txt | grep picoCTF

So I inspected raw bytes for hidden signatures:

hexdump -C logs.txt | head
00000000  69 56 42 4f 52 77 30 4b  47 67 6f 41 41 41 41 4e  |iVBORw0KGgoAAAAN|
00000010  53 55 68 45 55 67 41 41  41 34 41 41 41 41 53 41  |SUhEUgAAA4AAAASA|
00000020  43 41 49 41 41 41 41 68  38 62 53 4f 41 41 45 41  |CAIAAAAh8bSOAAEA|
00000030  41 45 6c 45 51 56 52 34  6e 4f 7a 39 31 39 4d 73  |AElEQVR4nOz919Ms|
00000040  79 5a 55 6e 69 50 33 4f  63 59 2b 49 46 4a 2b 36  |yZUniP3OcY+IFJ+6|
00000050  6f 75 71 57 42 71 6f 61  75 74 44 59 52 6d 4e 36  |ouqWBqoautDYRmN6|
00000060  65 6d 66 61 5a 6d 6c 63  30 6d 69 32 2b 37 78 50  |emfaZmlc0mi2+7xP|
00000070  4e 4a 4a 2f 47 4a 2f 34  52 76 4a 74 48 35 64 6d  |NJJ/GJ/4RvJtH5dm|
00000080  51 31 76 62 48 75 34 4d  70 39 6b 7a 6a 51 59 47  |Q1vbHu4Mp9kzjQYG|
00000090  6f 68 75 6f 41 6b 72 68  31 74 57 66 79 73 79 49  |ohuoAkrh1tWfysyI|

The starting bytes indicated a Base64-encoded PNG header. I decoded the file:

cat logs.txt | base64 --decode > discovered_image.png

In the PNG, I found this hex sequence:

7069636F4354467B666F72656E736963735F616E616C797369735F69735F616D617A696E675F35636363376362307D

It matched hex-byte characteristics (0-9, A-F, even length). Converting to ASCII:

echo "7069636F4354467B666F72656E736963735F616E616C797369735F69735F616D617A696E675F35636363376362307D" | xxd -r -p

Final flag: picoCTF{forensics_analysis_is_amazing_5ccc7cb0}.