CodeShell.kr - Quiet Frame

Challenge

256×160 的彩色斜条纹图,题面提示画面里有眼睛看不到的东西。难度在于位平面候选极多(通道 × 主序 × 翻转),要靠可输出的可打印性筛出唯一正确的那一个。

The picture remembers what the eye misses. Recover the flag in the form CodeShell{...}

图像记得眼睛漏掉的东西。

1
https://codeshell.kr/challenges/quiet-frame/

Solution

附件 quiet-frame.png 是 256×160 RGB 图,画面是彩色斜条纹。

Step 1:逐通道取 LSB,按 8 位 MSB-first 组字节,枚举行/列主序与各种翻转组合。

Step 2:只有 B 通道 row-major 在字节偏移 0 处出现明文,第 23 字节以 \x00 结束;其余位置是条纹自身的规律位(0x55 / 0xAA)。

1
CodeShell{QUIET_PIXELS}\x00UUUUUUUU\xaa\xaa...

Script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/bin/env python3
"""CodeShell.kr - Quiet Frame (Stegano, 50p) solver.

The payload is in the blue channel's LSB in row-major order, packed 8 bits
MSB-first, terminated by a NUL byte. The stripes themselves contribute regular
bits (0x55 / 0xAA), so the payload is the leading run of printable bytes.
"""
import numpy as np
from PIL import Image

PNG = "assets/challenge-images/quiet-frame.png"


def main():
a = np.array(Image.open(PNG).convert("RGB"))
flat = (a[:, :, 2] & 1).flatten() # B channel LSB, row-major
out = bytearray()
for i in range(0, len(flat) - 7, 8):
v = 0
for bit in flat[i:i + 8]:
v = (v << 1) | int(bit)
out.append(v)
print(out.split(b"\x00")[0].decode())


if __name__ == "__main__":
main()
CodeShell{QUIET_PIXELS}