本题思路与CTFSHOW: 36D杯 misc ez-qrcode思路相同
工具链接:补全二维码QRazyBox - QR Code Analysis and Recovery Toolkit (h3110w0r1d.com)
1.首先,我们需要基于上图的干净图像。
此二维码的大小为 29x29,版本V的大小为N × N,N = 17 + 4V,所以这是版本 3。
2.二维码格式信息
该区域表示二维码的格式信息。实际上,格式信息是 15 位长,区域有最后 7位。
所以二维码的信息字符串为????????0111110。再结合所有格式信息字符串的列表
所有格式信息字符串的列表:
ECC 级别 蒙版图案 类型信息位
L 0 111011111000100
L 1 111001011110011
L 2 111110110101010
L 3 111100010011101
L 4 110011000101111
L 5 110001100011000
L 6 110110001000001
L 7 110100101110110
M 0 101010000010010
M 1 101000100100101
M 2 101111001111100
M 3 101101101001011
M 4 100010111111001
M 5 100000011001110
M 6 100111110010111
M 7 100101010100000
Q 0 011010101011111
Q 1 011000001101000
Q 2 011111100110001
Q 3 011101000000110
Q 4 010010010110100
Q 5 010000110000011
Q 6 010111011011010
Q 7 010101111101101
H 0 001011010001001
H 1 001001110111110
H 2 001110011100111
H 3 001100111010000
H 4 000011101100010
H 5 000001001010101
H 6 000110100001100
H 7 000100000111011
所以这个二维码有ECC级别H和掩码模式1
1 号掩码有公式(row) mod 2 == 0。注意行号是从0开始的,所以我们要切换坐标为0,2,4,…,28的行的位。
二维码也有固定的图案,所以我们只需要切换数据部分的位即可。查看数据区和位顺序。
掩码号 如果下面的公式对于给定的行/列坐标为真,则切换该坐标处的位
0 (行 + 列) mod 2 == 0
1 (行) mod 2 == 0
2 (列) mod 3 == 0
3 (行 + 列) mod 3 == 0
4 (楼(行 / 2)+ 楼(列 / 3)) mod 2 == 0
5 ((行 * 列) mod 2) + ((行 * 列) mod 3) == 0
6 ( ((行 * 列) mod 2) + ((行 * 列) mod 3) ) mod 2 == 0
7 ( ((行 + 列) mod 2) + ((行 * 列) mod 3) ) mod 2 == 0
使用在线工具QRazyBox - QR Code Analysis and Recovery Toolkit (h3110w0r1d.com)
所以我们拿到掩码信息并且(row) mod 2 == 0,及取0,2,4,6,8,10……的数据
3.ruby脚本:(在线网站运行)
data = '00100000' \'00110100' \'11111010' \'01000101' \'00010001' \'00111101' \'00000100' \'10011110' \'11010100' \'00010100' \'11011101' \'11010010' \'01010100' \'01001110' \'01011001' \'00001110' \'01010001' \'11011010' \'10010010' \'11010101' \'00011001' \'00010001' \'00001110' \'00010010' \'00011111' \'01000000'
alphanumeric = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'.charsdef read(str, size)str.slice!(0, size)
enddef kanji(num)if num >= 0x1740(0xC140 + num / 0xC0 * 0x100 + num % 0xC0).chr(Encoding::Shift_JIS).encode(Encoding::UTF_8)else(0x8140 + num / 0xC0 * 0x100 + num % 0xC0).chr(Encoding::Shift_JIS).encode(Encoding::UTF_8)end
endloop docase mode = read(data, 4)when '0010' # Alphanumericcount = read(data, 9).to_i(2)(count / 2).times dochunk = read(data, 11).to_i(2)print alphanumeric[chunk / 45] + alphanumeric[chunk % 45]endprint alphanumeric[read(data, 11).to_i(2)] if count.odd?when '0100' # Bytecount = read(data, 8).to_i(2)count.times doprint read(data, 8).to_i(2).chrendwhen '1000' # Kanjicount = read(data, 8).to_i(2)count.times doprint kanji(read(data, 13).to_i(2))endwhen '0000' # Terminatebreakelsefail "Unhandled mode #{mode}"end
end
3.python脚本:
# D1-D26:
data = ['01000001', '01100110', '01100110', '11000110', '00010110', '01110111', '10110101', '01000110', '01110100', '00110110', '00010110', '11100110', '11100110', '11110111', '01000100', '01110110', '01010111', '01000100', '10000110', '11110111', '01010111', '00110110', '01010111', '11010000', '11101100', '00010001']
#data是掩码
data = "".join(data)
data = data[4:]for i in range(0, len(data), 8):print(chr(int(data[i:i+8], 2)), end="")
参考文章:
CTFSHOW: 36D杯 misc ez-qrcode_ctfshow 36d杯 misc-CSDN博客
【愚公系列】2022年02月 攻防世界-进阶题-MISC-83(qr-easy)-腾讯云开发者社区-腾讯云 (tencent.com)