2026软件系统安全赛初赛MISC--steganography

前言

一个更好的方法与本文章方法不一样,都可以用来参考。

解题

下载附件得到一个无后缀文件

发现头部被修改。

如果想知道如何判断,可以参考:
CTF必知:以一次MISC题目完整分析png图片16进制分别代表什么(干货满满!)

python 复制代码
data = open("steganography_challenge","rb").read()
print("Header:",data[:35].hex())
idx = data.find(b"\x89PNG")
print("PNG at offset:",idx)

到35字节的地方有PNG的IDAT。

删除前面的字节后。

用zsteg功能扫描一下。

前面的因为跳过的报错不用管,只需要注意最后一条118行无效滤波字节 254。这个警告说明 PNG 滤波字节被修改了。

说明图片身高造假,就是要修改一下图片的高。

把高改成00 00 00 76(118)即可。

如果想知道如何判断,可以参考:
CTF必知:以一次MISC题目完整分析png图片16进制分别代表什么(干货满满!)

提取成功。

解压后每个压缩包都加密了。

但是其中6个和密码有关的只有4个字节。

CRC爆破。

可以用代码:

python 复制代码
import binascii, struct, itertools, string
 
# 从各 pass*.zip 头中读取 CRC32
crcs = {
    "pass1": 0xce70d424,
    "pass2": 0xf90c8a70,
    "pass3": 0xff3fe4bb,
    "pass4": 0x242a5387,
    "pass5": 0x9a27098e,
    "pass6": 0xd3f6df9f,
}
 
# 枚举所有 4 字节可打印 ASCII,匹配 CRC32
charset = "".join(chr(i) for i in range(32, 127))
crc_to_plain = {}
for combo in itertools.product(charset, repeat=4):
    candidate = "".join(combo).encode()
    c = binascii.crc32(candidate) & 0xffffffff
    if c in set(crcs.values()):
        crc_to_plain[c] = candidate.decode()

这4个是CRC32。如果想知道如何判断,可以参考:
CTF必知:以一次MISC题目完整分析png图片16进制分别代表什么(干货满满!)

脚本:

python 复制代码
#!/usr/bin/env python3
import binascii
import itertools
import string
from concurrent.futures import ThreadPoolExecutor

crc_dict = {
    'ce70d424': 'pass1',
    'f90c8a70': 'pass2',
    'ff3fe4bb': 'pass3',
    '242a5387': 'pass4',
    '9a27098e': 'pass5',
    'd3f6df9f': 'pass6'
}

targets = {int(k, 16): v for k, v in crc_dict.items()}
chars = "".join(chr(i) for i in range(32, 127))  # 修复 Bug
results = {}
lock = __import__('threading').Lock()

def check_batch(batch):
    """检查一批组合"""
    local_results = {}
    for p in batch:
        s = "".join(p)
        crc = binascii.crc32(s.encode()) & 0xffffffff
        if crc in targets:
            local_results[targets[crc]] = s
    return local_results

def main():
    print("开始 CRC32 碰撞爆破...")
    print(f"目标 CRC 数:{len(targets)}")
    print(f"字符集大小:{len(chars)}")
    print(f"总组合数:{len(chars)**4:,}")
    print()
    
    # 分批次处理
    all_combos = itertools.product(chars, repeat=4)
    batch_size = 100000
    batch = []
    completed = 0
    
    with ThreadPoolExecutor(max_workers=8) as executor:
        futures = []
        for combo in all_combos:
            batch.append(combo)
            completed += 1
            
            if len(batch) >= batch_size:
                futures.append(executor.submit(check_batch, batch.copy()))
                batch = []
            
            if completed % 1000000 == 0:
                print(f"进度:{completed:,}/{len(chars)**4:,}")
        
        # 处理剩余
        if batch:
            futures.append(executor.submit(check_batch, batch))
        
        # 收集结果
        for future in futures:
            for name, s in future.result().items():
                if name not in results:
                    results[name] = s
                    print(f"✓ {name} = {s}")
        
        # 检查是否完成
        if len(results) == 6:
            print("\n" + "="*50)
            pwd = "".join([results[f'pass{i}'] for i in range(1, 7)])
            print(f"🎉 密码:{pwd}")
            print("="*50)
            return pwd
    
    print(f"\n只找到 {len(results)}/6 个")
    return None

if __name__ == '__main__':
    main()

或者直接用ZipCracker。

最终得到:

python 复制代码
pass is c1!xxtLf%fXYPkaA

解压后得到:

存在零宽字符隐写。

python 复制代码
txt = open("flag.txt",encoding="utf-8").read()
ZWSP = "\u200b" 
ZWNJ = "\u200c"

bits = []
for char in txt:
    if char == ZWSP:
        bits.append("0")
    elif char == ZWNJ:
        bits.append("1")

flag = ""
for i in range(0,len(bits) - 7 ,8):
    flag += chr(int("".join(bits[i:i+8]),2))

print(flag) 

得到dart{bf4100d9-cc8d-48f6-a095-54cbfad189e1}。

相关推荐
这个DBA有点耶4 小时前
2026年分布式数据库有哪些主流选择?先评估这5个维度再决定
数据库·分布式·dba
这个DBA有点耶7 小时前
从MySQL 5.7到8.0:JSON查询性能差在哪?虚拟列索引vs多值索引怎么选
数据库·mysql·架构
胡写代码7 小时前
数据库审计字段,别再每张表各写一套了——我统一成这 6 个字段
数据库
SelectDB11 小时前
为什么 JSON 正在成为分析数据库新的竞争点?
数据库·json·agent
ClouGence12 小时前
开源数据库管理工具 CloudDM 4.2.0 发布,新增 GoldenDB、KingbaseES 等数据源
数据库·dba·devops
发霉的馒头12 小时前
ORA-00845: MEMORY_TARGET not supported on this system的解决方法
数据库
草莓熊Lotso14 小时前
【Redis 初阶】Set 类型深度解析:去重集合的运算能力与实战场景
linux·网络·数据库·windows·redis·tcp/ip·缓存
煎饼皮皮侠15 小时前
【设计】设计一个web版的数据库管理平台后端(之五) --借鉴mybatis
数据库·mybatis
东风破_1 天前
danci 2:创建的单词书到底存在哪里?从 Supabase 一路理解 ORM、Drizzle 和 RLS
数据库·后端·node.js
橙子家1 天前
OSS 文件上传的几个风险点和解决方案
数据库