2026.8.10(5)【Misc】qr

📌 题目信息

项目内容
题目名称qr
题目来源青少年CTF S1·2026 公益赛
题目类型Misc
子分类二维码还原 / 像素点阵
考点二进制点阵 → 二维码图片 → 扫码
难度⭐⭐
最终 Flagflag{56876aae7cb7b98a3756bac05c6b6675}

🛠️ 使用工具

  • Python3 + PIL(Pillow):读取二进制点阵并按行列绘制二维码
  • OpenCV(py) QRCodeDetector:对生成的二维码图片扫码提取 flag
  • 也可用手机/任意扫码工具识别

📝 解题思路

附件 qr.txt 里是一串 0/1,本质是二维码的像素点阵数据(每个 0/1 代表一个黑白模块)。思路分三步:

  1. 把 0/1 按行列排成方形矩阵
  2. 按矩阵绘制成二维码图片(0=黑模块、1=白背景);
  3. 用扫码工具识别图片,读出 flag。

一步直达:在记事本里把字体缩放到最小,然后扫描二维码即可得到flag。

第 1 步:解析点阵,确定边长

qr.txt 内容是 0/1,注意它是用空格 + 换行分隔的:

0 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 ...
...

直接 read().strip() 会把空格也算进长度,导致边长算错。必须先去掉所有空白,再算边长:

bits = ''.join(open('qr.txt').read().split())  # 去空格和换行
print(len(bits))          # 40000  => 200 x 200
import math
print(int(len(bits)**0.5)) # 200

⚠️ 易错点(本份文件的关键):如果直接 read().strip() 不去空格,长度会是 79999,平方根算出 282,完全错误。一定要先 split() 去掉所有空白,得到纯 0/1 串 40000 = 200²,边长才是 200。


第 2 步:按矩阵绘制二维码

用 PIL 新建一张 1(黑白)模式的图,逐像素按 0/1 上色:这里把 1 画成黑色模块(也可反过来,只要能扫出来):

from PIL import Image

def qrcode(txt_path, output_path, module_size=10):
    with open(txt_path, 'r') as f:
        bits = ''.join(f.read().split())     # 关键:去掉空格/换行
    size = int(len(bits) ** 0.5)             # 200
    img_size = size * module_size
    img = Image.new('1', (img_size, img_size), 1)  # 背景白(1)

    for y in range(size):
        for x in range(size):
            idx = y * size + x
            if idx < len(bits) and bits[idx] == '1':
                # 把这一模块画成黑块
                for dy in range(module_size):
                    for dx in range(module_size):
                        img.putpixel((x*module_size+dx, y*module_size+dy), 0)
    img.save(output_path)
    print("边长:", size)

qrcode("qr.txt", "qrcode.png", module_size=10)

⚠️ 注意:module_size 是每个模块的放大倍数(这里 10),让二维码足够大、便于扫码。Image.new('1', ...)'1' 模式(1 位黑白)即可。

运行后得到 qrcode.png(2000×2000 黑白二维码图)。

第 3 步:扫码获取 Flag

直接用 OpenCV 内置的二维码检测器解码:

import cv2
img = cv2.imread("qrcode.png")
det = cv2.QRCodeDetector()
flag, _, _ = det.detectAndDecode(img)
print(flag)

输出:

flag{56876aae7cb7b98a3756bac05c6b6675}

✅ 最终 Flag

flag{56876aae7cb7b98a3756bac05c6b6675}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值