HackThisSite - Steganography Mission 3
Challenge
Look carefully: it's obvious, just not at first sight.
关卡作者 tiksi,页面在
https://www.hackthissite.org/missions/playit/stego/3/,数据文件是
https://www.hackthissite.org/missions/stego/lvl/3.bmp。
状态:live 已通关(verified)。提交后 profile 的
Stego: 一行出现 (3), 关卡回执为
You have already done this mission.。
Sample
1 | curl -sL -b "$HTS_COOKIE" -o 3.bmp \ |
1 | 3.bmp: PC bitmap, Windows 3.x format, 504 x 360 x 24, image size 544322, \ |
一张 504×360 的 24 位 BMP,file
看不出任何异常。直接打开就是一块纯灰色。
Solution
BMP 头字段先算清楚,排除尾部附加数据 / 头部与实际数据不符这条最常规的隐写路子:
1 | import struct |
1 | bfType b'BM' bfSize 544376 dataOffset 54 |
像素区正好 504×360×3 = 544320 字节,尾部只多出两个 0000
填充字节,没有可读的附加数据。 binwalk 也只认出一张
BMP,没有内嵌压缩包。尾部/头部这条路是封死的。
既然文件结构没东西,信息只能藏在像素值里。把三个通道各自做一次取值统计:
1 | import numpy as np |
1 | R uniq = 2 {61: 186, 62: 181254} |
整幅图本该是一块 RGB(62,62,62) 的纯灰。G、B
两个通道确实各自只有一个值 62, 但 R
通道有两个值:绝大多数是 62,另有 186
个像素是 61(比背景正好少 1)。
这一个计数差就是全部秘密所在。题面说的
obvious, just not at first sight,
指的正是这种肉眼看着是一整块灰、数值上却差了一个数的伪装。
把这 186 个 R=61 的像素按它真实的坐标画成位图:
1 | import numpy as np |
186 个点全部落在一个 58×12 的矩形里(x=[83..140],y=[204..215]),一点噪声都没有。 把这块单独取出即为一行小号点阵文字:
1 | ....................##...................#..........#...## |
点阵是 5×9 的小写字体。按列上的空列把字切开,逐个认:
- 第 1 字:左侧竖干 + 顶部拱起 →
n - 第 2 字:上横、右竖、中横、右竖、下横 →
3 - 第 3 字:上下两个闭环 →
8 - 第 4、5 字:
f之后跟一个上弧下拐的形状 →f、2 - 第 6 字:上面闭环比
8多一点、尾巴向左下拖 →9 - 第 7 字:与第 3 字同形 →
8 - 第 8 字:长竖 + 右侧小拱 →
h - 第 9、10 字:
S形曲线,紧挨一根带下勾的竖线 →s、j - 第 11 字:与第 4 字的
f同形 →f
连起来就是 11 个小写字符(关卡注明答案大小写敏感、作者尽量都用小写)。
若不想手工认字,把这块蒙版放大成图片(Image.resize(..., Image.NEAREST)
放大 16 倍) 肉眼即可读出,或者直接做一次简单的列分割 +
字形比对。核心只有一句: 把 R=61
的像素选出来、按其坐标画出来,答案就在上面。
Key points
- 这是像素级近色隐写:载体整幅只有一种颜色 RGB(62,62,62),信息通过把个别像素的 单个通道调低 1 来编码。差值小到在正常显示下完全看不出,但通道统计会立刻暴露。
- 它是少数像素、单个通道、固定偏移 1 这一类隐写,与常见的 LSB 位平面(把信息平铺到最低位)不同。 所以定位方法也不同:先做通道取值统计,再看少数派的那些值落在什么坐标。
- 24 位 BMP 没有调色板,
palette这条线不用查;尾部附加、头部尺寸不符这两条也都被头解析排除了。 排除法的顺序:结构(头/尾/内嵌)→ 颜色通道 → 像素坐标。 - 提交:关卡表单三个字段
formkey(每次加载都变)、lvl、pass,POST 到/missions/stego/template.php,并且 必须带Referer: .../missions/playit/stego/3/, 否则后端拒绝。答案为大小写敏感的 11 位小写字符串。