一、Keyes_secret
题目链接:https://adworld.xctf.org.cn/task/task_list?type=misc&number=1&grade=1&page=5
二、答题步骤
1.下载附件
得到一张图片:
首先,我们需要基于上图的干净图像。
此二维码的大小为 29x29,版本V的大小为N × N,N = 17 + 4V,所以这是版本 3。
2.二维码格式信息
该区域表示二维码的格式信息。实际上,格式信息是 15 位长,区域有最后 8 位。
搜索所有格式信息字符串的列表,我们可以发现类型信息位是001001110111110.所以这个二维码有ECC级别H和掩码模式1。
所有格式信息字符串的列表:
ECC 级别 蒙版图案 类型信息位
1 号掩码有公式(row) mod 2 == 0。注意行号是从0开始的,所以我们要切换坐标为0,2,4,…,28的行的位。
所以4行2列一组,原始的 D1-D26 是:
D1 = 0b11101100 D14 = 0b10000010 D2 = 0b11111000 D15 = 0b10010101 D3 = 0b00110110 D16 = 0b00111101 D4 = 0b01110110 D17 = 0b01100010 D5 = 0b00100010 D18 = 0b11101001 D6 = 0b11110001 D19 = 0b10100001 D7 = 0b00110111 D20 = 0b11100101 D8 = 0b01010010 D21 = 0b11010101 D9 = 0b00010111 D22 = 0b00101101 D10 = 0b11011110 D23 = 0b10010111 D11 = 0b01000100 D24 = 0b10001011 D12 = 0b01010100 D25 = 0b01111000 D13 = 0b11001101 D26 = 0b11000110
(行) mod 2 == 0 掩码之后
D1 = 0b00100000 D14 = 0b01001110 D2 = 0b00110100 D15 = 0b01011001 D3 = 0b11111010 D16 = 0b00001110 D4 = 0b01000101 D17 = 0b01010001 D5 = 0b00010001 D18 = 0b11011010 D6 = 0b00111101 D19 = 0b10010010 D7 = 0b00000100 D20 = 0b11010101 D8 = 0b10011110 D21 = 0b00011001 D9 = 0b11010100 D22 = 0b00010001 D10 = 0b00010100 D23 = 0b00001110 D11 = 0b11011101 D24 = 0b00010010 D12 = 0b11010010 D25 = 0b00011111 D13 = 0b01010100 D26 = 0b01000000
3.数据解码
解码有模式指示符:
0001:数字模式(每 3 位 10 位) 0010:字母数字模式(每 2 个字符 11 位) 0100:字节模式(每个字符 8 位) 1000:汉字模式(每个字符 13 位) 0111: ECI 模式
字符计数指示符跟在模式指示符之后。
版本 1-9 数字模式:10 位 字母数字模式:9位 字节模式:8位 汉字模式:8位 版本 10–26 数字模式:12位 字母数字模式:11 位 字节模式:16位 汉字模式:10位 版本 27–40 数字模式:14位 字母数字模式:13 位 字节模式:16位 汉字模式:12位
4.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
使用 Ruby 运行上述代码来获得falg:SECCON{PSwIQ9d9GjKTdD8H}
总结
二维码
ruby