Challenge
Forensic 3 — PapaSmurphey’s Pizza
The local police just arrested a suspect believed to be the notorious
PapaSmurphey, an online pizza trader. A flash drive was recovered from the scene and was copied; poorly. As best as you can, examine the contents for any incriminating evidence on the suspect. This challenge has several steps. The completion password will look like this:HTS{the_answer}
Solution
Step 1: 素材清单
附件 forensic_3.rar 解开后是 flashdrive/ 下 9 个文件。关键文件是体积异常的
shh.jpg:它只有 500×500 灰度图像,却占用约 10 MB;siggies.txt 则提供了文件签名
(magic bytes)参考。
49ZfDSNg.jpg 90658 680x992 JPEG(其实是一张三格漫画)bitcoin.pdf 184292 PDF 1.4,9 页DYNAMITE - Winamp 5.0RC8crk.mp3 2230928 MPEG layer III 48kHzHack This Site!.url 55 Windows Internet Shortcut(内容就是 hackthissite.org)legrandelibrary.xlsx 12871 xlsx,作者 Samshh.jpg 10376722 500x500 **灰度** JPEG,尺寸与体积严重不符siggies.txt 54743 十六进制文件签名对照表UXo9C84.jpg 57822 475x960 progressive JPEGsiggies.txt 是一张文件签名/魔数对照表(TGA、MOV、MOF……),
题面用它给出提示:类型按魔数判断,不以扩展名为准。
一张 500×500 的灰度 JPEG 不可能有 10 MB。binwalk 直接给出结构:
binwalk extracted/flashdrive/shh.jpg0 0x0 JPEG image, total size: 32346 bytes10371574 0x9E41F6 JPEG image, total size: 5148 bytes也就是说:第一张 JPEG 在偏移 32346 处结束,文件从这个偏移开始的内容不是普通 JPEG
尾部,而是连续嵌入的数据。继续扫描 JPEG 起始标记 FF D8 FF,在偏移 10371574
处找到第二张 JPEG(205×80);因此中间区间 [32346, 10371574) 正好是隐藏归档。
这条边界很重要:如果只用 binwalk 或普通文件识别,可能只能看到两张 JPEG,或者把
RAR 当成未知数据;应按文件签名和 JPEG 的 FF D9/FF D8 FF 边界手工确认。
Step 2: Carve 隐藏文件并修复 RAR 签名
shh.jpg 的结构可以概括为:
[JPEG #1][Zar!\x1a\x07\x00 ... encrypted RAR ...][JPEG #2] ^ RAR 的第一个签名字节被改成了 Z下面的 carving 脚本从实际 JPEG 标记计算第一张图片的结束位置和第二张图片的起始位置:
#!/usr/bin/env python3"""Carve and repair the embedded RAR stream from shh.jpg."""
from pathlib import Path
RAR4_SIGNATURE = b"Rar!\x1a\x07\x00"BROKEN_SIGNATURE = b"Zar!\x1a\x07\x00"
def carve(source, rar_output, tail_jpeg_output): data = Path(source).read_bytes() first_eoi = data.find(b"\xff\xd9") rar_start = first_eoi + 2 tail_start = data.find(b"\xff\xd8\xff", rar_start) if first_eoi < 0 or tail_start < 0 or not rar_start < tail_start: raise SystemExit("could not locate JPEG/RAR/JPEG boundaries")
carved = bytearray(data[rar_start:tail_start]) if bytes(carved[: len(BROKEN_SIGNATURE)]) != BROKEN_SIGNATURE: raise SystemExit( "unexpected embedded signature: %r" % bytes(carved[:8]) ) carved[: len(RAR4_SIGNATURE)] = RAR4_SIGNATURE Path(rar_output).write_bytes(carved) Path(tail_jpeg_output).write_bytes(data[tail_start:]) print("first JPEG end:", rar_start) print("RAR start:", rar_start) print("second JPEG start:", tail_start) print("RAR bytes:", len(carved)) print("tail JPEG bytes:", len(data) - tail_start)
def main(): carve("shh.jpg", "fixed.rar", "tail_embedded.jpg") print("RAR signature:", Path("fixed.rar").read_bytes()[:8])
if __name__ == "__main__": main()运行脚本的实际输出:
first JPEG end: 32346RAR start: 32346second JPEG start: 10371574RAR bytes: 10339228tail JPEG bytes: 5148RAR signature: b'Rar!\\x1a\\x07\\x00'此时 tail_embedded.jpg 是一个独立的 205×80 JPEG。打开它(也可以对它做 OCR 或直接放大)
能读出一个容易混淆 O/0 的 logo 文字,视觉上近似:
GLOzMeStep 3: 使用图片中的密码解压
再让 7-Zip 认修复后的归档,并用从 tail_embedded.jpg 读出的候选变体测试。
通过校验的密码是 GL0zMe(第三个字符是数字 0):
7z t -pGL0zMe fixed.rar7z x -y -pGL0zMe -so fixed.rar 'DNM Login.txt'Everything is OkPapaSmurphey -- HTS{You_caught_me!}Vulnerabilities
从闪存盘取证的场景里,拷贝的完整性本身就是证据的一部分: 本例的归档被改掉了一个签名字节、还被截断,靠魔数对照 + 字节级修复仍能还原出归档结构, 说明把文件混在图片里 + 改扩展名 + 改首字节这类手法只能阻碍直接双击查看。 需要保密的介质应整盘加密(如 BitLocker/LUKS),文件层面的伪装不构成保护。