HackThisSite - Steganography Mission 14
Challenge
题目提供
stego14.tar.gz,提示Get the image here。需要先看清 tar 内部结构,再从图片里挖出隐藏的密钥与密文,最后用古典密码还原口令。 A tar.gz is provided; the answer is recovered by unpacking it, carving a RAR archive out of the JPG, and decrypting a classical cipher with a key that is itself hidden inside the archive.
Solution
1 | $ tar tzf stego14.tar.gz |
成员名 6578747261637400 是一串 ASCII 十六进制,解码后是
extract\0。这个名字本身就在提示:真正的载荷不在图片像素里,而在图片之后附加的数据里,需要
extract(提取)出来。
图片本体是一张 150x20 的基线 JPEG:
1 | $ file 6578747261637400.jpg |
JPEG 以 EOI(FF D9)结束,但文件真实长度超过了 EOI
的位置,后面还跟了一段数据。扫描标记来定位:
1 | data = open("6578747261637400.jpg", "rb").read() |
输出显示 EOI 之后还有 5617 字节,且以 Rar! 开头,是一段
RAR v4 归档。把它切出来解开:
1 | $ python3 -c "d=open('6578747261637400.jpg','rb').read(); i=d.rfind(b'\xff\xd9'); open('appended.rar','wb').write(d[i+2:])" |
归档里只有一个文件 key.jpg(48x13)。
key.jpg
是纯黑白位图,像素值只有黑(0)与白(255)两色,放大后是一行小字。直接按
ASCII 打印像素即可读:
1 | from PIL import Image |
打印出来的是 *5+10。这正是仿射密码(Affine
cipher)的密钥,含义为 E(x) = (5 * x + 10) mod 26,也就是
a = 5, b = 10。
6578747261637400.jpg 的像素对比度极低,灰度只落在
197–255
之间,肉眼看上去几乎全白。把灰度拉伸到完整范围后,里面藏着一行大写密文
PGNNZCFYXD:
1 | from PIL import Image |
a = 5 与 26 互质,模逆元为
21(5 * 21 = 105 ≡ 1 (mod 26))。解密公式是
D(y) = 21 * (y - 10) mod 26:
1 | def affine_decrypt(cipher, a=5, b=10, alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ"): |
解出的明文 BULLDOZINJ
即口令(大小写敏感,站点惯用全小写)。提交后,个人资料页的
Stego: 一行出现 (14),关卡页也显示
You have already done this mission.,确认通关。
Key points
- 遇到
.tar.gz先tar tzf看成员名:6578747261637400是十六进制编码的extract\0,直接点破了手法。 - JPEG 文件可以合法地在 EOI
之后追加任意数据:
rfind(b"\xff\xd9")定位真正的图像结尾,尾部紧跟Rar!就是一段藏在图片后面的压缩包。 - 低对比度像素是常见隐写载体:把灰度拉伸(
197–255 → 0–255)就能让几乎全白的图浮出密文。 - 密钥图片是纯黑白位图时,直接打印像素字符画比逐像素放大更省事。
- 仿射密码的密钥形如
*a+b(这里是*5+10);解密先求a关于 26 的模逆元,再套D(y) = a_inv * (y - b) mod 26。