hint: I like to have my poems saved on CTFd instan...
Criado em: 3 de abril de 2026
Respondido usando GPT-5.4 Thinking por Chat01
Criado em: 3 de abril de 2026
Respondido usando GPT-5.4 Thinking por Chat01
hint: I like to have my poems saved on CTFd instances like this. But the admin does like it, so I hid the secret in my poem.
tìm flag dạng kashiCTF{...} rồi viết write up, đây là 1 bài CTF Stego về poem, poem được hiển thị ngay trên web, file tôi cung cấp cho bạn là tôi copy từ web, không có nhúng file ẩn gì ở trong cả. Giải cho đến khi tìm ra flag
pythonfrom pathlib import Path p = Path('/mnt/data/new 1.txt') data = p.read_bytes() data[:200], len(data) (b'Poem\r\nThe way a crow\t \t \t \t \t\t \t \t \r\nShook down on me \t \t\t \t \t \t\t \r\nThe dust of snow \t \t\t \t \t \t \t \r\nFrom a hemlock tree \t \t \t \t ', 739)
pythontext = data.decode('utf-8', errors='replace') lines = text.splitlines() for i,l in enumerate(lines): print(i, repr(l), len(l))
pythonvisible_lines = [ "The way a crow", "Shook down on me", "The dust of snow", "From a hemlock tree", "", "Has given my heart", "A change of mood", "And saved some part", "Of a day I had rued.", "", "", "", "", ] for i, vis in enumerate(visible_lines, start=1): l=lines[i] hidden=l[len(vis):] print(i, repr(hidden)) print(hidden.replace(' ','·').replace('\t','→'))
pythonfor i, vis in enumerate(visible_lines, start=1): hidden = lines[i][len(vis):] # split by tabs parts = hidden.split('\t') print(i, [len(p) for p in parts], len(parts)-1, 'tabs')
pythonoct_digits = [] for i, vis in enumerate(visible_lines, start=1): hidden = lines[i][len(vis):] oct_digits.extend(str(len(p)) for p in hidden.split('\t')) oct_str = ''.join(oct_digits) oct_str[:200], len(oct_str) ('06233053662031506250164764125755162235515273704576423353627334435650571342733345462364567652575556637441547064575', 113)
python# group into 3-digit octal from start for offset in range(3): s = oct_str[offset:] groups = [s[i:i+3] for i in range(0, len(s)-len(s)%3, 3)] txt = ''.join(chr(int(g,8)) for g in groups) print('offset',offset,'len',len(groups),'rem',len(s)%3) print(repr(txt[:100]))
pythonparts_all = [] for i, vis in enumerate(visible_lines, start=1): hidden=lines[i][len(vis):] parts=hidden.split('\t') if i==1 and parts and parts[0]=='': parts=parts[1:] parts_all.extend(len(p) for p in parts) len(parts_all), parts_all[:20] (112, [6, 2, 3, 3, 0, 5, 3, 6, 6, 2, 0, 3, 1, 5, 0, 6, 2, 5, 0, 1])
pythonvals=parts_all # pack 3-bit values msb-first into bytes bits=''.join(f'{v:03b}' for v in vals) len(bits), bits[:48] (336, '110010011011000101011110110010000011001101000110')
pythonimport math by = bytes(int(bits[i:i+8],2) for i in range(0,len(bits),8)) by[:50], len(by) (b'\xc9\xb1^\xc83FT\x1d>\x85_i\xc9;M]\xf1/\xd17^]\xb9\x1d\xd4^\\]\xb7,\xc9\xe9w\xd5_m\xd9\xf9\r\x9ci}', 42)
pythonvals=parts_all bits=''.join(str((v>>i)&1) for v in vals for i in [0,1,2]) # b1,b2,b3 by = bytes(int(bits[i:i+8],2) for i in range(0,len(bits),8)) by, len(by) (b'kashiCTF{1_like_poems_but_1_lik3_u_more<3}', 42)
Mình đã giải ra flag:
kashiCTF{1_like_poems_but_1_lik3_u_more<3}
Write-up ngắn:
Kiểm tra dữ liệu được cung cấp
File poem chỉ là bài thơ hiển thị trên web, không có file nhúng ẩn nào khác. Trong cả bản copy lẫn view-source, phần đáng ngờ là rất nhiều tab/space ở cuối từng dòng của bài thơ. (new 1.txt) (view-source_https___kashictf.iitbhucybersec.in_poem.html)
Nhận ra kiểu stego là SNOW / stegsnow
SNOW giấu dữ liệu bằng trailing whitespace; một tab đầu tiên đánh dấu điểm bắt đầu dữ liệu, sau đó dữ liệu được mã hóa bằng các nhóm 0–7 dấu cách ngăn bởi tab, mỗi nhóm tương ứng 3 bit. (JustSolve)
Cách decode cụ thể với bài này
\t.v phải đổi thành bit theo thứ tự:v&1, (v>>1)&1, (v>>2)&1. (GitHub)Ghép bit thành byte ASCII
Sau khi pack lại 8 bit một, chuỗi thu được là:
kashiCTF{1_like_poems_but_1_lik3_u_more<3}
Python tối giản để tự kiểm tra:
pythonfrom pathlib import Path text = Path("new 1.txt").read_text(encoding="utf-8") lines = text.splitlines() visible = [ "The way a crow", "Shook down on me", "The dust of snow", "From a hemlock tree", "", "Has given my heart", "A change of mood", "And saved some part", "Of a day I had rued.", "", "", "", "", ] vals = [] for idx, vis in enumerate(visible, start=1): hidden = lines[idx][len(vis):] parts = hidden.split("\t") if idx == 1 and parts and parts[0] == "": parts = parts[1:] # bỏ start-tab marker vals.extend(len(p) for p in parts) bits = "".join(str((v >> i) & 1) for v in vals for i in [0, 1, 2]) flag = "".join(chr(int(bits[i:i+8], 2)) for i in range(0, len(bits), 8)) print(flag)
Kết luận: đây là whitespace steganography kiểu stegsnow, không phải hidden file hay metadata ẩn trong HTML. (new 1.txt) (view-source_https___kashictf.iitbhucybersec.in_poem.html)