本题思路与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 $%*+-./:'.chars
def read(str, size)
str.slice!(0, size)
end
def 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
end
loop do
case mode = read(data, 4)
when '0010' # Alphanumeric
count = read(data, 9).to_i(2)
(count / 2).times do
chunk = read(data, 11).to_i(2)
print alphanumeric[chunk / 45] + alphanumeric[chunk % 45]
end
print alphanumeric[read(data, 11).to_i(2)] if count.odd?
when '0100' # Byte
count = read(data, 8).to_i(2)
count.times do
print read(data, 8).to_i(2).chr
end
when '1000' # Kanji
count = read(data, 8).to_i(2)
count.times do
print kanji(read(data, 13).to_i(2))
end
when '0000' # Terminate
break
else
fail "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)