202003_MRCTF_千层套娃
Tags:ZIP套娃
,QRCODE
0x00. 题目
附件路径:https://pan.baidu.com/s/1GyH7kitkMYywGC9YJeQLJA?pwd=Zmxh#list/path=/CTF附件
附件名称:202003_MRCTF_千层套娃.zip
0x01. WP
01. 打开压缩文件发现hint信息
发现是zip套娃,需要通过python脚本进行自动化解压
Hint:密码均为四位数字 和压缩包名字有关联哦
Python真好用233
autoUnzip.py
import zipfile
import os
import re
def find_next_zip():
"""查找当前目录及子目录中下一个四位数字命名的ZIP文件"""
for root, dirs, files in os.walk('.'):
for file in files:
if re.match(r'^\d{4}\.zip$', file):
return os.path.join(root, file)
return None
def extract_zip(i,current_zip, password):
"""解压指定ZIP文件并使用给定密码"""
try:
with zipfile.ZipFile(current_zip) as zf:
zf.extractall(pwd=password.encode('utf-8'))
print(f"第{i}层,解压成功: {current_zip} ,密码: {password}")
return True
except zipfile.BadZipFile:
print(f"第{i}层,错误: {current_zip} 不是一个有效的ZIP文件")
return False
except RuntimeError as e:
if 'password' in str(e).lower():
print(f"第{i}层,密码错误: {current_zip} - 预期密码: {password}")
else:
print(f"第{i}层,解压失败: {e}")
return False
def main(start_zip):
current_zip = start_zip
max_attempts = 5000 # 防止无限循环
for _ in range(max_attempts):
# 提取密码(文件名不含扩展名)
password = os.path.splitext(os.path.basename(current_zip))[0]
# print(current_zip)
# 执行解压
if not extract_zip(_,current_zip, password):
break
# 删除已处理的ZIP文件以保持清洁(可选)
os.remove(current_zip)
# 查找下一个符合条件的ZIP
next_zip = find_next_zip()
if not next_zip:
print("已找到最内层文件,结束解压流程")
break
current_zip = next_zip
print(f"最终保留的文件: {current_zip}" if os.path.exists(current_zip) else "所有压缩文件已处理完毕")
if __name__ == "__main__":
initial_zip = "0573.zip" # 初始文件名,按实际修改
if os.path.exists(initial_zip):
main(initial_zip)
else:
print(f"初始文件 {initial_zip} 不存在!")
别的师傅的精简脚本 unzip.py
import zipfile
name = '0573'
while True:
fz = zipfile.ZipFile(name + '.zip', 'r')
fz.extractall(pwd=bytes(name, 'utf-8'))
name = fz.filelist[0].filename[0:4]
fz.close()
2. 逐层解压得到最里面是个文本文件,进行二维码解码
包含了40000行信息,只有(255, 255, 255)
和(0, 0, 0)
,初步判断是个二维码,需要python脚本构图并读取
autoQR.py
# Usage: python qr.py qr.txt
from PIL import Image
import re
import argparse # 新增参数解析模块
from pyzbar.pyzbar import decode # 新增二维码识别模块
from pyzbar.pyzbar import ZBarSymbol # 新增符号类型限定
def parse_pixel(line):
"""解析单行像素数据,返回(r, g, b)元组"""
matches = re.findall(r'\d+', line)
if len(matches) != 3:
raise ValueError(f"无效的像素格式: {line}")
r = min(max(int(matches[0]), 0), 255)
g = min(max(int(matches[1]), 0), 255)
b = min(max(int(matches[2]), 0), 255)
return (r, g, b)
def txt_to_image(input_file, output_file="output.png"):
"""将文本像素文件转换为图片并进行二维码解析"""
try:
with open(input_file, 'r') as f:
lines = [line.strip() for line in f if line.strip()]
if len(lines) != 200*200:
raise ValueError(f"文件应包含40000行数据,实际检测到{len(lines)}行")
img = Image.new('RGB', (200, 200))
pixels = img.load()
for index, line in enumerate(lines):
y = index // 200
x = index % 200
pixels[x, y] = parse_pixel(line)
img.save(output_file)
print(f"图片已生成:{output_file}")
# 新增二维码识别功能 ################################
print("\n开始二维码扫描...")
detected_qrcodes = decode(
img,
symbols=[ZBarSymbol.QRCODE] # 仅检测QR Code
)
if detected_qrcodes:
print("发现二维码内容:")
for qr in detected_qrcodes:
content = qr.data.decode('utf-8')
print(f"• 位置 {qr.rect} -> {content}")
# 可选:保存识别到的二维码内容到文本文件
with open('qrcode_content.txt', 'w') as f:
f.write(content)
else:
print("未检测到有效二维码")
# ################################################
except FileNotFoundError:
print(f"错误:输入文件 {input_file} 不存在")
except ValueError as ve:
print(f"数据错误:{ve}")
except Exception as e:
print(f"运行时异常:{e}")
def main():
parser = argparse.ArgumentParser(description='像素转图片+二维码识别')
parser.add_argument('input', help='输入文本文件路径')
parser.add_argument('-o', '--output', default='output.png',
help='输出图片路径,默认output.png')
args = parser.parse_args()
txt_to_image(args.input, args.output)
if __name__ == "__main__":
main()
# MRCTF{ta01uyout1nreet1n0usandtimes}
别的师傅的精简脚本 qr.py
import itertools
from PIL import Image
max = 200
file = open("qr.txt", "r")
img = Image.new("RGB", (max, max))
for y, x in itertools.product(range(max), range(max)):
pixel = eval(file.readline())
img.putpixel([x, y], pixel)
img.show()