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