结构化文件格式利用检测 (0‑Click Chains)

Tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

本页总结了通过验证文件格式的结构不变量而非依赖字节签名来检测 0‑click 移动利用文件的实用技术。该方法可泛化,适用于不同样本、多态变体以及滥用相同解析器逻辑的未来利用。

关键思想:对只有在到达易受攻击的 decoder/parser 状态时才会出现的结构性不可能性和跨字段不一致进行编码。

参见:

PDF File analysis

为什么关注结构,而不是签名

当已武器化样本不可用且有效载荷字节发生变异时,传统的 IOC/YARA 模式会失效。结构检测检查容器声明的布局与该格式实现从数学或语义上可能实现的内容之间的差异。

典型检查:

  • 验证从规范和安全实现推导出的表大小和边界
  • 标记嵌入 bytecode 中的非法/未记录的 opcodes 或状态转换
  • 交叉核对元数据与实际编码流组件
  • 检测指示解析器混淆或整数溢出设置的矛盾字段

下面是针对多个高影响链条的具体、经过实战验证的模式。


PDF/JBIG2 – FORCEDENTRY (CVE‑2021‑30860)

Target: JBIG2 symbol dictionaries embedded inside PDFs (often used in mobile MMS parsing).

结构性信号:

  • 矛盾的字典状态:在良性内容中不会出现,但触发算术解码溢出时是必须的。
  • 在 refinement coding 期间可疑地使用 global segments,并伴随异常的符号计数。

Pseudo‑logic:

# Detecting impossible dictionary state used by FORCEDENTRY
if input_symbols_count == 0 and (ex_syms > 0 and ex_syms < 4):
mark_malicious("JBIG2 impossible symbol dictionary state")

Practical triage:

  • 识别并从 PDF 中提取 JBIG2 流
  • 使用 pdfid/pdf-parser/peepdf 定位并导出流
  • 将算术编码标志和符号字典参数与 JBIG2 spec 核对

Notes:

  • 可在没有嵌入的 payload 签名的情况下工作
  • 实际中误报率低,因为被标记的状态在数学上不一致

WebP/VP8L – BLASTPASS (CVE‑2023‑4863)

Target: WebP lossless (VP8L) Huffman prefix‑code tables.

Structural signals:

  • 构建出的 Huffman 表的总大小超过了参考/已修补实现所期望的安全上限,暗示存在溢出的前置条件。

Pseudo‑logic:

# Detect malformed Huffman table construction triggering overflow
let total_size = sum(table_sizes)
if total_size > 2954:   # example bound: FIXED_TABLE_SIZE + MAX_TABLE_SIZE
mark_malicious("VP8L oversized Huffman tables")

实用初筛:

  • 检查 WebP 容器块:VP8X + VP8L
  • 解析 VP8L 前缀编码并计算实际分配的表大小

注意:

  • 对 payload 的字节级多态具有鲁棒性
  • 界限基于上游限制/补丁分析得出

TrueType – TRIANGULATION (CVE‑2023‑41990)

目标:TrueType bytecode 位于 fpgm/prep/glyf 程序中。

结构性信号:

  • 在 exploit chain 使用的 Apple 解释器中存在未记录/禁止的 opcodes。

伪逻辑:

# Flag undocumented TrueType bytecode leveraged by TRIANGULATION
switch opcode:
case 0x8F, 0x90:
mark_malicious("Undocumented TrueType bytecode")
default:
continue

实用初步筛查:

  • Dump 字体表(例如,使用 fontTools/ttx)并扫描 fpgm/prep/glyf 程序
  • 无需完全模拟解释器即可仅凭存在性检查获得有用信息

Notes:

  • 如果非标准字体包含未知 opcodes,可能会产生罕见的误报;请使用辅助工具进行验证

DNG/TIFF – CVE‑2025‑43300

Target: DNG/TIFF image metadata VS actual component count in encoded stream (e.g., JPEG‑Lossless SOF3).

Structural signals:

  • 在 EXIF/IFD 字段(SamplesPerPixel, PhotometricInterpretation)与管道用于解析的图像流头部中解析出的组件数量之间存在不一致。

Pseudo‑logic:

# Metadata claims 2 samples per pixel but stream header exposes only 1 component
if samples_per_pixel == 2 and sof3_components == 1:
mark_malicious("DNG/TIFF metadata vs. stream mismatch")

Practical triage:

  • 解析主要 IFD 和 EXIF 标签
  • 定位并解析嵌入的 JPEG‑Lossless 头 (SOF3),并比较组件计数

Notes:

  • 已有实战中被利用的报告;是进行结构一致性检查的优秀候选

DNG/TIFF – Samsung libimagecodec.quram.so (CVE‑2025‑21042) + 附加的 ZIP payload (LANDFALL)

Target: DNG (TIFF‑derived) images carrying an embedded ZIP archive appended at EOF to stage native payloads after parser RCE.

Structural signals:

  • 文件 magic 表明为 TIFF/DNG (II*\x00 or MM\x00*),但文件名伪装成 JPEG(例如 .jpg/.jpeg,WhatsApp 命名)。
  • 在 EOF 附近存在 ZIP Local File Header 或 EOCD magic (PK\x03\x04 or PK\x05\x06),但它未被任何 TIFF IFD 数据区域(strips/tiles/JPEGInterchangeFormat)引用。
  • 在最后被引用的 IFD 数据块之后存在异常大的尾随数据(数百 KB 到 MB),与捆绑的 .so 模块归档一致。

Pseudo‑logic:

# Detect appended ZIP payload hidden after DNG/TIFF data (Samsung chain)
if is_tiff_dng(magic):
ext = file_extension()
if ext in {".jpg", ".jpeg"}: mark_suspicious("Extension/magic mismatch: DNG vs JPEG")

zip_off = rfind_any(["PK\x05\x06", "PK\x03\x04"], search_window_last_n_bytes=8*1024*1024)
if zip_off >= 0:
end_dng = approx_end_of_tiff_data()  # max(end of Strip/Tile/JPEGInterchangeFormat regions)
if zip_off > end_dng + 0x200:
mark_malicious("DNG with appended ZIP payload (LANDFALL‑style)")

Practical triage:

  • Identify format vs name:
  • file sample; exiftool -s -FileType -MIMEType sample
  • Locate ZIP footer/header near EOF and carve:
  • off=$(grep -aboa -E $‘PK\x05\x06|PK\x03\x04’ sample.dng | tail -n1 | cut -d: -f1)
  • dd if=sample.dng of=payload.zip bs=1 skip=“$off”
  • zipdetails -v payload.zip; unzip -l payload.zip
  • Sanity‑check TIFF data regions don’t overlap the carved ZIP region:
  • tiffdump -D sample.dng | egrep ‘StripOffsets|TileOffsets|JPEGInterchangeFormat|StripByteCounts|TileByteCounts|JPEGInterchangeFormatLength’
  • Verify max(offset+length) << zip_off
  • One‑shot carving (coarse): binwalk -eM sample.dng

Notes:

  • Exploited in the wild against Samsung’s libimagecodec.quram.so (CVE‑2025‑21042). The appended ZIP contained native modules (e.g., loader + SELinux policy editor) extracted/executed post‑RCE.

HEIF/AVIF – libheif & libde265 (CVE‑2024‑41311, CVE‑2025‑29482, CVE‑2025‑65586)

Target: HEIF/AVIF containers parsed by libheif (and ImageIO/OpenImageIO builds that bundle it).

Structural signals:

  • Overlay items (iloc/iref) whose source rectangles exceed the base image dimensions or whose offsets are negative/overflowing → triggers ImageOverlay::parse out‑of‑bounds (CVE‑2024‑41311).
  • Grid items referencing non‑existent item IDs (ImageItem_Grid::get_decoder NULL deref, CVE‑2025‑43967) – easy structural check, no decoding required.
  • SAO/loop‑filter parameters or tile counts that force table allocations larger than the max allowed by libde265 (CVE‑2025‑29482): overly large band counts or slice dimensions.
  • Box length/extent sizes that point past EOF (typical in CVE‑2025‑65586 PoCs discovered via fuzzing).

Pseudo‑logic:

# HEIF overlay bounds check
for overlay in heif_overlays:
if overlay.x < 0 or overlay.y < 0: mark_malicious("HEIF overlay negative offset")
if overlay.x + overlay.w > base.w or overlay.y + overlay.h > base.h:
mark_malicious("HEIF overlay exceeds base image (CVE‑2024‑41311 pattern)")

# Grid item reference validation
for grid in heif_grids:
if any(ref_id not in item_ids):
mark_malicious("HEIF grid references missing item (CVE‑2025‑43967 pattern)")

# SAO / slice allocation guard
if sao_band_count > 32 or (tile_cols * tile_rows) > MAX_TILES or sao_eo_class not in {0..3}:
mark_malicious("HEIF SAO/tiling exceeds safe bounds (CVE‑2025‑29482 pattern)")

Practical triage:

  • 快速元数据合理性检查(无需完全解码):
  • heif-info sample.heic
  • oiiotool –info –stats sample.heic
  • 验证 extents 与文件大小:
  • heif-convert –verbose sample.heic /dev/null | grep -i extent
  • 提取可疑 box 以供手动检查:
  • dd if=sample.heic bs=1 skip=$((box_off)) count=$((box_len)) of=box.bin

Notes:

  • 这些检查能在进行大量解码之前发现结构畸形;对只需要允许/拒绝决策的邮件/MMS 网关很有用。
  • libheif 的限制会随版本变化;当上游更改时(1.18.x → 1.21.x 对 overlay 和 grid 验证更严格)需重新基准化常数。

Implementation patterns and performance

A practical scanner should:

  • 自动检测文件类型并只分发给相关分析器 (PDF/JBIG2, WebP/VP8L, TTF, DNG/TIFF, HEIF/AVIF)
  • 流式/部分解析以最小化分配并支持提前终止
  • 并行运行分析(thread‑pool)以进行批量初筛

Example workflow with ElegantBouncer (open‑source Rust implementation of these checks):

# Scan a path recursively with structural detectors
$ elegant-bouncer --scan /path/to/directory

# Optional TUI for parallel scanning and real‑time alerts
$ elegant-bouncer --tui --scan /path/to/samples

DFIR 小贴士与边缘情况

  • Embedded objects: PDFs may embed images (JBIG2) and fonts (TrueType); extract and recursively scan
  • 解压安全:使用在分配前对表/缓冲区进行硬性限制的库
  • 误报:保持规则保守,偏向识别在规范下不可能出现的矛盾
  • 版本漂移:当上游解析器改变限制时,重新基准化边界(例如 VP8L 表大小)

相关工具

  • ElegantBouncer – 用于上述检测的结构扫描器
  • pdfid/pdf-parser/peepdf – PDF 对象提取和静态分析
  • pdfcpu – PDF linter/sanitizer
  • fontTools/ttx – 导出 TrueType 表和字节码
  • exiftool – 读取 TIFF/DNG/EXIF 元数据
  • dwebp/webpmux – 解析 WebP 元数据和数据块
  • heif-info/heif-convert (libheif) – HEIF/AVIF 结构检查
  • oiiotool – 通过 OpenImageIO 验证 HEIF/AVIF

References

Tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks