HackThisSite - Programming Mission 7
Challenge
Level 7
This level is about image processing, inspired by pay-tv cracking. Code a program which is able to automatically unscramble the lines of a given image. Type in all characters from the image. Begin with the upper line, and add the lower line without a blank in between.
限时 180 秒:GET /missions/prog/7/
生成随机实例(图在 /missions/prog/7/BMP),
POST /missions/prog/7/index.php 字段
solution。
Solution
Step 1: 图像结构
实例图是 200×100 的 PNG。
对像素做颜色统计:
1 | shape (100, 200, 3) |
- 只有两个颜色的像素数在 800 以上(1031 / 871),它们就是两行文字的字形颜色;
- 其余颜色每个只有 4–6 个像素,是逐像素噪声(不是行级噪声);
- 两种字形色各自的 27–28 行散布在整幅图的高度上(span 3–98 / 7–91),说明加扰是行置换: 原始图的两行文字,它们的像素行被打乱后均匀撒在整张图里。
这就给出还原思路:先判断每一行原本在图像里的纵坐标,再把每个颜色的行按这个坐标排序,就能把两行文字拼回来。
Step 2: 行序判定
背景是一条垂直渐变,B
通道随行号单调变化;而行置换并不改变每一行的像素内容,
于是每一行自身的 B
通道统计量就保留了它原来的纵坐标信息。实测
(min+max)/2(midrange)足够稳定:
1 | import numpy as np |
对每个字形色取出它的行、按 rank 排序后渲染(白底黑字、5
倍放大),就得到两段干净的字形条带:
1 | colour A (129, 127, 77): 27 rows -> ranks [8, 10, 12, ..., 46, 48, 49] |
注意这里的 rank 是从下往上计数的(rank
0 = 底部):色带 B 的 rank 均值更大,
说明它原本位于上面那一行;所以拼接顺序必须是 B 的文字 +
A 的文字。
Step 3: 读出字符
条带放大 5 倍后字形是纯黑白的点阵,逐像素打成 ASCII
1 | line 1 (strip B): J 6 7 L 3 6 |
Verify
同一个实例的提交实测(每行是 solution=<串>
的返回判定):
1 | submit 'ME5FEYJ67L36' -> ok=False bad=True # 先上后下、但左右顺序错 |