boredchilada/pdfstudio
GitHub: boredchilada/pdfstudio
一款基于静态分析的 PDF 安全审计工具,提供结构化视图、可视化与自动化报告以识别恶意特征。
Stars: 0 | Forks: 0
# pdfstudio
**PEstudio 风格静态结构 PDF 文件浏览器。**
Stevens-parity CLI,支持目录图遍历、30+ 检测规则,
HTML/JSON/SARIF/STIX 报告、块图文件布局、递归
嵌入 PDF 跟随器、Shell REPL、Curses TUI 以及写模式解除器。
### 先驱工作(亦即已经完成困难部分的人)
在 pdfstudio 出现之前,有两款工具完成了这项工作的大部分。如果你刚接触 PDF 分析,应该先阅读它们——本 README 可以稍后阅读。
- **[Didier Stevens](https://blog.didierstevens.com/)**
实际上已经发明了静态 PDF 恶意软件分析这一学科。他的
[pdf-tools 页面](https://blog.didierstevens.com/programs/pdf-tools/)
提供了 `pdfid.py` 和 `pdf-parser.py`,它们长期以来一直是“如何查看恶意 PDF 内部”的标准答案。相关阅读:
- [Anatomy of Malicious PDF Documents](https://www.scribd.com/document/20604734/Anatomy-of-Malicious-PDF-Documents) (2008)
- [The entire /pdf/ blog category](https://blog.didierstevens.com/category/pdf/)
—— 十五年以上“这些技巧是如何运作”的内容。pdfstudio 的 `--pdfid` 输出、`-o` / `-s` / `-k` / `-r` /
`-e` / `-a` / `--search` / `--no-decode` 开关以及整行“每行一个关键词”的显示风格,都是为了让熟悉肌肉记忆的分析师可以继续使用 pdf-parser。我们并不打算取代他的工具;我们在尽情 remix。
- **[PEstudio](https://www.winitor.com/)** (Marc Ochsenmeier)
是每当你拿到一个 PE 文件就会用到的 Windows 恶意软件分析工具,因为它能在咖啡生效前把关键信息摆在你面前。垂直块图布局、“表面指标而非触发即炸”的姿态,以及“一张屏幕替代十条 CLI 调用”的理念,都源于多年希望“这东西要是为 PDF 存在就好了”的愿望。现在它实现了。
感谢你,Marc。
如果你想争论 pdfstudio 是一封用太多 Python 写成的情书,我不会阻止你。
仅使用标准库的 Python 3.10+。可选依赖:`yara-python` 用于 YARA 扫描;`windows-curses` 用于 Windows 下的 TUI。
## 快速一览 —— 如果只读一项,就读这一项
将 pdfstudio 指向一个 PDF(或文件夹)并请求一份报告包:
```
pdfstudio suspicious.pdf --report out/
```
在任意你喜欢的 Markdown 查看器中打开 [`out//deep_dump.md`](#what-the-deep-dump-contains)。这是一份完整、独立的 **一站式分析师视图**,包含工具发现的所有内容:
1. **结构报告** —— 首部、修订版本、对象表、触发器、带严重性图标的标志
2. **文件布局块图** —— PEstudio 风格的垂直堆栈:`Header / Body(v0) / xref / Trailer / %%EOF`,附带字节偏移
3. **pdfid 关键词表** —— pdfid 兼容的关键词计数、熵、信息字典、结构标记
4. **目录遍历** —— `/Root → /Pages → /Page → …` 的缩进树形解析结果,带动作触发点标注
5. **统计信息** —— 按类型、`/Type`、流过滤器划分的对象计数
6. **Mermaid 图** —— 粘贴到任意支持 Mermaid 的查看器即可可视化目录图
7. **IOC** —— URL、域名、每个流的 SHA-256
8. **标记对象正文** —— 被 HIGH/MED 规则标记的每个对象的原始 PDF 语法,按对象分组
9. **畸形区域** —— 解析器无法识别的字节
10. **十六进制窗口** —— 文件首部字节 + 最后一个 `startxref`(xref/trailer/EOF)周围的尾部内容
扫描包还包含 `report.html`、`report.json`、
`report.sarif`(SARIF 2.1)、`report.stix.json`(STIX 2.1)、
`flags.csv`、`iocs.csv`、`summary.txt`。对 BigFix / SCCM / Tanium /
CI 指向该包目录即可。
### 深包内容示例(样本)
```
## 1b. 文件布局(块图)
┌─ Header ──────────────────────────────────────────────────────── 0x00000000
│ %PDF-1.3 (22 B) │
╞═ Body — Revision 0 ═════════════════════════════════════════════ 0x00000016
│ 14,400 bytes NEW=17 REWRITE=0 │
│ obj 2 v0 Page MediaBox=[0 0 612 792] │
│ obj 13 v0 Catalog │
│ obj 14 v0 Stream Filters=/FlateDecode │
├─ xref (v0) 370 B ────────────────────────────────────────────── 0x00003856
├─ Trailer (v0) 142 B ─────────────────────────────────────────── 0x000039C8
│ /Root 13 0 R /Size 18 │
├─ %%EOF (v0) ──────────────────────────────────────────────────── 0x00003A56
╞═ Body — Revision 1 (incremental update) ══════════════════════ 0x00003A5B
│ 45,231 bytes NEW=6 REWRITE=2 │
│ ★ obj 20 v1 Filespec F=form.pdf │
│ ★ obj 21 v1 Stream Decoded=Windows PE │
│ ★ obj 22 v1 Action:JavaScript │
│ ★ obj 23 v1 Action:Launch F=cmd.exe │
├─ xref (v1) 183 B ────────────────────────────────────────────── 0x0000EB0A
├─ Trailer (v1) 75 B ──────────────────────────────────────────── 0x0000EBC1
│ /Root 13 0 R /Size 24 /Prev 14422 │
├─ %%EOF (v1) ──────────────────────────────────────────────────── 0x0000EC0C
└───────────────────────────────────────────────────────────────── 0x0000EC11
## 7. 标记对象体
### obj 23 v1 [Action:Launch] — 高优先级 — 标志:`LAUNCH_CMD`, `LAUNCH_NEWLINE_PAD`
```
<100 MB)**:解析器会将整个文件载入内存。
- **对抗性输入**:解析器基于正则表达式驱动,并已针对常见畸形进行了加固,但并非模糊测试免疫。若发现崩溃,请提供触发样本的哈希并打开问题。
## 速查表
```
# 默认结构视图(触发器 + 标志 + 版本修订 + 对象表)
python pdfstudio.py file.pdf
# 相同的分析,以独立 HTML 文件呈现
python pdfstudio.py file.pdf --html report.html
# 机器可读的 JSON,用于下游工具
python pdfstudio.py file.pdf --json
# pdfid 兼容关键字 + 熵摘要
python pdfstudio.py file.pdf --pdfid
python pdfstudio.py file.pdf --pdfid --nozero # suppress zero counts (pdfid -n)
python pdfstudio.py file.pdf --pdfid --extra-info # /CreationDate, /Producer etc. (pdfid -e)
python pdfstudio.py file.pdf --pdfid --all-keywords # expanded keyword table (pdfid -a)
# 目录扫描(pdfid -s / --recursedir)
python pdfstudio.py samples/ # one-line summary per PDF in dir
python pdfstudio.py samples/ --recursedir # recurse into subdirectories
python pdfstudio.py samples/ --recursedir --pdfid --nozero # per-file pdfid summary
# 外科对象操作
python pdfstudio.py file.pdf -o 23 # show object 23
python pdfstudio.py file.pdf -o 23 --revision 0 # show v0 copy
python pdfstudio.py file.pdf -o 21 -d raw.bin # dump raw stream
python pdfstudio.py file.pdf -o 21 -D decoded.bin # dump filter-decoded stream
# 搜索
python pdfstudio.py file.pdf -s "/Launch" # object-body search
python pdfstudio.py file.pdf -s "MZ" --in-streams # search decoded streams too
# 引用查找
python pdfstudio.py file.pdf -r 21 # who references object 21?
# 图形导出
python pdfstudio.py file.pdf --mermaid # Mermaid flowchart
python pdfstudio.py file.pdf --mermaid --full-graph # include all objects
python pdfstudio.py file.pdf --dot graph.dot # Graphviz DOT file
# 然后:dot -Tsvg graph.dot -o graph.svg
# 可视化:注释矩形叠加为 SVG
python pdfstudio.py file.pdf --rects overlay.svg # page + clickable rects
# 十六进制视图
python pdfstudio.py file.pdf -o 23 --hex # object body + stream in hex
python pdfstudio.py file.pdf -o 23 --hex --hex-max 0 # full dump (no truncation)
# 双 PDF 结构差异
python pdfstudio.py left.pdf --diff right.pdf
# 完整目录图树遍历(缩进、抑制循环、严重性星级)
python pdfstudio.py file.pdf --walk
# 畸形 / 未声明的字节(任何不在间接对象或结构令牌中的内容)
python pdfstudio.py file.pdf --show-malformed
python pdfstudio.py file.pdf -x unclaimed.bin
# 交互式 REPL — 解析一次,然后导航
python pdfstudio.py file.pdf --shell
# (在 shell 中:)
# info
# triggers
# obj 21 --hex
# stream 21 dec
# key /URI
# refs 21
# walk
# hunt url (如果提供了 --hunt)
# quit
# 威胁狩猎增强
python pdfstudio.py file.pdf --hunt-offline # extract IOCs, no network
python pdfstudio.py file.pdf --hunt # + DNS resolve + HTTP HEAD + URLhaus anonymous
python pdfstudio.py file.pdf --hunt --hunt-vt # also VirusTotal (needs VT_API_KEY env var)
python pdfstudio.py file.pdf --hunt --hunt-mb # also MalwareBazaar (needs MB_API_KEY env var)
# Curses TUI(箭头键导航,实时对象浏览器)
python pdfstudio.py file.pdf --tui
# 在 Windows 上安装一次 curses 后端: pip install windows-curses
# 递归 — 跟踪嵌入 PDF 中的 /EmbeddedFile 流
python pdfstudio.py file.pdf -R
python pdfstudio.py file.pdf -R --recursive-depth 10
# 写入一个解除武装的副本(字节替换 /OpenAction、/AA、/Launch、/JS、/JavaScript)
python pdfstudio.py file.pdf --disarm safe_copy.pdf
# 自动化 — 单行摘要、退出策略、报告捆绑包、批处理
python pdfstudio.py file.pdf --summary-line # grep-friendly one-liner
python pdfstudio.py file.pdf --strict-exit # exit 0/5/10/20 by severity
python pdfstudio.py file.pdf --exit-on-severity HIGH # exit 20 iff any HIGH flag
python pdfstudio.py file.pdf --report out/s1/ # 7-file bundle
python pdfstudio.py file.pdf --sarif out.sarif # SARIF 2.1
python pdfstudio.py file.pdf --stix out.stix.json # STIX 2.1
python pdfstudio.py file.pdf --csv out.flags.csv # flat CSV
# 批处理扫描多个 PDF(BigFix/SCCM/Tanium 友好)
ls samples/*.pdf | python pdfstudio.py ignored --batch - --report batch_out/ --jobs 8 --strict-exit
python pdfstudio.py ignored --batch files.txt --report batch_out/ --jobs 8 --strict-exit
# 指向一个文件夹 — pdfstudio 自动发现 .pdf 文件
python pdfstudio.py samples/ # one-line triage
python pdfstudio.py samples/ --recursedir # recurse subdirectories
python pdfstudio.py samples/ --strict-exit # exit reflects worst severity
python pdfstudio.py samples/ --report out/ --jobs 8 --strict-exit # full parallel batch + bundles
python pdfstudio.py samples/ --recursedir --report out/ --jobs 8 # recursive + parallel + bundles
```
## 自动化/编排指南
`pdfstudio` 专为编排工具(BigFix、SCCM、Tanium、Intune、GitHub Actions、GitLab CI 等)设计,并直接产出这些工具可摄入的输出。
### 退出码(`--strict-exit`)
| 码 | 含义 |
|----|------|
| 0 | 解析成功,无 MED/HIGH 标志 |
| 5 | 仅 LOW 标志 |
| 10 | 至少一个 MED 标志 |
| 20 | 至少一个 HIGH 标志(恶意) |
| 2 | 参数 / 用法错误 |
| 3 | 解析失败(不是 PDF 或加密) |
`--exit-on-severity HIGH|MED|LOW` 提供与策略对齐的二元判定:任何 ≥ 级别的标志 → 退出 20,否则退出 0。
### 单行摘要(`--summary-line`)
以 `KEY=VALUE` 形式输出到标准输出,字段顺序稳定:
```
PDFSTUDIO v=0.1.0 file=X.pdf size=60435 md5=... sha256=... \
header=%PDF-1.3 revs=2 objs=25 streams=4 urls=0 \
severity=HIGH flags=EMBEDDED_PE,LAUNCH_CMD,LAUNCH_NEWLINE_PAD,...
```
便于 grep/Splunk 友好,且为单行输出,便于简单捕获后使用正则。
### 报告包(`--report DIR`)
为每个输入 PDF 写入七个文件,供任意编排器上传:
| 文件 | 用途 |
|------|------|
| `summary.txt` | 单行摘要 + 3 行分类摘要 |
| `report.json` | 完整的机器可读模型 |
| `report.html` | 自包含的 HTML 查看器(带样式) |
| `report.sarif` | SARIF 2.1 —— 可直接导入 GitHub/Azure 等 |
| `report.stix.json` | STIX 2.1 包 —— 可直接导入 MISP/TIPs |
| `flags.csv` | 标志的平面 CSV |
| `iocs.csv` | URL / 域名 / 流哈希的平面 CSV |
### 批量模式(`--batch FILE --report DIR --jobs N`)
处理 FILE 中的每一行路径(支持 stdin 使用 `-`),为每个输入生成一个以 SHA-256 为键的包,并写入 `index.csv` 与 `index.json` 进行汇总。使用 `concurrent.futures.ProcessPoolExecutor` 实现并行。示例 BigFix 风格动作:
```
python pdfstudio.py _ --batch /tmp/todo.txt --report /tmp/out --jobs 8 --strict-exit
# /tmp/out/index.csv, /tmp/out//report.{json,html,sarif,...}
```
### BigFix / SCCM / Ansible 片段
```
# 单主机操作
python pdfstudio.py "$SUSPICIOUS" --report "$UPLOAD_DIR" --strict-exit
rc=$?
case $rc in
0) echo "clean" ;;
5) echo "low" ;;
10) echo "suspicious" ;;
20) echo "malicious — escalate" ;;
*) echo "error rc=$rc" ;;
esac
```
### 网络安全姿态
- 默认关闭网络。仅 `--hunt` 标志会打开套接字;其他路径不会发起连接。在空气隔绝端点运行安全。
- 默认仅使用标准库;可选扩展为 `yara-python`(用于 `-`)和 `windows-curses`(用于 `--tui` 在 Windows 上)。
- 默认只读。唯一写模式为 `--disarm`(显式输出路径;永不修改输入)。所有其他导出器仅写入用户命名的路径。
- 输出确定性 —— JSON 负载中不包含运行时间戳(STIX/SARIF 时间戳为规范强制)。
## 解除武装(Disarm)
`--disarm OUT.pdf` 会写入一份中性化副本,将五个危险关键词替换为长度相同的“看似”字符,使 PDF 阅读器不会将其解析为动作:
```
/OpenAction → /OpenActi0n
/AA → /A0
/Launch → /Launc0
/JS → /J0
/JavaScript → /JavaScrip0
```
因为每次替换都保持字节长度不变,xref 表保持有效,文件仍可被解析为 PDF —— 只是不再自动执行任何内容。与 pdfid 的 `--disarm` 使用相同技术。该过程仅在对象字典区域内扫描,永不进入流正文,因此压缩负载保持不变。
## 递归遍历
`-R` / `--recursive` 会展开所有以 `%PDF-` 开头的解码流,将其作为子 PDF 解析。子 PDF 会拥有独立的分类/遍历/标记流程,并挂载在父级的 `parent.children` 下。运行至有界深度(`--recursive-depth N`,默认 5),以防止循环和深层嵌套内容耗尽资源。对 PDF 载荷为另一 PDF 的常见多态/嵌入附件模式非常有用。
## TUI
`--tui` 启动全屏 Curses 界面,包含左侧对象列表与右侧详情,以及底部的状态栏。
```
Up/Down or j/k move selection
Enter or → follow first indirect reference
Backspace or ← step back
/ search
n next search hit
t / f / w / o triggers / flags / walk / objects view
g go to object by number
x dump decoded stream of selected object
? / q help / quit
```
解析一次后,所有导航即时生效。在 Windows 上:`pip install windows-curses` 一次。在 Linux/macOS 上开箱即用。
## 威胁狩猎模式(`--hunt`)
默认关闭的网络增强功能。提取每个 URL(来自 `/URI` 动作、正文中的自由格式 URL 模式以及解码流)。然后推导这些 URL 对应的域名,并计算每个解码流的 SHA-256。接着运行任意组合:
- **DNS 解析** —— 每个主机 → A 记录
- **HTTP HEAD** —— 状态、内容类型、内容长度、位置、重定向后的最终 URL
- **URLhaus**(abuse.ch,匿名 POST) —— 每个 URL:查询状态、威胁、标签
- **VirusTotal**(通过 `VT_API_KEY` 可选启用) —— 每个 URL:最新分析统计
- **MalwareBazaar**(通过 `MB_API_KEY` 可选启用) —— 每个流 SHA-256:签名
仅当提供 `--hunt` 时运行。使用 `--hunt-offline` 可提取 IOC 而不进行任何网络调用。不下载任何载荷正文。
## 交互式 Shell
`--shell` 会在解析后进入 `cmd.Cmd` REPL。所有命令均基于已解析的内存模型。可用命令:
```
info objects obj N [--hex] body N stream N [raw|dec]
triggers walk flags search KW [streams] key /KEY refs N
type TYPE revisions stats dump N path ddump N path
hunt [url|hash|all] quit
```
## 流魔数嗅探器
每个解码流会自动嗅探常见文件签名(MZ、ELF、Mach-O、PE、PK/ZIP、7z、gzip、OLE 复合体、PDF、JPEG、PNG、GIF、
BMP、RTF、Flash SWF、ISO 9660 在偏移 0x8001、XML/HTML)。命中结果会显示为 `Decoded=` 标签,并在适用时触发
`EMBEDDED_PE`、`EMBEDDED_ZIP` 或 `EMBEDDED_ELF` 标志。
扩展签名表请修改 `pdfstudio/magic.py`。
## 包布局
```
tools/pdfstudio/
├── pdfstudio.py # CLI entry point
├── pdfstudio/ # library
│ ├── __init__.py
│ ├── model.py # dataclasses: PDFFile, Revision, PDFObject, Stream, Trailer
│ ├── parser.py # find %PDF, xref, trailers, objects, streams
│ │ # + FlateDecode, ASCIIHex, ASCII85, LZW, RunLength decoders
│ ├── classify.py # assign a high-level 'kind' to each object
│ ├── walker.py # Catalog → OpenAction / AA / Names / Annots traversal
│ ├── flags.py # suspicious-indicator rule engine
│ ├── extract.py # -o object view, -d / -D stream dump
│ ├── search.py # -s keyword search, -r referrer lookup
│ ├── pdfid_view.py # pdfid-style keyword + entropy summary
│ ├── graphviz_out.py # Mermaid + Graphviz DOT graph exporters
│ ├── rects_svg.py # page + annotation rectangle SVG overlay
│ ├── hexview.py # hex dumper
│ ├── diff.py # two-PDF structural diff
│ ├── magic.py # file-signature sniffer for decoded streams
│ ├── objstm.py # /ObjStm content expansion
│ ├── xrefstream.py # /XRef cross-reference stream parser
│ ├── parity.py # -k, -t, -e, -a, -c, multi-object spec
│ ├── walk_view.py # --walk full tree rendering
│ ├── malformed.py # -x / --show-malformed extraction
│ ├── shell.py # --shell interactive REPL
│ ├── tui.py # --tui curses interface
│ ├── hunt.py # --hunt forensic enrichment
│ ├── disarm.py # --disarm byte-substitution writer
│ ├── recursive.py # -R embedded PDF walker
│ ├── automation.py # exit codes, summary line, report bundle, SARIF/STIX/CSV, batch
│ ├── yara_scan.py # -y YARA scanning
│ ├── pdfid_view.py # --pdfid keyword summary
│ └── render/
│ ├── __init__.py
│ ├── text.py # default CLI text renderer
│ └── html.py # standalone HTML renderer
└── README.md
```
每个模块均小巧(~100–250 行)。新增视图只需创建 `pdfstudio/render/.py` 并在 `pdfstudio.py` 中注册。
## pdfid.py 选项 → pdfstudio 选项
与 Didier Stevens 的 `pdfid.py --help` 的权威映射:
| pdfid 标志 | pdfstudio 等效 |
|------------|----------------|
| (无标志) | `--pdfid` |
| `-s` 扫描目录 | 将目录作为位置参数传递 |
| `-a` 全部名称 | `--pdfid --all-keywords` |
| `-e` 额外(日期等) | `--pdfid --extra-info` |
| `-f` 强制(无 %PDF) | 解析器不要求头部即可继续 |
| `-n` nozero | `--nozero` |
| `-o FILE` 日志文件 | 重定向标准输出(`> file.txt`) |
| `--recursedir` | `--recursedir` |
| `-d` 解除武装 | *不支持 —— 只读工具* |
| `-p` 插件 | *不支持 —— 请使用 `--flags` 引擎配合 `--yara`* |
| `-c` CSV | *不支持 —— 请使用 `--json`* |
| `-l` 字面名称 | *不适用 —— pdfstudio 不支持通配符展开* |
## pdf-parser.py 选项 → pdfstudio 选项
与 Didier Stevens 的 `pdf-parser.py --help` 的权威映射:
| pdf-parser 标志 | pdfstudio 等效 |
|-----------------|----------------|
| `-s SEARCH` | `-s SEARCH`(支持 `--regex`、`--case`) |
| `--searchstream=X` | `-s X --in-streams` |
| `--unfiltered` | `--unfiltered`(与 `-s` 联用) |
| `--casesensitive` | `--case` |
| `--regex` | `--regex` |
| `-f`(应用过滤器) | `-D OUT`(过滤转储)/ 默认解码 |
| `-w`(原始数据) | `-d OUT`(原始转储) |
| `-o OBJECT` | `-o SPEC`(接受 `12`、`12,15`、`20-25`) |
| `-r REFERENCE` | `-r N` |
| `-e cxtsi` | `-e cxtsi` |
| `-a`(统计) | `-a` |
| `-t TYPE` | `-t TYPE` |
| `-O`(解析 /ObjStm) | `-O` |
| `-H`(对象哈希) | 自动包含在 `-o` 输出中 + 默认视图(文件级) |
| `-c`(内容) | `-c` |
| `-v`(详细/畸形) | `-v` |
| `-k KEY` | `-k KEY` |
| `-y YARA` | `-y RULES` |
| `--yarastrings` | `--yarastrings` |
| `-d OUT`(转储流) | `-d OUT`(原始)/ `-D OUT`(解码) |
| `-x FILE`(提取畸形) | `-x OUT`(字节)/ `--show-malformed`(表格) |
| `-g` 生成 Python | (未计划 —— 超出范围) |
| `--overridingfilters` | (尚未实现 —— 计划中) |
## pdfstudio 相较于 pdf-parser 的增强
- `--html` —— 带样式的独立 HTML 报告
- `--json` —— 机器可读的转储
- `--pdfid` —— pdfid 兼容的关键词摘要
- `--mermaid` / `--dot` —— 目录引用图
- `--rects out.svg` —— 每页注释矩形叠加
- `--diff other.pdf` —— 两份 PDF 的结构差异
- `--hex` —— 每个对象的十六进制转储(正文 + 原始流 + 解码流)
- **命名可疑标志引擎**(`EMBEDDED_PE`、`LAUNCH_CMD`、`LAUNCH_NEWLINE_PAD`、`OPENACTION_JS`、`FULL_PAGE_LINK`、`MULTI_REV_WEAPONIZATION`、`STREAM_HIGH_ENTROPY`、`OBJSTM_PRESENT`、`XREF_STREAM`、`ENCRYPTED`、`EMBEDDED_ZIP`、`EMBEDDED_ELF`)
- **目录遍历器**——解析 `/OpenAction` / `/AA` / `/Names /EmbeddedFiles` / `/Annots → /A` 链
- **按修订版本对比**——通过 `/Prev` 链重建新版本与改写对象
- **自动文件签名嗅探器**(22+ 签名),显示为 `Decoded=` 标签
## 与 pdfid / pdf-parser 的能力对比
| 功能 | pdfid | pdf-parser | pdfstudio |
|------|-------|------------|-----------|
| 关键词计数 | ✔ | — | ✔(`--pdfid) |
| 流熵(进出) | ✔ | — | ✔(`--pdfid`) |
| 对象树解析 | — | ✔ | ✔ |
| 对象正文显示(`-o N`) | — | ✔ | ✔ |
| 流转储(`-d` / `-D`) | — | ✔ | ✔ |
| FlateDecode / ASCIIHex / ASCII85 解码器 | — | ✔ | ✔ |
| LZW / RunLength 解码器 | — | ✔ | ✔ |
| 关键词搜索(`-s`) | — | ✔ | ✔ |
| 引用查找(`-r`) | — | ✔ | ✔ |
| 目录图遍历(触发解析) | — | — | ✔ |
| 按修订版本的新旧对比重构 | — | 部分 | ✔ |
| 命名可疑标志引擎 | — | — | ✔ |
| HTML 报告 | — | — | ✔ |
| JSON 输出 | — | — | ✔ |
| Mermaid / Graphviz 导出 | — | — | ✔ |
| 注释矩形 SVG 叠加(`--rects`) | — | — | ✔(`--rects`) |
| 十六进制视图(`--hex`) | — | (通过 `-a`) | ✔ |
| 两份 PDF 结构差异(`--diff`) | — | — | ✔(`--diff`) |
| 魔法嗅探器(PE/ZIP/ISO/…) | — | — | ✔(自动) |
| `/ObjStm` 检测(仅标志) | ✔ | ✔ | ✔(检测;扩展计划中) |
| 对象流内容扩展 | — | ✔ | —(计划中) |
| 加密 PDF 支持 | — | ✔ | —(计划中) |
| YARA 规则集成 | — | ✔ | —(计划中) |
## 范围与非目标
- **仅静态分析**。不执行 JavaScript,不模拟 shellcode。
- **不进行字节级篡改**。只读。如需 PDF 修复或伪造,请使用其他工具(例如 `qpdf`)。
- **尽力而为的解析器**。基于正则表达式;可处理 Adobe Reader 仍会接受的合法与畸形 PDF。无法可靠解析加密、交叉引用流式或重度线性化 PDF。
## 扩展它
- **新增标志规则**:在 `pdfstudio/flags.py` 中添加函数,并将其追加到 `ALL_RULES`。接收解析后的 `PDFFile`,返回 `(严重性, 代码, 消息)` 元组列表。
- **新增视图**:创建 `pdfstudio/render/.py`,暴露 `render(pdf, hits) -> str` 并在 `pdfstudio.py` 中注册并连接。
- **新增分类器**:在 `classify.py` 顶部的字典中扩展。
## 许可证
单文件内部工具,当前无许可证文件。暂按公共领域处理,待明确授权。
标签:CLI, curses TUI, DAST, Didier Stevens, HTML报告, JSON报告, PDF分析, PDF取证, PDF安全, PDF工具, PEStudio, Python, Python 3.10, SARIF报告, Shell REPL, STIX报告, WiFi技术, 云安全监控, 写模式解除, 块图布局, 嵌入式PDF, 开源安全工具, 恶意PDF, 恶意软件分析, 文件取证, 无后门, 检测规则, 目录图遍历, 网络资产发现, 逆向工程平台, 静态分析, 静态结构浏览器