サポート情報 | フォーカスシステムズ サイバーフォレンジックセンター

メールでのお問い合わせ
お問い合わせはこちら
東京証券取引所 プライバシーマーク ISMS JUSE

サポート情報

ホーム > サポート情報一覧 > 仮想メモリ取得した方法の正体

仮想メモリ取得した方法の正体

目次へ

 これで、メモリに展開されたプログラムの出所と展開方法がわかりました。しかし、この展開先のメモリ領域は、どのように取得したのでしょうか?Importテーブルには、GlobalAllocはありましたが、VirtualAllocを使用している様子はありませんでした。また、ここまでの処理の実行で、GlobalAllocの呼び出しを見つけてはいませんでした。もちろん、メモリ内のプログラムの解析のほうが重要で、そこはブラックボックスという考え方もありかと思います。一方で、そういった技法を知っておけば、解析の時に何かの役に立つかもしれません。

 今回の解析で、その方法が発見されているので、解析を交えて概要を紹介しておきます。通常行われないような動作なので、この挙動を検知してアラートをあげることができれば、防止策になるかもしれませんね。

 ヒントは、メモリ展開の直前の処理にありました。プログラムを書く方なら分かると思いますが、今からデータをまっさらな領域に展開しよう、という場合は、割と直前にメモリを確保するものです。そのため、直前のコードが怪しい、と思ってコードをみていると、0x00406EA9の処理がおかしいことに気づきます。ここでも、retnの直前でeaxをpushしており、任意のアドレスを呼び出すためにretnを利用していることが伺えます。そこで、ここにブレークポイントを設定し、再度実行しなおしてみました(【図39】参照)。

CryptoWall_IDA_Step010

【図39】不審なretnでブレークしたときの状況

 

 すると、retn実行時に実行されるアドレスは、kernel32.dll内のVirtualAlloc関数だったのです。スタックに設定された値から、VertualAllocのアドレスの後の4バイトは、VirtualAlloc終了時のリターンアドレスです。その後ろに、第1~4引数が続きます。このことから、実行しているAPIは以下のようになります。

 

 VirtualAlloc( Null, // システムが割り当て領域を決定

        0x2ECB, // サイズ:11,979byte

        MEM_COMMIT, // 物理的な領域を割り当て

        PAGE_EXECUTE_READWRITE // 実行アクセス、読み取りアクセス、書き込みアクセスを許可

       );

 

これが、先ほど展開されたメモリの取得の正体だったのです。

 それにしても、ではこのVirtualAllocのアドレスは、どのように知ったのでしょうか?その答えは、VirtualAllocを保持している0x0040D6C0へ値を格納している処理にありました。0x00406E82のcallの結果がeaxに格納されており、その直後に0x0040D6C0へ値を格納していたのです。つまり、0x00406E82の「call sub_4021D0」によって取得しているのです。では、0x00406E82にブレークポイントを設定してまた再実行してみましょう(【図40】参照)。

CryptoWall_IDA_Step011

【図40】VirtualAllocのアドレスを取得する処理の直前でのブレーク

 

 関数の引数として、第1引数にkernel32.dllのポインタを指定しているのが分かります。また第2引数は0xE5F4E8B5という値を設定しています。この値は、関数の中で取得したいAPIかどうかを照合する処理で用いています。処理内で、実際に照合している処理を例に示します(【図41】参照)。

CryptoWall_IDA_Step012

【図41】利用したいAPIの照合処理

 

 0x00402410のcmpで比較し、合致した場合に0x00402419でediにecx(VirtualAllocのアドレス)を格納しています。この後の処理でediをeaxに格納しており、この関数は「取得できたらeaxにアドレス、取得できなかったらeax=0」という処理を行っています。

 なお、0x00402410で照合しているeaxの算出方法は複雑になっています。xorの使い方も含め、これも検知逃れまたは難読化の意図が見て取れます。大まかな流れとしては、kernel32.dllのポインタから、dllの内部のAPIアドレスのマップとそのインデックスのアドレスを割出し、そこから得られるAPIのポインタや情報を元に、繰り返し処理で照合していく、という処理が行われています。

 この方法を用いることで、importテーブルに載らない状態でそのAPIを使用することができ、悪意ある処理がよく使うAPIの利用を隠すことに用いられると考えられます。そのため、調査にあたっても、こういった方法を知っておいて、見落としが無いように心がける必要があります。もし、怪しいと思っていても、その処理が見つからないならば、このようなケースを想定して、使用していると推測するAPIを実装しているdllのアドレスの参照や、メモリ上のAPIにブレークポイントを張って調査することも一つの方法です。

 

 < メモリに展開されたプログラムはどこから来たのか?目 次 仮想メモリ内の難読化 >