tên challenge: Confusion mô tả: Wdym you can "rea...
创建于:2026年5月9日
使用 GPT-5.5 Thinking 回答 Chat01
创建于:2026年5月9日
使用 GPT-5.5 Thinking 回答 Chat01
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ĩ
textBKISC{bUy_0n3_g37_7W0_aHh_f1lE}
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.
bashls -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ú ý:
textchall.png: Targa image data - Map 32 x 14554 x 1
Nhưng trong hexdump lại thấy:
text000000 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:
text00 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:
bashpython3 - <<'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ả:
textb'%PDF' [27, 2497203] b'ftyp' [260] b'\x89PNG' [18317] b'BKISC' []
Có ít nhất 3 định dạng bên trong:
| Offset | Magic | Ý nghĩa |
|---|---|---|
0x1b | %PDF-1.7 | |
0x100 | MP4 ftyp box | Video |
0x478d | PNG magic | Ảnh PNG nằm trong ICO |
Header ICO có entry trỏ tới ảnh PNG:
textimage offset = 0x478d image size = 0x138da
Extract bằng script:
bashpython3 - <<'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:
text0x478d 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.
PDF bắt đầu tại offset 0x1b, nên chỉ cần cắt từ %PDF:
bashpython3 - <<'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:
text0x1b out.pdf: PDF document, version 1.7, 1 page(s)
Đọc text trong PDF:
bashpdftotext out.pdf -
Nhận được nửa sau của flag:
text7W0_aHh_f1lE}
Vậy hiện tại có:
text???? + 7W0_aHh_f1lE}
Trong file có MP4 ftyp tại offset 0x100.
Ban đầu mình thử cắt từ ftyp ra thành MP4:
bashpython3 - <<'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:
bashffprobe -f mp4 chall.png
Nó nhận đúng video:
textDuration: 00:00:15.84 Stream #0:0: Video: h264, 1296x720 Stream #0:1: Audio: aac
Extract frame:
bashmkdir 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:
bashffmpeg -y -f mp4 -i chall.png -ss 1 -vframes 1 frame.png
Trong frame thấy text ở dưới:
textBKISC{bUy_0n3_g37_
Đây là nửa đầu của flag.
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.
pythonfrom 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:
bashpython3 solve.py pdftotext out.pdf - ffmpeg -y -i out.mp4 -ss 1 -vframes 1 frame.png
PDF cho:
text7W0_aHh_f1lE}
Video frame cho:
textBKISC{bUy_0n3_g37_
Ghép lại:
textBKISC{bUy_0n3_g37_7W0_aHh_f1lE}
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:
textBKISC{bUy_0n3_g37_7W0_aHh_f1lE}