第 6回 クラックルーチンの注入 文●愛甲健二 クラック手法を考える 今回は、第 5 回までの解析結果を元に crackme_ ex.exe のパスワードを突き止めます。 理論は すでにわかっているため、あとは解析手法を選 ぶだけですが、せっかく「進め ! リバースエン ジニアリングの道」と題して連載していますの で、コンパイラやスクリプト言語などは使わずに、 アセンブラだけで実現したいと思います。よっ て、crackme_ex.exe 自体をクラック用に修正 してパスワードを探し当てましょう。 OllyDbg を使ってクラック用 の 処理を追加 します。まずは HACKER JAPAN ONLINE より ファイルをダウンロードして解凍します。アン チウイルスソフトによっては警告が出る場合が ありますが、除外項目にしてください。この中 の crackme_ex.exe を OllyDbg で読み込むと 00406368 以降が空いていますので、ここにク ラックルーチンを追加します。 ただ、クラックルーチンを追加しただけでは 00406368 へ処理が進みませんので、正規ルー チンの適当な場所から 00406368 へ処理をジャ ンプさせる必要があります。よって、00402891 の call 命令のジャンプ先を 004019F0 から 0040 6368 へ変更します。これで、ユーザー 名とパ 変更前 正規のルーチン 00402890 PUSH EAX 00402891 CALL crackme_.004019F0 00402896 ADD ESP,4 変更後 正規のルーチン 00402890 PUSH EAX 00402891 CALL crackme_.00406368 00402896 ADD ESP,4 クラックルーチン 00406368 PUSH EBP … 004063B4 CALL crackme_.004019F0 図 1 パスワードクラックの処理フロー 1 スワードを入力し、OK ボタンをクリックするこ とでクラック処理が走ります(図 1 )。 では、パスワード解析のメイン処理となるク ラックルーチンを書いていきましょう。 OllyDbgでクラックルーチン実行 パスワードクラックにはいくつかの手法があ りますが、今回は dictionaryA.txt( DVD-ROM にも収録しています)を使用した辞書攻撃を行 います。よって、00406368 以降に追加するク ラック処理は以下の流れで実現しましょう。 1. 辞書ファイルを開く 2. 文字列を 1 行取得 3. 文字列をスタックへ 4. 004019F0 を呼び出す 5. 2 へ戻る(繰返し) まずは辞書ファイルを開く処理 ですが、 こ れは CreateFileA を使 います。 ファイルを読 み 込 み 専 用 で 開くの で、 第 1 引 数 に 対 象と なるファイル名、第 2 引数に GENERIC_READ ( 80000000h )、第 5 引数に OPEN_EXISTING ( 3h ) 、第 6 引数に FILE_ATTRIBUTE_NORMAL ( 80h )をセットします。 次に文字列を取得 する部分 で すが、これは ReadFile を使 いま 正規のルーチン しょう。ReadFile で 1 文字ずつ取 004019F0 PUSH EBP 得していき、改行コード「 0D0Ah 」 004019F1 MOV EBP,ESP を見つけたら文字列として認識し、 004019F3 SUB ESP,20 次ステップへ進む、という処理に します。文字列を取得したら、そ れをスタックへ pushして 004019 F0 を call します。004019F0 内で 正規のルーチン 004019F0 PUSH EBP は、渡されたパスワード (第 1 引数) 004019F1 MOV EBP,ESP が 正しいかどうかの 判定 が 行 わ 004019F3 SUB ESP,208 れます。 これらの処理を C 言語風に書く と以下になります。辞書ファイル 名は dictionaryA.txt だとアセン ブラ上 では扱 いにくいため、 便 宜上「 DIC 」としています。 func_00406368(char *s) { char buff[4] = "DIC"; eax = CreateFileA( buff,80000000h, 0,0,3h,80h,0); esi = eax; _READ_STR: ebx = s; _READ_CHAR: ReadFile(esi,ebx,1,buff,0); al = *ebx; ebx++; if(al != 0x0D) goto _READ_CHAR; ebx--; *ebx = '¥0'; 004019F0(s); ReadFile(esi,ebx,1,buff,0); goto _READ_STR; } 00406368 に記 述 するコードは、004019F0 の代わりとして call されるため、実行時にはス タックに「入力されたパスワード」のアドレスが 格納されています。ただ、本来の処理とは異な り、パスワードは辞書ファイルから読み込むた め、このスタックにある 「入力されたパスワード」 は必要ないのですが、せっかくなのでメモリ領 域だけは使わせてもらいましょう。ebx レジス タに s を格納し、この領域へ読み込んだ文字列 を格納します。 ReadFile で 1 文 字 ず つ 読 み 込 み、0Dh が 見 つ かったら 改 行 の 代 わりに 00h を 入 れ て、 004019F0 を呼び出します。Windows の 場合 は 0D0Ah が改行コードであるため、0Dh を読 み込むと次のバイトは 0Ah です。よって、0Ah を 1 回読 み 捨 てて _READ_STR へジャンプし、 最初へ戻ります。 また、ReadFile に buff を 渡して い ます が、 buff( ="DIC" )は CreateFileA 呼び出し時にし か使用しないため、その後は読み込 んだバイ ト数を格納するための領域として使用します。 このコードをアセンブラにすると以下になり ます。OllyDbg で crackme_ex.exe を読み込み、 00406368 以降に以下のコードを書き込んでく ださい。 00406368 00406369 0040636B 00406370 00406372 00406374 00406379 0040637B 0040637D 0040637F 00406384 00406385 0040638A 0040638C 0040638F 00406391 00406393 00406396 00406398 00406399 0040639B 0040639C PUSH EBP MOV EBP,ESP PUSH 434944 // "DIC" MOV EAX,ESP PUSH 0 PUSH 80 PUSH 3 PUSH 0 PUSH 0 PUSH 80000000 PUSH EAX CALL kernel32.CreateFileA MOV EBX,EBP ADD EBX,8 MOV ESI,EAX MOV EDI,EBP SUB EDI,4 PUSH 0 PUSH EDI PUSH 1 PUSH EBX PUSH ESI 図 2 00406368 の 書き換え 図 3 00402891 の 書き換え 2 図 4 0040274Eと 0040276F の書き換 え 0040639D 004063A2 004063A4 004063A5 004063A7 004063A9 004063AA 004063AC 004063AE 004063B0 004063B3 004063B4 004063B9 004063BC 004063BE 004063BF 004063C1 004063C2 004063C3 004063C8 CALL kernel32.ReadFile MOV AL,BYTE PTR DS:[EBX] INC EBX CMP AL,0D JNZ SHORT 00406396 DEC EBX XOR EAX,EAX MOV BYTE PTR DS:[EBX],AL MOV EBX,EBP ADD EBX,8 PUSH EBX CALL 004019F0 ADD ESP,4 PUSH 0 PUSH EDI PUSH 1 PUSH EBX PUSH ESI CALL kernel32.ReadFile JMP SHORT 00406396 以上でクラックルーチンの作成は終了です (図 2 )。 あとは、00402891 の call 命令 のジャンプ先 を 004019F0 から 00406368 へ書き換えましょう (図 3 ) 。これで、パスワードクラックを行う実 行イメージの完成かと思えますが、実はあと 2 つ細かな修正点があります。 1 つは、エラーメッセージに関する処理です。 004019F0 は 引数 に「 入力 された パスワード」 を得る関数 で、 その パスワードが 正解 ならば DES で復号された 200h バイトのデータ列をマ 図 5 解析成功のメッセージボックス 3 シン語として実行し、間違いならばエラーを意 味する文字列をメッセージボックスに表示しま すが、パスワードクラック中に毎回間違いのメッ セージボックスが表示されても困るので、あら かじめこの処理を jmp 命令で飛ばしておきます。 もう 1 つは、0040277A で呼び出されている VirtualFree の引数を MEM_RELEASE(8000h)、 サイズを 0 にしておくことです。 ぶっちゃけた 話 をするとただのプログラム の バグで( 汗 )、 元 々の crackme.exe はメモリを正常に解放し ていませんでした。よって、パスワードクラック によって何度も 004019F0 を呼び出すと、途中 で VirtualAlloc 呼び出し時に「メモリが確保で きない」というエラーが発生します。それを防 ぐために、VirtualFree 呼び出しを問題ないコー ドに変更します。 これら 2 つの修正を終えると、パスワードクラッ ク用実行イメージの完成です(図 4 )。ファイル 名を「 DIC 」に変更した辞書ファイルを同じディ レクトリに置き、OllyDbg 上で、修正後のイメー ジを実行してください。数分ほど待った後、パ スワードが解析されたことを意味するメッセー ジボックスが表示されます(図 5 )。 成功のメッセージボックスが表示されている 状態で 0040276F にブレイクポイントをセットし、 メッセージボックスの OK ボタンをクリックする と、0040276F で処理が止まります。この状態 でスタックを確認するとパスワード 「OtmPpLvQ」 が確認できます(図 6 )。 crackme.exeについて 見事 パスワードがわかり、crackme.exe の すべてが解析されました。メッセージボックス に 書 か れ て いる URL「 http://ruffnex.oc.to/ kenji/crackme/ 」へアクセスするとユーザー 名とパスワードを求められますので、ユーザー 名「 WizardBible 」、パスワード「 OtmPpLvQ 」 と入力すると、crackme.exe のソースコードが ダウンロードできます。興味がある方はぜひソー スコードを眺めてみてください。 図 6 パスワードの 確認 また、パスワードクラック用に改造した crackme_ ex_fin.exe もダウンロードファイルに含まれて います。これは本記事にて OllyDbg 上で行っ た 修 正 を 実 行ファイル へ 適 用したも の で す。 Windows XP SP3 Professional にて動作確認 していますが、CreateFileA と ReadFile のアド レスを決め打 ちしていますので、 動作しない 場合 はこれらのアドレスを修正してください。 また 以前にも 書きましたが、crackme.exe は Windows7 上では正常に動作しません。よって、 特に第 6 回目の本記事は Windows7 以外の環 境でテストしてください。 Windows7 で動作しない理由、成功時にメッ セージボックスが表示されるメカニズムなどが 知りたい 方は、00402769 辺りにブレイクポイ ントを仕掛け、正常なパスワードを入力し、成 功時に実行される処理を眺めてみてください。 リバースエンジニアリング技術からは少し離れ ますが、Windows システムに関するさまざま なことがわかるかと思います。 最後に これで「進め ! リバースエンジニアリングの 道」は終了となります。読者の皆様、本当にお 疲れ様でした。本連載は、なるべく初心者向け であり、かつ、普遍的な技術をテーマに書かせ 新連載予告 ていただきましたが、いかがだったでしょうか。 現在、ソフトウェア開発の現場においてはや はり Java や .NET が主流であり、Web サービス の世界では JavaScript、Ruby、Python といっ たプログラミング言語が好まれています。そう 考えると、21 世紀においてアセンブラを学ぶ 意味は果たしてあるのか ? と思われる読者も 多いと思います。 はっきり言ってしまえば、アセンブラの知識 はコンピューターセキュリティの世界において も、マルウェア解析や脆弱性監査に使われる程 度ですし、それらも近年では自動化され、人の 手で行うソフトウェア解析の活躍の場はさらに 減ってきているかもしれません。ただ、だから といって、その技術が不必要になることは決し てないと思 います。ビジネスに繋がる機会は 少ないかもしれませんが、ソフトウェア技術の 根幹はやはりバイナリデータであり、最終的に CPU が解釈するのはマシン語です。そのベー スとなるスキルを持っていることで 解決 でき る技術的問題も多 々あります。 そして何より、 無意味かどうかよりも、楽しいかどうかでソフ トウェア 技術を学 び 続 けたいというのが 個人 的な本音です。 読者の方々が、本連載を通して少しでもリバー スエンジニアリングに興味を持っていただけた なら幸いです。 実践的なリバースエンジニアリングを学ぼう ! 次回から 「進め ! リバースエンジニアリングの道 Next(仮)」 と題して、改めて連載をスタートします。リバー スエンジニアリングを扱う、という意味ではさほど変わりませんが、これまでの連載が、デバッガの使い方 やアセンブラを中心に扱ったのに対し、次回以降では、CTF( Capture the Flag )やマルウェア解析を題材 にして、より実践的なリバースエンジニアリングに関する内容がメインとなります。 マルウェア解析や脆弱性監査を行う際は、当然デバッガを使ったり、アセンブラを読む必要があるので すが、実際はそれだけではありません。これらはあくまで基礎的な技術であり、業務を遂行するためには、 それらにプラスしてまたいくつかのベーススキルが必要になります。 よって、次回以降は、リバースエンジニアリングという技術をよりセキュリティに応用していく方向で連 載を進めていくことになります。なるべく現場レベル、業務レベルでの解析を紹介、解説していきたいと 思いますので、興味がある方は、ぜひ引き続きよろしくお願い致します。 4
© Copyright 2024 ExpyDoc