二维码就是在二维矩阵相应元素位置上用“点”表示二进制“1”,用“空”表示二进制“0”,用“点”和“空”的排列组成的图像。在定位准确的前提下,只要扫码设备读取到的位置有一个黑点——哪怕只是非常小的黑点,都不妨碍它被识别为“1”,浅色的地方自然就被识别为“0”。如图2.5.1所示,大家可以扫码尝试。扫描则是靠明暗差异来识别二维码,所以二维码是否由小方块组成并没有影响,但一定要用对比鲜明的颜色。如果二维码被设置成了深灰+浅灰,就很难被识别出来。
图2.5.1 一个“若隐若现”的二维码
二维码的种类很多,包括PDF417码、汉信码、颜色条码等。目前,大家看到的二维码大多是“QR码”(微信、支付宝等工具使用的二维码几乎都是QR码)。QR码是Quick Response(快速反应)的缩写,由Denso-Wave公司发明。本节重点介绍QR码的基础知识、常用工具和修复方法。
QR码的结构如图2.5.2所示。
图2.5.2 QR码的结构
❑ 位置探测图形、位置探测图形分隔符、定位图形 :用于对二维码定位。对每个QR码来说,位置都是固定的,只是大小、规格有所差异。位置探测图形就是QR码图案 三个角上的“回字形”图案 ,当然,这3个“回字形”图案也可以是圆形的。有了这3个“回字形”图案,我们就可以从 任何角度 准确扫描二维码信息,即使二维码被拉伸、压扁也能被准确识别。
注意: 如果位置探测图形被遮挡,就无法识别二维码。
位置探测图形如图2.5.3所示,无论版本如何,这个图案的尺寸就是这么大,根据位置探测图形的大小可以推算QR码整体的大小。
❑ 版本信息 :即二维码的规格。QR码符号共有40种规格的矩阵,官方称为版本(Version)。Version 1是21×21的矩阵,Version 2是25×25的矩阵,Version 3是29×29的矩阵。版本号每增加一,尺寸就会增加4,版本号和尺寸对应公式为:(V-1)×4+21(V是版本号),版本号最高为40,对应的尺寸为(40-1)×4+21=177,即177×177的正方形。
图2.5.3 位置探测图形所占像素大小
❑ 校正图形 :版本确定后,校正图形的数量和位置也就确定了。
❑ 格式信息 :表示该二维码的 纠错级别和选用的掩码模式 。纠错级别分为L、M、Q、H,分别对应7%、15%、25%、30%的容错度。也就是说,如果生成二维码时选择H级的容错度,那么即使30%的图案被遮挡,也可以被正确扫描。这也是很多二维码中间被加上各种图形也能被正确识别的原因。
❑ 数据和纠错码字 :实际保存的数据和纠错码字。纠错码字(也叫校验区)用于校验数据是否正确并对其修复。
这里我们不准备讲解二维码的所有生成和扫码细节,读者们知道上述各区域的功能和位置即可。在平时的练习过程中,遇到二维码后可以用手机扫描,但是一些CTF比赛不让使用手机,因此我们需要提前准备好离线扫描工具,这里强烈推荐QR Research(工具包中)。该工具在Windows10系统下运行可能会有问题,建议在Windows7虚拟机中运行。使用方法为,双击CQR.exe,如图2.5.4所示,“鼠标”按钮是区域解码,可以选择指定区域后解码;其左侧的“屏幕”按钮是全屏解码,会把当前屏幕中的二维码解码。图中的二维码有遮挡且位置探测图形缺失,但是QR Research仍然可以解码成功。
图2.5.4 QR Research离线扫码
大部分二维码只由黑白两种颜色构成,因此可以用0与1分别表示黑或白。这样的题目往往只给一个01字符串,需要我们根据01字符串画图以生成二维码。
【例题】question.txt
【题目来源】 2018央企大赛。
【题目描述】 找到文件中的flag。
【解题思路】 TXT文件中是01字符串,因此我们首先想到二进制。如果采用二进制表示信息,我们习惯用8比特表示一个字节。因此,二进制信息流的长度通常是8的倍数。但本例中信息总长度是729字节,729不能被8整除,我们猜测题目的考点并不是二进制。
这时重点关注文本长度,729是27的平方,考虑可能是二维码的变形。将字符串整理为27个字符一行,并增加空格(可利用替换功能快速完成),如图2.5.5所示,不难看出这是个二维码,但是无法扫码,我们需要根据01把QR码画出来。这里提供两种思路:①写脚本画图。②利用Excel画图。我们演示思路②的操作。把整理后的文档保存成txt文件。新建Excel文件,单击“文件”菜单,选择“打开”,再选择整理后的TXT文件,然后选择“分隔符号→空格”,导入后如图2.5.6所示。选中内容为1的单元格,用<Ctrl+f>组合键打开替换窗口,选择“选项”,替换方法如图2.5.7所示,通过设置格式将背景变成黑色。调整单元格宽度,使得二维码呈正方形,扫码后就得到Flag{fucbw5rxlx}。
图2.5.5 人工整理
图2.5.6 导入Excel
图2.5.7 高级替换
QR码修复也是比赛中经常遇到的考点。比较简单的考法是只修复位置探测图形,稍微复杂的考法是只给一半二维码,让参赛选手修复另一半。QR码修复不需要特别专业的工具,使用Windows自带的画图工具就可以完成修复。
【例题】biu.png
【题目描述】 找到文件中的flag。
【解题思路】 图像是个残缺的二维码,使用画图工具打开,3个位置探测图形中只有一个。可以把仅有的这个位置探测图形抠出来,再复制到相应的位置。使用画图工具中的选择功能,选择仅有的位置探测图形,然后使用<Ctrl+C>组合键和<Ctrl+V>组合键实现复制、粘贴,调整好位置后再次使用<Ctrl+V>组合键进行粘贴,调整位置。最后扫码就能看到flag。对于QR Research工具而言,不需要把3个位置探测图形都修复,只要有2个位置探测图形完好,就可以扫码。
在稍微复杂的题目中,只提供一半二维码,理论上需要我们根据数据恢复纠错码(或者根据纠错码恢复数据),再拼接得到完整的二维码。目前,有些现成的工具可以帮助我们完成二维码的修复。
【例题】broken_qr.png
【题目描述】 找到文件中的flag。
【解题思路】 打开图像,发现是右半张QR码,需要修复。推荐使用工具QRazyBox(网址为https://github.com/merricx/qrazybox/),该工具可以修复破损比较严重二维码。具体方法如下:首先查看PNG图片,根据位置探测图形的大小,得到对应的二维码规格是29×29。在QRazyBox选择对应的版本,如图2.5.8所示。
图2.5.8 选定二维码规格
然后单击图中的蓝色方格,这个位置对应QR码的“格式信息”,如图2.5.9所示。我们需要选择纠错级别和掩码图形,这里需要经过多次尝试,与PNG图中格式信息图形相一致,最后确定纠错级别是H,掩码图形是6。
接下来,按照PNG图像填入方格,如图2.5.10所示,未知区域使用油漆桶工具填充为白色。单击右上角的“Tools→Extract QR Information”,即可看到flag{Broken_Qr_Hah@}。
图2.5.9 选择格式信息
图2.5.10 根据题目画出二维码