不只是扫一扫用Python玩转CTF中的二维码生成与花式隐写Stegosaurus/PIL实战在CTF竞赛的Misc类题目中二维码和隐写技术堪称黄金搭档。但大多数解题攻略止步于工具使用鲜少深入技术原理与自动化实现。本文将用Python代码实战带你从二进制数据解析到动态生成二维码再到Stegosaurus工具的深度应用构建完整的解题技术链。1. 二维码的底层逻辑与Python生成实战二维码的本质是二进制矩阵的艺术。理解其编码规则才能应对CTF中各种魔改题型。以经典的25x25二维码为例其核心结构包含定位图案三个角落的回字形方框时序图案黑白相间的导航线数据区实际存储信息的模块纠错码Reed-Solomon编码的冗余数据from PIL import Image def create_qr_matrix(data_str, size25): 将01字符串转换为二维码矩阵 matrix [] for i in range(size): row [int(data_str[i*size j]) for j in range(size)] matrix.append(row) return matrix def draw_qr(matrix, cell_size10): 可视化二维码矩阵 img Image.new(RGB, (len(matrix[0])*cell_size, len(matrix)*cell_size), white) pixels img.load() for y in range(len(matrix)): for x in range(len(matrix[0])): color (0, 0, 0) if matrix[y][x] else (255, 255, 255) for dy in range(cell_size): for dx in range(cell_size): pixels[x*cell_sizedx, y*cell_sizedy] color return img # 示例手工构造的25x25二维码数据 sample_data 1111111000100001101111111100000101110010110100000110111010100000000010111011011101001000000001011101101110101110110100101110110000010101011011010000011111111010101010101111111000000001011101110000000011010011000001010011101101111010101001000011100000000000101000000001001001101000100111001111011100111100001110111110001100101000110011100001010100011010001111010110000010100010110000011011101100100001110011100100001011111110100000000110101001000111101111111011100001101011011100000100001100110001111010111010001101001111100001011101011000111010011100101110100100111011011000110000010110001101000110001111111011010110111011011 qr_matrix create_qr_matrix(sample_data) draw_qr(qr_matrix).show()注意实际CTF题目中二维码数据可能隐藏在IDAT块、文件末尾或像素LSB中需要先进行数据提取和清洗2. 从二进制到二维码的自动化流水线CTF中的二维码往往不会直接给出图片文件而是隐藏在各类数据格式中。以下是典型处理流程数据提取PNG文件解析IDAT块使用zlib解压流量包过滤HTTP传输提取二进制流文本文件转换十六进制或Base64编码格式转换处理字节序问题修正损坏的文件头尾转换数据维度如将一维数组转为二维矩阵可视化生成处理非标准尺寸如625位数据可能是25x25矩阵添加定位图案等必要元素import zlib import struct def extract_idat(png_path): 从PNG文件中提取异常IDAT块 with open(png_path, rb) as f: data f.read() # 查找IDAT标记(0x49444154) idat_pos data.find(bIDAT) - 4 length struct.unpack(I, data[idat_pos:idat_pos4])[0] return data[idat_pos8:idat_pos8length] def decode_zlib(data): 解压zlib压缩数据 return zlib.decompress(data) # 实战示例 idat_data extract_idat(hidden_qr.png) raw_data decode_zlib(idat_data) qr_matrix create_qr_matrix(bin(int.from_bytes(raw_data, big))[2:].zfill(625))3. StegosaurusPython字节码隐写的黑科技Stegosaurus工具利用Python字节码(.pyc)文件的特性实现隐写特性说明无效空间利用参数占位字节存储Payload编码密度低平均每100字节pyc可隐藏5字节运行时透明不影响原程序执行逻辑抗检测性强strings等工具无法直接发现安装与基础使用git clone https://github.com/AngelKitty/stegosaurus.git cd stegosaurus python stegosaurus.py -p secret_message target.pycCTF实战案例从题目给出的.pyc文件中提取隐藏信息python stegosaurus.py -x challenge.pyc隐藏解题脚本到提供的.pyc中# 生成包含Payload的.pyc with open(payload.txt, w) as f: f.write(print(FLAG{hidden_in_pyc})) !python stegosaurus.py -p payload.txt sample.pyc -o infected.pyc4. 综合实战从数据碎片到flag的完整链条假设获得一个经过多重处理的文件解题步骤如下文件分析import binascii def file_signature(file_path): with open(file_path, rb) as f: return binascii.hexlify(f.read(8)).decode() print(file_signature(mystery.bin)) # 输出89504e470d0a1a0a → PNG文件数据修复与提取def repair_png(broken_data): # 添加缺失的IEND块 return broken_data bytes.fromhex(0000000049454e44ae426082) with open(mystery.bin, rb) as f: fixed_data repair_png(f.read()[8:-4]) # 去除错误头尾二维码生成与解码from pyzbar.pyzbar import decode qr_img draw_qr(extract_matrix_from_idat(fixed_data)) result decode(qr_img) print(result[0].data.decode()) # 输出隐藏的flag或下一步提示进阶处理如遇Python字节码import subprocess # 使用Stegosaurus提取隐藏信息 output subprocess.check_output([python, stegosaurus.py, -x, hidden.pyc]) print(output.split(bExtracted payload:)[-1].decode().strip())在实战中可能需要组合多种技术。例如某次比赛中我们需要先修复损坏的PNG文件头提取异常的IDAT块数据将zlib解压后的二进制转为二维码扫描二维码获得.pyc文件最后用Stegosaurus提取出flag这种技术链条的构建能力正是区分普通选手与高手的核心要素。掌握这些技能后面对各类二维码隐写题目时你将拥有系统化的解题思路而非盲目尝试各种工具。