1. Misc-图片隐写-文件分离

任务目标

给定一张包含隐藏压缩包的图片文件,通过文件分离技术提取出内嵌的ZIP压缩包,解压后获取flag字符串。

环境准备

本案例需要Linux环境(或安装了WSL的Windows),并确保以下工具可用:

  • binwalk:用于扫描并提取图片中嵌入的文件
  • unzip:解压ZIP压缩包
  • file:查看文件真实类型

安装命令(Debian/Ubuntu):sudo apt install binwalk unzip file

关键完整代码

以下脚本实现从图片中自动分离隐藏ZIP并解压获取flag的完整流程:

#!/bin/bash
# 文件分离并提取flag脚本
# 用法: ./solve.sh secret.png

if [ $# -ne 1 ]; then
    echo "用法: $0 <图片文件>"
    exit 1
fi

IMG="$1"
OUTDIR="extracted"

# 1. 检查文件类型
echo "[*] 文件类型:"
file "$IMG"

# 2. 使用binwalk扫描隐藏文件
echo "[*] binwalk扫描结果:"
binwalk "$IMG"

# 3. 提取嵌入的文件
echo "[*] 提取嵌入文件..."
binwalk -e "$IMG" -C "$OUTDIR" 2>/dev/null || {
    # 若binwalk提取失败,尝试手动定位ZIP头
    echo "[!] binwalk提取失败,尝试手动分离..."
    mkdir -p "$OUTDIR"
    # 搜索ZIP文件头 PK\x03\x04
    OFFSET=$(grep -abo $'\x50\x4b\x03\x04' "$IMG" | head -1 | cut -d: -f1)
    if [ -z "$OFFSET" ]; then
        echo "[-] 未找到ZIP文件头"
        exit 1
    fi
    echo "[*] 在偏移量 $OFFSET 处发现ZIP头"
    dd if="$IMG" of="$OUTDIR/hidden.zip" bs=1 skip="$OFFSET" 2>/dev/null
}

# 4. 查找提取出的ZIP文件
ZIPFILE=$(find "$OUTDIR" -name "*.zip" | head -1)
if [ -z "$ZIPFILE" ]; then
    echo "[-] 未找到ZIP文件"
    exit 1
fi
echo "[*] 找到ZIP: $ZIPFILE"

# 5. 解压ZIP
echo "[*] 解压ZIP..."
unzip -o "$ZIPFILE" -d "$OUTDIR"

# 6. 查找flag文件并输出
FLAGFILE=$(find "$OUTDIR" -type f -name "flag*" | head -1)
if [ -z "$FLAGFILE" ]; then
    echo "[-] 未找到flag文件"
    exit 1
fi
echo "[*] flag文件内容:"
cat "$FLAGFILE"

运行与验证

运行方式:

chmod +x solve.sh
./solve.sh secret.png

验证方法:

  1. 脚本首先输出图片的真实文件类型,确认其为PNG/JPEG等图片格式;
  2. binwalk扫描结果应显示在图片末尾存在ZIP压缩包(显示Zip archive data);
  3. 提取成功后,脚本自动解压ZIP并读取flag文件内容;
  4. 若终端输出flag字符串(通常形如flag{...}),则任务完成。

判定标准:脚本最终输出以flag{开头的字符串即为成功。若binwalk无法识别,脚本会尝试手动搜索ZIP文件头(PK\x03\x04)并截取,确保分离成功。

常见问题

  • binwalk提取失败:部分图片可能对ZIP做了额外处理,脚本已内置手动偏移截取逻辑作为备选方案。
  • ZIP有密码:本案例默认ZIP无密码;若遇加密ZIP,需另行使用fcrackzip等工具破解,不在本案例范围内。
  • flag不在独立文件中:若flag直接写在ZIP内的文本文件中,脚本的find命令会定位到该文件并输出内容。