君にもできる目grepを使わない目grepリローデッドへの挑戦 (010 Editor編)
2012/11/17に開催されたAVTokyo2012の中で「目grepリローデッド」という題目で murachue氏、ucq氏が目grep力を競うイベントが行われた。
その際に愛甲氏によって出題された問題が以下のURLで公開されている。
一般的に目grepはバイナリエディタに搭載されているビットマップビューを駆使し、 鍛えられた眼力、研ぎ澄まされた野生の勘によって発揮される能力であり、 鍛練の度合いによって大きく個人差が生じる能力である。
そこで今回は属人的な要素である目grepを極力使わず、 可能な限りツールを駆使することを目的として、 010 Editorを使用した目grepリローデッドへの挑戦について紹介する。
カナダのSweetScape Software Inc.が販売している有償のバイナリエディタで、 Windows/Mac版の非商用利用ライセンスは49ドルで販売されている。 また購入前に30日間のお試し使用が可能である。
010 Editorには目grepに必須のビットマップビュー機能はないが、 010 Editorの特徴としてファイルフォーマットを解析するテンプレート機能と 作業の自動化を実現するスクリプト機能が強力である点が挙げられる。
インストール直後の状態では数種類のテンプレート、スクリプトしか入っていないが、 以下URLからさまざまなテンプレート・スクリプトがダウンロードできる。
まずはTemplate ArchiveからPDFTemplate.btをダウンロードする。
010 EditorでL1.pdfを開いている状態で、PDFTemplate.btを適用する。 テンプレートの適用方法については下記URLを参照
- Running Templates and Scripts
テンプレートの適用結果の表示ウインドウをみると、ファイルの末尾で PDFファイルのフォーマット解析に失敗している部分があることがわかる。
ひとつ前のセクションを見るとすぐに"PK"の文字列が見つかる。 "PK\x03\x04"で始まる4バイトのデータはzipファイルの先頭に付加されるシグネチャである。
- ZIP (ファイルフォーマット) - Wikipedia
つまり、PDFファイルの末尾にzipファイルが付加されていることがわかる。
PKの文字列がある7790hからファイル末尾までを010 Editorで切り出してL1.zipという名前で保存。 L1.zipを解凍すると次の問題であるL2.gifとL2.binが登場する。
L2.binはfileコマンドなどで調べてもフォーマットが不明である。
まずは、ファイルに含まれているデータの素性を調べるために、010 Editorにあるヒストグラム機能を使用して頻度解析を行う。
頻度解析を行うと0x00~0xffの値はほぼ均一に0.4%程度(100%/256=0.39%)の割合で 出現していることがわかる。 これは圧縮されているデータによく見られる頻度傾向であることから、 何かの圧縮ファイルが何かの暗号化によって隠されていると判断する。
次に、簡単な暗号化としてxorの復元を行ってみる。 Script ArchiveからXORSelectionHex.1scをダウンロードしてXORを実行。
0xffでxorすると先頭にPKの文字列が現れる。ZIPTemplateを適用して確認すると、ファイルの解析に成功し、正しくzipファイルを取り出すことができることがわかる。
この内容をL2.zipというファイル名で保存。解凍するとL3.pngが登場する。
まずはL3.pngを010 Editorで開きPNGTemplateを適用。
するとエラーが表示され、末尾のチャンクの解析に失敗していることがわかる。
解析に失敗している部分(294Eh~4FC0h)を選択し頻度解析を行うと、 0x00~0xffの値がほぼ均一に0.4%程度の割合で出現している。 この部分は圧縮データが付加されている可能性が高い。
また、PNGTemplateの解析結果をもとに他のチャンクの内容を確認すると、 tEXTチャンクの末尾にPKの文字列があり、1740h~1864hに zipファイルの断片らしきものが存在することがわかる。
1740h~1864hのみを取り出してZIPTemplateを適用するとテンプレートの適用に 失敗しエラーが表示される。
エラーの内容をよく見ると、zipファイルの先頭部分の解析には成功しているが、 圧縮されたデータの本体であるfrDataの読み込みに失敗していることがわかる。 ZIPTemplateの内容でエラーが発生している部分のスクリプトを見ると、 frCompressedSizeで指定された長さよりもファイルの内容が短いため、 frDataの読み込みに失敗していることがわかる。
つまり、1740h~1864hのzipファイルらしきデータには続きがあることを示唆している。
そこで、zipファイル1740h~1864hを取り出したデータに、L3.pngの末尾で解析に 失敗している部分(294Eh~4FC0h)を継ぎ足し再びZIPTemplateを適用すると、 解析に成功し、正しいzipファイルを復元できたことがわかる。
この内容をL3.zipというファイル名で保存・解凍する。 解凍時にCRCエラーが発生するが気にせず解凍すると、次の問題であるx.exeが現れる。
x.exeを010 Editorで開きEXETemplateを適用する。 今回はエラーは発生せず正しくEXEファイルの解析が行われる。 Template Resultの項目にヘッダや、セクションなどのの解析結果が表示される。
各セクションを上から順に内容を眺めたり、セクション毎の頻度分析を行うと datasection[4096]の部分に圧縮データらしいデータが含まれていることが確認できる。
x.exeのdatasection(1600h~25FFh)を切り出し、ひとまずdatasection.binとして別ファイルに保存する。
datasection.binの頻度解析結果は0.4%程度の均一な出現頻度であり圧縮データらしいが、 PKの文字列などの手がかりが見つからないため、暗号化されたデータであると仮定し、 L2.binと同様のアプローチを試してみることにする。
L2.binと同様にXORSelectionHex.1scを使用して0xFFでxorすると、 0018h以降の部分に"PK"を含むZIPファイルらしきデータが現れる。
0000h~0017hまでの部分を削除しZIPTemplateを適用すると、password.pngを含むzipファイルとして認識する。
復元したzipファイルのデータをL4.zipというファイル名で保存。解凍すると最後の答えであるpassword.pngが現れる。
010 Editorのテンプレート・スクリプト機能を駆使した 目grepリローデッドへの挑戦方法について紹介した。
今回取り組んだ問題のまとめとして次の3つのポイントが挙げられる。
- データの隠し場所
- 圧縮データの傾向
- 暗号化
今回の出題ではファイルの末尾、コメント領域、.dataセクションにデータが隠されていた。 一般的にも通常のアプリケーションからの利用では害がない部分に隠されることが多い。 問題のファイルに対峙した際に、データの隠し場所についてひらめくかどうかは、 ファイルフォーマットを多く知っていることが鍵になると思われる。
圧縮されたデータの傾向として、頻度解析を行うと0x00~0xffの値はほぼ均一に 0.4%程度(100%/256=0.39%)の割合で出現していることを学んだ。 ただし、0x00~0xffのデータが順番に並ぶような規則性を持つ場合でも ヒストグラム上に同じような傾向が現れるため、頻度解析を行う際には注意が必要である。 ある程度データがランダムに並んでいることを目視で確認したうえで頻度解析を行った方がよい。 (目grepで圧縮データを見た場合、ノイズのような不規則なパターンが見られるケース)
暗号化に関しては、出題側が強力な暗号化を施してしまうと問題そのものが 無理ゲー化してしまう恐れがあるため、CTFなどでの出題の際には 必ず解くためのヒントがどこかにあるケースや、あるいは暗号化に 用いられるアルゴリズムが弱いケースであることが多いと思われる。 まずはXOR 0xffやROT13などの弱いアルゴリズムから試してみるのがよい戦術であると考えられる。
今回使用した010 Editorについては、010 EditorのTemplate Archiveには さまざまなファイルフォーマットに対応したテンプレートが用意されており、 テンプレートを通じてファイルの構造・内容を 眺めるだけでもファイルフォーマットについて学ぶことができる。 010 Editorを使用する際には必ずTemplate Archiveを活用してほしい。
今回の紹介では"PK"の文字列を見つける部分を目視で行っているため、 若干目grepフリーではないツッコミどころも残ってはいるが、 この点に関しては010 Editor用のスクリプトを作成してある程度の自動化で 対応することも可能である。
CTFなどの限られた時間内で問題に取り組む必要があるシーンにおいては、 極力ツールを用いたり自動化できる仕組みを事前に準備し、 問題に対峙した際に人間の能力を最大限に発揮できる環境を 整えておくことが重要である。