文章总结: 本文档详细记录了第十届御网杯网络安全大赛的解题过程,涵盖WEB和PWN两大方向。WEB部分包括贪吃蛇前端数据伪造、PHP反序列化漏洞利用、目录穿越绕过、FlaskSSTI注入与Session伪造;PWN部分涉及基础栈溢出、ret2text后门利用、栈可执行Shellcode注入等技术。文档提供了完整的漏洞分析、解题步骤和EXP代码,具有实战参考价值。 综合评分: 85 文章分类: CTF,WEB安全,二进制安全,实战经验,漏洞分析
解题步骤
- 解压 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\n\x1a\n'):
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']}\n")
if __name__ == "__main__":
run()
关键截图
flag
flag{memory_dump_analysis}
19、签到题 – 损坏的压缩包|Base64 解码
题目:data.txt,内容为 Base64 字符串
考点:基础 Base64 解码
解题步骤
- 打开 data.txt,内容:
a2Jzdg==。 - 直接 Base64 解码,得到 flag。
关键截图
flag
flag{kbsv}
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:赛查查 《第十届御网杯网络安全大赛 Write Up》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论