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()

posted @ 2025-09-11 16:51  JasonJHu  阅读(20)  评论(0)    收藏  举报