解析

Malwarebyte Crackme Writeup

はじめに

@hasherezade氏が作成したCrackmeのプログラムを自分の勉強のために解析した結果、とてもよい学びになったのと、そして日本語のWriteupはなかったので、作成しました。

Writeup自体は公式にあるし、ほかにも検索するとあるので多言語が読める方はそちらでいいと思います。

使用したツール

解析には下記のツールを使いました。

概要把握

実行すると、下記のように表示される。目的はflag{...}の形式のものを抜き出すこと

I am so sorry, you failedという文字が見つかるので、その文字をベースに解析を始める。

静的解析

I am so sorry, you failedという文字を探すとFUN_004014f0();の結果で分岐していることがわかる。flagはFUN_00401690を探していけばよいかとあたりをつけれる。

FUN_00401690()の解析(途中まで)

この関数を最初に見ていくと、I need internet\nという文字があり、その前にFUN_00403560()を読んでいます。FUN-00403560()関数ではInternetGetConnectedStateを呼び出していることから関数はインターネット接続をチェックしてると思われるのでcheck_internet()と名前を変えておきます。

次を見ていくとcallocでメモリ確保した後そのメモリを引数にとりFUN_004033d0()を呼び出しているのが見つかります。この関数ではInternetOpenUrlA()InternetReadFile()を呼び出していることから、通信を行い確保したメモリにデータを格納することがわかるのでdownload_data()と名前を変えておきます。

通信先はdownload_data()の第一引数になっているDAT_00429e70ですが、特にデータは入ってないので、実行することで割り与えられるデータと予想できます。

そこでDAT_00429e70のリファレンスを見ると最初に飛ばしたFUN_004014f0()で書き込まれているのがわかります。

FUN_004014f0の解析

最初に飛ばしたFUN_004014f0()を解析する必要があるので、戻ってきました。
DAT_00429e70FUN_004031c0FUN_00403380で呼ばれています。
それぞれ解析していくとFUN_004031c0は第二引数のデータを復号していることがわかうるのでdecrypt_urlと名前を付けます。
FUN_00403380は特殊な計算をしているが現時点ではよくわからないのでおいておきます。

直前に格納しているデータが暗号化したURLのデータで、第四引数key_buffが鍵を生成するためのHashDataとなっている。このkey_buffFUN_004014f0()の前半の関数で呼び出されているので、そのあたりも解析する必要がある。

解析した結果は次のとおりである。

耐解析用のチェックをしているが、このcrackmeで面白いのは例えばcheck_hardware_debugではハードウェアブレークポイントが仕掛けられているかを確認するが、仕掛けられていたらkey_buffにデータを格納するというものである。

上記の関数のデータを格納する部分が実行されるようにPE-bearを用いてJE命令をNOPに変更する。

これでURLが復号され、通信を行うようになる。復号されると次のURLhttps://pastebin.com/raw/9FugFa91を取得することができる

FUN_00401690()の解析(URLからデータを取得した以降の処理)

先に取得したURLを見てみるとBase64のデータなので、Base64をデコードする処理が入っていると予想しつつ解析を進める。

URLからダウンロードに成功するとYou are on the right track!と表示される。

処理を追っていくとFUN_00403050でBase64デコードした後に、FUN_00405960でRtlDecompressBufferを呼び出し圧縮したデータを展開している。
さらにクリップボードの値を取得し、その値をxorしているところまでがわかる。

RtlDecompressBufferを呼び出した後のデータは下図のようになっている。

この後クリップボードの値とxorするが、データの内容からxorするデータはmalwarebytesであると予想できる。そのあとのコードは先頭2byteがMZであるか比較したあと、secret.dll#1を実行する動きをすることがわかる。

このデータをダンプして、CyberChefを使う。

MZThis program cannot be run in DOS modeという文字が確認でき、実行ファイルとなっている。このデータを保存する。

secret.dll(exe)の解析

dllという名称で呼び出しているが、exportを見てもentry以外の何もないので、普通に実行できそうだとわかる。exeに拡張子を変えて実行すると下記の結果となる。

You failed :( Better luck next time!という文字があるので、この文字を探して解析を進める。
この文字が使用されているFUN_00401260関数を解析していくと、最初にrundll32.exeのパスをチェックして、そのあとにEnumWindowsので処理を行っている。

このEnumWindowsの処理ではGetClassnameAで取得した値のチェックサムを計算し、その結果が第二引数の値と一致していれば、次の処理に移る。

DAT_0040e000のデータをxorしていき、そのデータをFUN_00401130zwCreateSectionNtMapViewOfSection等で利用していくことからDAT_0040e000shellcodeであろうと予想がつく。

ProcessHollowing、プロセスインジェクションっぽいテクニックが使用されていることまで突き詰めたら、あとはシェルコードを取得して強制的に実行してあげればよい。

デバッガで無理やりif文の中に入るようにした後、do-while文が終わったタイミングでメモリダンプをとる。

FUN_004014d0でチェックサムと取っているので、そこでif文の中に入ることがわかる。

あとはこのシェルコードを実行してあげればよい。

シェルコードの実行

PEBearsecret.exeに新たなセクションを追加して、シェルコードから実行させるようにすればよい。

PEBearでAdd a new sectionを開き、Choose a fileからダンプしたシェルコードを選択し、サイズを176とし、read、write、executeにチェックを入れて(画像では入れてないが)追加する。

そのあと追加したデータのDisasmからSet EP = 13000とした後にexeとして保存する

最後に保存したexeを実行するとflagが入手できる。

終わりに

いろいろなテクニックが詰まった、いい問題でした。皆さんもぜひやってみてください。私もやったんだからさww

Thank you @hasherezade

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です