tên challenge: Confusion mô tả: Wdym you can "rea...

Создано: 9 мая 2026 г.

Отвечено с использованием GPT-5.5 Thinking от Chat01

Вопрос

chall.png

tên challenge: Confusion
mô tả: Wdym you can "read" the image? "Play" the image too? Nah you capping bruh. flag format: BKISC{...}
solve challenge rồi viết write up chi tiết như 1 player đang giải challenge kèm giải thích + câu lệnh , script đã dùng + cách tư duy suy nghĩ

Мысль

Explaining polyglot file format confusion

The file is a polyglot, blending ICO/PNG, PDF, and MP4 formats. It starts with an ICO directory header, points to an embedded PNG at offset 0x478d, contains a PDF signature at offset 0x1b, and has an MP4 ftypisom at 0x100. This mix-up leads to confusion but allows extraction through careful parsing. No need for citations here; I'll detail the approach with the necessary commands and script.

Thought for 3m 39s

Ответ

Flag

text
BKISC{bUy_0n3_g37_7W0_aHh_f1lE}

Write-up: Confusion

Challenge đưa file tên .png, nhưng preview báo unsupported. Mô tả hint rất rõ:

“read” the image? “play” the image too?

Nên mình nghĩ đây không phải PNG bình thường, mà là polyglot file: cùng một file nhưng có thể được parser khác nhau đọc thành nhiều định dạng khác nhau.


1. Recon ban đầu

bash
ls -lh chall.png file chall.png od -Ax -tx1z -N 256 chall.png strings -a -n 6 chall.png | head

Kết quả đáng chú ý:

text
chall.png: Targa image data - Map 32 x 14554 x 1

Nhưng trong hexdump lại thấy:

text
000000 00 00 01 00 01 00 ... 000010 ... 8d 47 00 00 3c 21 2d 2d 0a 25 50 44 46 2d 000020 31 2e 37 ...

Ở đây có vài dấu hiệu:

text
00 00 01 00 01 00

Đây giống header của ICO file.

Tiếp theo lại có:

text
%PDF-1.7

Vậy file .png này thực chất đang bị “confuse” giữa nhiều định dạng.

Mình search các magic bytes:

bash
python3 - <<'PY' from pathlib import Path data = Path("chall.png").read_bytes() for sig in [b"%PDF", b"ftyp", b"\x89PNG", b"BKISC"]: print(sig, [i for i in range(len(data)) if data.startswith(sig, i)][:10]) PY

Kết quả:

text
b'%PDF' [27, 2497203] b'ftyp' [260] b'\x89PNG' [18317] b'BKISC' []

Có ít nhất 3 định dạng bên trong:

OffsetMagicÝ nghĩa
0x1b%PDF-1.7PDF
0x100MP4 ftyp boxVideo
0x478dPNG magicẢnh PNG nằm trong ICO

2. Extract phần ảnh PNG từ ICO

Header ICO có entry trỏ tới ảnh PNG:

text
image offset = 0x478d image size = 0x138da

Extract bằng script:

bash
python3 - <<'PY' from pathlib import Path import struct data = Path("chall.png").read_bytes() png_size = struct.unpack_from("<I", data, 14)[0] png_off = struct.unpack_from("<I", data, 18)[0] print(hex(png_off), png_size) Path("out.png").write_bytes(data[png_off:png_off + png_size]) PY file out.png

Output:

text
0x478d 80090 out.png: PNG image data, 225 x 225, 8-bit/color RGBA, non-interlaced

Mở ảnh ra thì chỉ là meme, không có flag trực tiếp. Nhưng bước này xác nhận file thật sự “làm ảnh” được.


3. Extract PDF để “read” image

PDF bắt đầu tại offset 0x1b, nên chỉ cần cắt từ %PDF:

bash
python3 - <<'PY' from pathlib import Path data = Path("chall.png").read_bytes() pdf_off = data.find(b"%PDF-") Path("out.pdf").write_bytes(data[pdf_off:]) print(hex(pdf_off)) PY file out.pdf

Output:

text
0x1b out.pdf: PDF document, version 1.7, 1 page(s)

Đọc text trong PDF:

bash
pdftotext out.pdf -

Nhận được nửa sau của flag:

text
7W0_aHh_f1lE}

Vậy hiện tại có:

text
???? + 7W0_aHh_f1lE}

4. “Play” file như MP4

Trong file có MP4 ftyp tại offset 0x100.

Ban đầu mình thử cắt từ ftyp ra thành MP4:

bash
python3 - <<'PY' from pathlib import Path data = Path("chall.png").read_bytes() ftyp_off = data.find(b"ftyp") - 4 Path("bad.mp4").write_bytes(data[ftyp_off:]) print(hex(ftyp_off)) PY ffprobe bad.mp4

Nhưng video bị lỗi NAL unit. Lý do là MP4 dùng stco chunk offsets. Các offset này được tính theo file gốc, nơi MP4 bắt đầu tại 0x100. Nếu mình cắt bỏ 256 byte đầu, các offset bị lệch.

Cách nhanh hơn là ép ffmpeg parse file gốc như MP4:

bash
ffprobe -f mp4 chall.png

Nó nhận đúng video:

text
Duration: 00:00:15.84 Stream #0:0: Video: h264, 1296x720 Stream #0:1: Audio: aac

Extract frame:

bash
mkdir frames ffmpeg -y -f mp4 -i chall.png -vf fps=2 frames/f_%03d.png

Mở một frame khoảng giây thứ 1:

bash
ffmpeg -y -f mp4 -i chall.png -ss 1 -vframes 1 frame.png

Trong frame thấy text ở dưới:

text
BKISC{bUy_0n3_g37_

Đây là nửa đầu của flag.


5. Script solve đầy đủ

Script này extract cả PNG, PDF, và MP4. Với MP4, mình patch lại stco offsets để file out.mp4 chạy được bình thường sau khi cắt từ offset 0x100.

python
from pathlib import Path import struct inp = Path("chall.png") data = inp.read_bytes() # 1. Extract PDF pdf_off = data.find(b"%PDF-") Path("out.pdf").write_bytes(data[pdf_off:]) # 2. Extract PNG from ICO header png_size = struct.unpack_from("<I", data, 14)[0] png_off = struct.unpack_from("<I", data, 18)[0] Path("out.png").write_bytes(data[png_off:png_off + png_size]) # 3. Extract MP4 # MP4 starts at ftyp box, but stco offsets are relative to original file. ftyp_off = data.find(b"ftyp") - 4 # Calculate MP4 end by walking top-level boxes until mdat off = ftyp_off while off + 8 <= len(data): size = struct.unpack_from(">I", data, off)[0] typ = data[off + 4:off + 8] if size == 1: size = struct.unpack_from(">Q", data, off + 8)[0] if size == 0: size = len(data) - off off += size if typ == b"mdat": break mp4 = bytearray(data[ftyp_off:off]) # Patch stco chunk offsets pos = 0 patched = 0 while True: i = mp4.find(b"stco", pos) if i == -1: break box_start = i - 4 box_size = struct.unpack_from(">I", mp4, box_start)[0] entry_count = struct.unpack_from(">I", mp4, i + 8)[0] entries_start = i + 12 if box_start >= 0 and box_start + box_size <= len(mp4): for j in range(entry_count): old = struct.unpack_from(">I", mp4, entries_start + 4 * j)[0] struct.pack_into(">I", mp4, entries_start + 4 * j, old - ftyp_off) patched += entry_count pos = i + 4 Path("out.mp4").write_bytes(mp4) print(f"PDF @ {pdf_off:#x} -> out.pdf") print(f"PNG @ {png_off:#x}, size {png_size} -> out.png") print(f"MP4 @ {ftyp_off:#x}, patched {patched} stco offsets -> out.mp4")

Chạy:

bash
python3 solve.py pdftotext out.pdf - ffmpeg -y -i out.mp4 -ss 1 -vframes 1 frame.png

PDF cho:

text
7W0_aHh_f1lE}

Video frame cho:

text
BKISC{bUy_0n3_g37_

Ghép lại:

text
BKISC{bUy_0n3_g37_7W0_aHh_f1lE}

Kết luận

Challenge tên Confusion vì file cố tình làm parser bị “confuse”:

text
.png extension ICO-style header embedded PNG embedded PDF embedded MP4

Hint “read” = đọc PDF.
Hint “play” = chạy như MP4.
Flag lấy từ video + PDF:

text
BKISC{bUy_0n3_g37_7W0_aHh_f1lE}

Поделиться этим Q&A