解题步骤
- 解压 image\_04.zip,获取 image\_04.png。
- 读取 PNG 结构,IEND 块后残留 64 字节数据,为隐写密文。
- 密文结构:4 字节填充 + 4 字节 seed + XOR 密文。
- 用 seed 初始化 LCG,生成随机数与密文异或,得到 Base62 字符串。
- Base62 转字节,UTF-8 解码得到 flag。
完整 EXP
#!/usr/bin/env python3
import argparse
import string
import struct
import zipfile
from pathlib import Path
# LCG参数
A = 1664525
C = 1013904223
MASK = 0xFFFFFFFF
# Base62字符集
B62 = string.digits + string.ascii_lowercase + string.ascii_uppercase
# 读取ZIP中的PNG
def get_png_data(zip_file: Path):
with zipfile.ZipFile(zip_file, 'r') as zf:
png_list = [n for n in zf.namelist() if n.lower().endswith('.png')]
if not png_list:
raise RuntimeError(\"No PNG inside archive\")
target_name = png_list[0]
return target_name, zf.read(target_name)
# 截取IEND块后的数据
def cut_after_iend(data: bytes) -> bytes:
if not data.startswith(b'\\x89PNG\\r\
\\x1a\
'):
raise RuntimeError(\"Not a valid PNG file\")
offset = 8
data_len = len(data)
while offset + 8 <= data_len:
chunk_len = struct.unpack('>I', data[offset:offset+4])[0]
chunk_type = data[offset+4:offset+8]
offset += 8 + chunk_len + 4
if chunk_type == b'IEND':
return data[offset:]
raise RuntimeError(\"IEND chunk missing\")
# LCG解密
def lcg_decrypt(raw: bytes):
if len(raw) < 8:
raise RuntimeError(\"Trailer data too short\")
seed = int.from_bytes(raw[4:8], 'big')
cur = seed
out = bytearray()
for b in raw[8:]:
cur = (A * cur + C) & MASK
out.append(b ^ (cur & 0xFF))
return seed, bytes(out)
# Base62解码
def b62_decode(s: str) -> bytes:
num = 0
for c in s:
num = num * 62 + B62.index(c)
byte_cnt = (num.bit_length() + 7) // 8
return num.to_bytes(byte_cnt, 'big')
# 解析文件
def parse_file(zip_path: Path):
png_name, png_buf = get_png_data(zip_path)
tail = cut_after_iend(png_buf)
seed, dec_buf = lcg_decrypt(tail)
b62_str = dec_buf.rstrip(b'\\x00').decode('ascii')
flag = b62_decode(b62_str).decode('utf-8')
return {
'zip_path': str(zip_path),
'png_name': png_name,
'png_size': len(png_buf),
'tail_size': len(tail),
'seed_hex': f\"0x{seed:08x}\",
'b62_str': b62_str,
'flag': flag
}
# 扫描目标文件
def scan_targets(input_list: list[str]) -> list[Path]:
if not input_list:
input_list = [str(Path(__file__).parent.resolve())]
paths = []
for item in input_list:
p = Path(item)
if p.is_dir():
paths += sorted(p.glob('*.zip'))
else:
paths.append(p)
return paths
# 主运行
def run():
parser = argparse.ArgumentParser()
parser.add_argument('targets', nargs='*')
args = parser.parse_args()
file_list = scan_targets(args.targets)
if not file_list:
print(\"[!] No ZIP files found\")
return
for fp in file_list:
try:
res = parse_file(fp)
except Exception as e:
print(f\"[!] {fp}: {str(e)}\")
continue
print(f\" Flag: {res['flag']}\
\")
if __name__ == \"__main__\":
run()
关键截图
flag
flag{memory_dump_analysis}
19、签到题 - 损坏的压缩包|Base64 解码
题目:data.txt,内容为 Base64 字符串
考点:基础 Base64 解码
解题步骤
- 打开 data.txt,内容:
a2Jzdg==。 - 直接 Base64 解码,得到 flag。
关键截图
flag
flag{kbsv}
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论