WeChall - LSB

Challenge

Stegano LSB 图像隐写。挑战页面提供一张 carrier.png,其中包含 12 个大写字母的隐藏信息。每 session 不同。

Solution

隐藏信息不在传统的 data-hiding LSB 中(zsteg 检测不到有效文本),而是通过 visual bit plane 方式嵌入:将字母写入某个 bit plane,肉眼查看该 plane 的图像即可读出。

遍历 8 个 bit plane × 3 个颜色通道后发现,字母出现在 绿色通道的 bit 2(0-indexed)中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from PIL import Image

img = Image.open('carrier.png')
w, h = img.size
pixels = list(img.getdata())

out = Image.new('L', (w, h))
out_pixels = []
for pixel in pixels:
# 取绿色通道 (index 1) 的 bit 2
val = (pixel[1] >> 2) & 1
out_pixels.append(255 if val else 0)
out.putdata(out_pixels)
out.save('bit2_green.png')

生成的 bit2_green.png 中,97% 以上像素为黑,仅 2-3% 的白点构成 12 个斜体大写字母。肉眼直接可读。

也可以从工具集一键扫描所有 bit plane:

1
$ uv run ~/ctf/tool/script/forensics/lsb_scan.py carrier.png

输出每个 bit plane 的白色像素占比,sparse(< 5%)的 plane 就是隐藏文本所在。

同样可以通过其他 stegano 工具发现:

  • Stegsolve(Java):Analyse → Bit Plane 逐层查看,绿色通道 bit 2 即可看到字母
  • Stegoveritasstegoveritas carrier.png 自动提取所有 bit plane,输出到 results/ 目录

关键点

  • 使用绿色通道的 bit 2(不是 bit 4),Steganabara 对应 mask=4(即 2^2)
  • 字母在 bit plane 图像中肉眼可见,白字黑底
  • zsteg 不适用——这不是 data-hiding,而是 visual plane 嵌入;zsteg 找的是 LSB 中编码的数据字节,而字母是直接画在 bit plane 上的
  • 答案 session-bound,每张 carrier.png 不同