Flags follow the format: kashiCTF{[A-Za-z0-9_|()]}...

Tạo vào: 3 tháng 4, 2026

Trả lời bằng GPT-5.4 Thinking bởi Chat01

Câu hỏi

flag.pdf

Flags follow the format: kashiCTF{[A-Za-z0-9_|()]}
giải cho đến khi tìm được flag rồi viết lại 1 file write up thật chi tiết bằng tiếng Việt

Suy nghĩ

Mình sẽ mở PDF để phân tích challenge, cố gắng lần ra flag trước, rồi đóng gói toàn bộ quá trình thành một file write-up tiếng Việt thật chi tiết. Nếu PDF chỉ là đề bài mà cần thêm dữ liệu ngoài, mình sẽ bám theo những gì tìm được trong file và ghi rõ phần nào là suy luận.

Thought for 23s

Python

python
from PIL import Image img=Image.open('/mnt/data/flag.pdf') img.mode, img.size ('RGB', (284, 150))

Python

python
from PIL import Image import numpy as np, os, matplotlib.pyplot as plt, pandas as pd, textwrap, math, itertools, collections, re, zlib, base64, struct img = Image.open('/mnt/data/flag.pdf') arr = np.array(img) arr.shape, arr.min(), arr.max(), arr.mean() ((150, 284, 3), np.uint8(0), np.uint8(255), np.float64(211.19287949921753))

Python

python
for c,name in enumerate('RGB'): vals=arr[:,:,c].flatten() print(name, len(np.unique(vals)), vals.min(), vals.max(), vals.mean(), vals.std())

Python

python
from PIL import Image import numpy as np, os img = Image.open('/mnt/data/flag.pdf').convert('RGB') arr = np.array(img) outdir='/mnt/data/bitplanes' os.makedirs(outdir, exist_ok=True) for c,name in enumerate('RGB'): for b in range(8): plane=((arr[:,:,c]>>b)&1)*255 Image.fromarray(plane.astype('uint8')).save(f'{outdir}/{name}_bit{b}.png') print(outdir)

Python

python
from PIL import Image, ImageOps, ImageDraw import os, math paths=[f'/mnt/data/bitplanes/{c}_bit{b}.png' for c in 'RGB' for b in range(7,-1,-1)] ims=[Image.open(p).convert('L').resize((284,150)) for p in paths] labels=[os.path.basename(p).replace('.png','') for p in paths] w,h=ims[0].size sheet=Image.new('RGB',(w*4,h*6),(255,255,255)) draw=ImageDraw.Draw(sheet) for i,(im,label) in enumerate(zip(ims,labels)): x=(i%4)*w y=(i//4)*h sheet.paste(Image.merge('RGB',(im,im,im)),(x,y)) draw.rectangle([x,y,x+80,y+15],fill=(255,255,255)) draw.text((x+2,y+2),label,fill=(255,0,0)) sheet.save('/mnt/data/bitplanes_sheet.png

Python

python
from PIL import Image, ImageOps, ImageDraw import os, math paths=[f'/mnt/data/bitplanes/{c}_bit{b}.png' for c in 'RGB' for b in range(7,-1,-1)] ims=[Image.open(p).convert('L').resize((284,150)) for p in paths] labels=[os.path.basename(p).replace('.png','') for p in paths] w,h=ims[0].size sheet=Image.new('RGB',(w*4,h*6),(255,255,255)) draw=ImageDraw.Draw(sheet) for i,(im,label) in enumerate(zip(ims,labels)): x=(i%4)*w y=(i//4)*h sheet.paste(Image.merge('RGB',(im,im,im)),(x,y)) draw.rectangle([x,y,x+80,y+15],fill=(255,255,255)) draw.text((x+2,y+2),label,fill=(255,0,0)) sheet.save('/mnt/data/bitplanes_sheet.png <<ImageDisplayed>>

Python

python
import os, math, collections, re, struct, zlib, bz2, lzma, gzip, base64, binascii, hashlib data=open('/mnt/data/flag_tail.bin','rb').read() len(data), data[:16], data[-16:] (29820, b'\xff\xff\xfb\xff\xff\xfb\xff\xff\xfb\xff\xff\xfb\xff\xff\xfb\xff', b'\xff\xfe\xff\xfd\xfe\xff\xff\xfe\xff\xfd\xfe\xff\xff\xfe\xff\xfd')

Python

python
from PIL import Image data=open('/mnt/data/flag.pdf','rb').read() header=b'P6\n284 150\n255\n' assert data.startswith(header) pix=data[len(header):] len(pix), 284*185*3 (157620, 157620)

Python

python
from PIL import Image import numpy as np data=open('/mnt/data/flag.pdf','rb').read() header=b'P6\n284 150\n255\n' pix=data[len(header):] img = Image.frombytes('RGB', (284,185), pix) img.save('/mnt/data/flag_full.png') print('/mnt/data/flag_full.png')

Python

python
from PIL import Image import numpy as np data=open('/mnt/data/flag.pdf','rb').read() header=b'P6\n284 150\n255\n' pix=data[len(header):] img = Image.frombytes('RGB', (284,185), pix) img.save('/mnt/data/flag_full.png') print('/mnt/data/flag_full.png') <<ImageDisplayed>>

Python

python
from PIL import Image, ImageOps, ImageDraw import os, glob, math files=sorted(glob.glob('/mnt/data/writeup_render/page-*.png')) ims=[Image.open(f).convert('RGB') for f in files] # resize thumbnails thumbs=[] for i,im in enumerate(ims): im.thumbnail((380,540)) canvas=Image.new('RGB',(400,560),'white') canvas.paste(im,((400-im.width)//2,20)) d=ImageDraw.Draw(canvas) d.text((10,5),os.path.basename(files[i]),fill='black') thumbs.append(canvas) sheet=Image.new('RGB',(800,1120),'#dddddd') for idx,im in enumerate(thumbs): x=(idx%2)*400 y=(idx//2)*560 sheet.paste(im,(x,y)) sheet.save('/mnt/data/writeup_sheet.png') print('/mnt/data/writeup_sheet.png')

Python

python
from PIL import Image, ImageOps, ImageDraw import os, glob, math files=sorted(glob.glob('/mnt/data/writeup_render/page-*.png')) ims=[Image.open(f).convert('RGB') for f in files] # resize thumbnails thumbs=[] for i,im in enumerate(ims): im.thumbnail((380,540)) canvas=Image.new('RGB',(400,560),'white') canvas.paste(im,((400-im.width)//2,20)) d=ImageDraw.Draw(canvas) d.text((10,5),os.path.basename(files[i]),fill='black') thumbs.append(canvas) sheet=Image.new('RGB',(800,1120),'#dddddd') for idx,im in enumerate(thumbs): x=(idx%2)*400 y=(idx//2)*560 sheet.paste(im,(x,y)) sheet.save('/mnt/data/writeup_sheet.png') print('/mnt/data/writeup_sheet.png') <<ImageDisplayed>>

Python

python
from PIL import Image, ImageOps, ImageDraw import os, glob files=sorted(glob.glob('/mnt/data/writeup_render/page-*.png')) len(files) 4

Python

python
from PIL import Image, ImageOps, ImageDraw import os, glob, math files=sorted(glob.glob('/mnt/data/writeup_render/page-*.png')) ims=[Image.open(f).convert('RGB') for f in files] thumbs=[] for i,im in enumerate(ims): im.thumbnail((380,540)) canvas=Image.new('RGB',(400,560),'white') canvas.paste(im,((400-im.width)//2,20)) d=ImageDraw.Draw(canvas) d.text((10,5),os.path.basename(files[i]),fill='black') thumbs.append(canvas) sheet=Image.new('RGB',(800,1120),'#dddddd') for idx,im in enumerate(thumbs): x=(idx%2)*400 y=(idx//2)*560 sheet.paste(im,(x,y)) sheet.save('/mnt/data/writeup_sheet2.png') print('/mnt/data/writeup_sheet2.png')

Python

python
from PIL import Image, ImageOps, ImageDraw import os, glob, math files=sorted(glob.glob('/mnt/data/writeup_render/page-*.png')) ims=[Image.open(f).convert('RGB') for f in files] thumbs=[] for i,im in enumerate(ims): im.thumbnail((380,540)) canvas=Image.new('RGB',(400,560),'white') canvas.paste(im,((400-im.width)//2,20)) d=ImageDraw.Draw(canvas) d.text((10,5),os.path.basename(files[i]),fill='black') thumbs.append(canvas) sheet=Image.new('RGB',(800,1120),'#dddddd') for idx,im in enumerate(thumbs): x=(idx%2)*400 y=(idx//2)*560 sheet.paste(im,(x,y)) sheet.save('/mnt/data/writeup_sheet2.png') print('/mnt/data/writeup_sheet2.png') <<ImageDisplayed>>

Python

python
from PIL import Image, ImageOps, ImageDraw import os, glob files=sorted(glob.glob('/mnt/data/writeup_render/page-*.png')) len(files), files (4, ['/mnt/data/writeup_render/page-1.png', '/mnt/data/writeup_render/page-2.png', '/mnt/data/writeup_render/page-3.png', '/mnt/data/writeup_render/page-4.png'])

Python

python
from PIL import Image, ImageOps, ImageDraw import os, glob, math files=sorted(glob.glob('/mnt/data/writeup_render/page-*.png')) ims=[Image.open(f).convert('RGB') for f in files] thumbs=[] for i,im in enumerate(ims): im.thumbnail((380,540)) canvas=Image.new('RGB',(400,560),'white') canvas.paste(im,((400-im.width)//2,20)) d=ImageDraw.Draw(canvas) d.text((10,5),os.path.basename(files[i]),fill='black') thumbs.append(canvas) sheet=Image.new('RGB',(800,1120),'#dddddd') for idx,im in enumerate(thumbs): x=(idx%2)*400 y=(idx//2)*560 sheet.paste(im,(x,y)) sheet.save('/mnt/data/writeup_sheet3.png') print('/mnt/data/writeup_sheet3.png')

Python

python
from PIL import Image, ImageOps, ImageDraw import os, glob, math files=sorted(glob.glob('/mnt/data/writeup_render/page-*.png')) ims=[Image.open(f).convert('RGB') for f in files] thumbs=[] for i,im in enumerate(ims): im.thumbnail((380,540)) canvas=Image.new('RGB',(400,560),'white') canvas.paste(im,((400-im.width)//2,20)) d=ImageDraw.Draw(canvas) d.text((10,5),os.path.basename(files[i]),fill='black') thumbs.append(canvas) sheet=Image.new('RGB',(800,1120),'#dddddd') for idx,im in enumerate(thumbs): x=(idx%2)*400 y=(idx//2)*560 sheet.paste(im,(x,y)) sheet.save('/mnt/data/writeup_sheet3.png') print('/mnt/data/writeup_sheet3.png') <<ImageDisplayed>>

Suy nghĩ

from PIL import Image, ImageOps, ImageDraw import os, glob, math files=sorted(glob.glob('/mnt/data/writeup_render/page-*.png')) ims=[Image.open(f).convert('RGB') for f in files] thumbs=[] for i,im in enumerate(ims): im.thumbnail((380,540)) canvas=Image.new('RGB',(400,560),'white') canvas.paste(im,((400-im.width)//2,20)) d=ImageDraw.Draw(canvas) d.text((10,5),os.path.basename(files[i]),fill='black') thumbs.append(canvas) sheet=Image.new('RGB',(800,1120),'#dddddd') for idx,im in enumerate(thumbs): x=(idx%2)*400 y=(idx//2)*560 sheet.paste(im,(x,y)) sheet.save('/mnt/data/writeup_sheet3.png') print('/mnt/data/writeup_sheet3.png')

<<ImageDisplayed>>

Thought for 10m 48s

Trả lời

Đã tìm được flag:

kashiCTF{iLOVEkashi}

Mấu chốt là file flag.pdf thực ra không phải PDF mà là ảnh PPM bị đổi đuôi, và phần header đã bị sửa chiều cao từ 185 xuống 150 để che 35 dòng pixel cuối. Khi dựng lại ảnh với kích thước đúng, flag hiện ra ở mép dưới.

File write-up tiếng Việt chi tiết: Download write-up DOCX

Ảnh đã khôi phục: Recovered image

Chia sẻ Q&A này