上周末的SECCON CTF, 有几个QR码的题..
http://www.youtube.com/watch?v=omobhuutrE4
这个视频里, 中间最下方有一个滚动的被挡住的QR二维码.
先抽帧. 二维码是37x37的, 因此我挑了一个fps=6.8, 使得二维码滚过去的时间差不多为37帧.
图中的文字部分是扭曲的, 因此标出一个perspective变换, 将文字部分扭正:
然后将每幅图的最后一行拼起来, resize成方形再做二值化, 得到二维码:
噪声较大, 但是使用一个足够好的扫码软件是能够扫出来的(反正微信扫不出来).
后来想到, 由于总是要resize成方形, 所以抽帧频率其实是不太重要的, 再抽的密一些可能还可以减少噪声. 甚至perspective可能也不需要做..
题中的二维码严重缺失, 找了找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解析出来:
qr码编码分为若干segment, 每一个segment包含4bit的类型标识(数字/数字字母/byte等),segment长度, 及数据. 在ISO/IEC 18004:2006标准手册中找到具体的规则, 即可将以上数据解码为答案.
此题只提供了EC部分, qr码使用的是Reed-Solomon Error Correction.
比赛时看不下去数论, 就利用一些尝试性的东西乱搞, 最终把答案的前11个字符弄出来了, 后面就弄不动了.
以后有空看了reed-solomon再解决它吧..