悪意あるPDF(malicious PDF)に含まれる Exploit コードを pdf-parser.py で確認する

Adobe Reader脆弱性CVE-2009-4324)が 0day 状態なわけですが、この脆弱性を悪用した PDF が出回っている模様です。ありがたいこと(?)にこれらの PDF をブログ(contagio)で公開している方がいらっしゃいます。ブログ contagio から悪意ある PDF をダウンロードして*1、その PDF に含まれる Exploit コードを確認しようとしました。しかし、先の日記で使用した PDF Toolkit、pdftk ではエラーが発生し、Exploit コードを確認できませんでした。pdftk に代わり、pdf-parser.py を使ってみたところ、うまく確認できました。備忘録もかねて pdf-parser.py を使用した Exploit コード確認の過程をまとめてみます。

確認対象とする PDF は、"Outline of interview.pdf"。

pdftk におけるエラー

確認対象 PDF "Outline of interview.pdf"*2 の中身を pdftk を使って整形しようとすると、以下のようにエラーが生じます。

C:\>pdftk.exe "outline of interview.pdf_" output output.pdf.txt
Error: Unexpected Exception in open_reader()
Error: Failed to open PDF file:
   outline of interview.pdf_
Errors encountered.  No output created.
Done.  Input errors, so no output created.

実際に仮想環境の Adobe Reader 8.1.0 で開いてみると、同じくエラーが生じます。これは Adobe ReaderJavaScript を無効にしても同様であることから、Exploit の実行でエラーが生じているわけではなさそうです。Exploit の実行でエラーが生じたとしたら、DoS 状態となり、Adobe Reader 自体が落ちる可能性が高いだろうし。

では pdf-parser.py で、この PDF ファイルに含まれる Exploit コードを確認していきます。

pdf-parser.py による PDF 解析

"Outline of interview.pdf" に含まれる Exploit コードを以下の流れで確認しました。pdf-parser.py は version 0.3.1 を使用しました。CVE-2009-4324 の Exploit コードは、Adode Reader の JavaScript メソッド media.newPlayer() における脆弱性であるとのことなので、PDF に含まれる JavaScript コードを特定することがゴールとなります。

  1. JavaScript コードの特定
  2. 圧縮されている JavaScript コードの解凍

なお PDF を解析するにあたり、JavaScript コードを解析するぐらいであれば、PDF の基本構造を理解しておければ OK です。僕も PDF の仕様は分からないことばかりなので、Adobe 社が公開しているPDF の仕様書を適宜確認しています。

1. JavaScript コードの特定

まず、"Outline of interview.pdf" に含まれる JavaScript コードを特定します。

C:\>python.exe pdf-parser.py -s JavaScript "outline of interview.pdf_"
obj 106 0
 Type:
 Referencing: 107 0 R
 [(2, '<<'), (2, '/JavaScript'), (1, ' '), (3, '107'), (1, ' '), (3, '0'), (1, '
 '), (3, 'R'), (2, '>>'), (1, '\r')]

 <<
   /JavaScript 107 0 R
 >>


obj 108 0
 Type:
 Referencing: 110 0 R
 [(2, '<<'), (2, '/S'), (2, '/JavaScript'), (2, '/JS'), (1, ' '), (3, '110'), (1
, ' '), (3, '0'), (1, ' '), (3, 'R'), (2, '>>'), (1, '\r')]

 <<
   /S /JavaScript
   /JS 110 0 R
 >>


obj 109 0
 Type:
 Referencing:
 [(2, '<<'), (2, '/S'), (2, '/JavaScript'), (2, '/JS'), (2, '('), (3, '\\n\\r'),
 (2, ')'), (2, '>>'), (1, '\r')]

 <<
   /S /JavaScript
   /JS (\n\r)
 >>

文字列「JavaScript」が含まれるオブジェクトとして、「obj 106 0」, 「obj 108 0」, 「obj 109 0」が列挙されました。PDF の情報はオブジェクトとして定義されています。これは PDF の JavaScript コードも同様です。

しかし、ここで列挙された 3 つのオブジェクトには、想定している Exploit コードとなりそうなものはありません。想定している Exploit コードはこれらのオブジェクトが参照しているオブジェクトに格納されていると考えられます。Adobe 社が公開している PDF の仕様書によれば、各オブジェクトの値として、他のオブジェクトを参照できます(Indirect Objects と呼ぶようです)。上記の「107 0 R」、「110 0 R」が Indirect Objects に該当し、それぞれ「obj 107 0」, 「obj 110 0」を参照しています。/JS で指定している箇所が JavaScript エンジンに渡され実行されるため、Exploit コードは「obj 110 0」で定義されていると推測します。

なお、実際に上記オブジェクトは以下のようになっています。この画像は、"Outline of interview.pdf" をテキストエディタで開き、該当オブジェクトを表示させたものです。「obj 110 0」になにやら出鱈目な文字列が設定されていることが分かります。これが Exploit コードと疑わしいもの箇所です。

2. 圧縮されている JavaScript コードの解凍

1.で特定した「obj 110 0」の JavaScript コードは、FlateDecode フィルターで圧縮されています。圧縮されたままだと、どんな JavaScript コードか分かりません。pdf-parser.py で圧縮されている JavaScript コードを解凍します。

C:\>python.exe pdf-parser.py -o 110 -w -f "outline of interview.pdf_"
obj 110 0
 Type:
 Referencing:
 Contains stream
 <>

 <<
   /Length 4574
   /Filter [
   /FlateDecode ]
 >>

k=0x5c;

//# put xor'ed string to s1
s1='\x2a\x3d\x2e\x7c\x31\x39\x31\x33\x2e\x25\x67\x56\x56\x35\x3a\x74\x3d\x2c\x2c
\x72\x2a\x35\x39\x2b\x39\x2e\x0a\x39\x2e\x2f\x35\x33\x32\x7c\x62\x61\x7c\x64\x75
(割愛)
\x25\x25\x25\x6d\x6d\x6d\x7e\x70\x7c\x32\x39\x2b\x7c\x18\x3d\x28\x39\x74\x75\x75
\x67\x56\x21';

s2='';
for (i=0; i

上記の pdf-parser.py の実行では、解析対象のオブジェクトに「obj 110 0」を指定して(「-o 110」部分)、そのオブジェクトの中身を解凍した結果(「-f」部分)を出力しています(「-w」部分)。なお、pdf-parser.py では、FlateDecode と ASCIIHexDecode の 2 つのフィルターにしか対応していません。他のフィルターで圧縮されている場合、解凍できないため注意が必要です。

Exploit コードと思われる箇所を抽出できたため、pdf-parser.py の役目は終わりとなります。

"Outline of interview.pdf" に含まれていた Exploit コード

「outline of interview.pdf_」に含まれていた JavaScript コードは、排他的論理和(XOR)を使用した簡単な難読化処理が施されています。この難読化処理を解除すると、以下のような JavaScript コードが確認できます。画像の赤枠部分が公開されている実証コード(Proof of Concept:PoC)と一致することから、CVE-2009-4324 の脆弱性を悪用している Exploit コードであると判断できます。


まとめ

pdftk や pdf-parser.py を使わずとも、Wepawetを使用すれば、PDF に含まれる Exploit コードを確認できると思います。しかし、機密情報が含まれる(かもしれない)PDF ファイルをむやみに組織外の Web サービスにアップロードすることができない場合もあります。このような場合も考えると、解析ツールを使用した PDF における Exploit コードの確認方法も必要でしょう。Let's parse PDF!

おまけ:VirusTotal で PDFiD 結果も確認できる

今回使用した pdf-parser.py の開発者 Didier Stevens 氏は、PDFiD というツールも公開しています。PDFiD は、PDF のオブジェクトや /JS, /JavaScript キーワードの統計情報を表示するツールです。このツールは VirusTotal にも導入されているため、VirusTotal にアップロードすれば、合わせて PDFiD の実行結果も確認できます。以下が "Outline of interview.pdf" の VirusTotal 結果における PDFiD 部分になります。


参考情報

*1:ブログ contagio で公開されている PDF はパスワード付き ZIP で圧縮されています。ブログの筆者 Mila さんにメールしてパスワードを教えていただきました!

*2:間違ってダブルクリックして開かないように癖で、拡張子を変更しています(^^;