QR Puzzles from SECCON CTF

上周末的 SECCON CTF, 有几个 QR 码的题..

Problem 1

http://www.youtube.com/watch?v=omobhuutrE4

这个视频里, 中间最下方有一个滚动的被挡住的 QR 二维码.

先抽帧. 二维码是 37x37 的, 因此我挑了一个 fps=6.8, 使得二维码滚过去的时间差不多为 37 帧.

you-get http://www.youtube.com/watch?v=omobhuutrE4
ffmpeg -i SECCON\ WARS.webm -r 6.8 -ss 00:00:54 -f image2 ./images/%3d.png

图中的文字部分是扭曲的, 因此标出一个 perspective 变换, 将文字部分扭正:

four = [(134, 86), (36, 239), (186, 86), (279, 239)]
four = np.asarray(four, dtype='float32')
corner = [(36, 0), (36, 239), (279, 0), (279, 239)]
corner = np.asarray(corner, dtype='float32')
m = cv2.getPerspectiveTransform(four, corner)

然后将每幅图的最后一行拼起来, resize 成方形再做二值化, 得到二维码:

噪声较大, 但是使用一个足够好的扫码软件是能够扫出来的 (反正微信扫不出来).

后来想到, 由于总是要 resize 成方形, 所以抽帧频率其实是不太重要的, 再抽的密一些可能还可以减少噪声. 甚至 perspective 可能也不需要做..

Problem 2

题中的二维码严重缺失, 找了找 QR Code 的 specification 发现 codeword 的 layout:

可以看到, 对于 29x29 的二维码, 所有的 data codewords 在图中都是完好的, format 部分有一点, 也足够恢复出 format 信息. (format 有效值只有 5 位, 其余为冗余编码).

即使将 Fixed Patterns 部分补全, 也无法用常用软件恢复, 因为软件的工作原理都是在假设每个点都有可能错误的情形下, 利用 error correction codewords 进行纠正, 这也是 qr 码的设计初衷. 而题目提供的信息是 "保证正确的点 + 缺失的点", 由于缺失过多, 又无法向软件提供 "保证正确" 这一信息, 因而无法恢复, 需要研究 qr 编码方式.

为了便于识别, qr 码需要避免出现大片的连续黑白区域, 因此在将数据及 EC 编码结束后, 会对其尝试应用一些全局的 mask, 挑一个效果最好的 mask.

从 format 中可以得到本题的 mask 为 001, 因此对 data 部分异或一次 mask, 就可得到真实的二进制数据, 再按照 layout 图中标出的阅读顺序, 将 26x8 个 bit 解析出来:

0010000000110100111110100100010100010001001111010000010010011110110101000001010011011101110100100101010001001110010110010000111001010001110110101001001011010101000110010001000100001110000100100001111101000000

qr 码编码分为若干 segment, 每一个 segment 包含 4bit 的类型标识 (数字 / 数字字母 / byte 等),segment 长度, 及数据. 在 ISO/IEC 18004:2006 标准手册中找到具体的规则, 即可将以上数据解码为答案.

Problem 3

此题只提供了 EC 部分, qr 码使用的是 Reed-Solomon Error Correction.

比赛时看不下去数论, 就利用一些尝试性的东西乱搞, 最终把答案的前 11 个字符弄出来了, 后面就弄不动了.

以后有空看了 reed-solomon 再解决它吧..

Comments