メモリ上のプログラムや用いられている文字列が難読化されていることを踏まえた上で、実際の処理を追いかけてみましょう。一つの着眼点としては、Windows APIの使用状況を把握することが挙げられます。OSの機能を呼び出すために用いられますが、その使用状況と順序から、それぞれの個所の処理の目的がある程度見えてくるためです。
では、このランサムウェアでは、どのようにしてAPIを呼び出しているのでしょうか。
Windows APIを利用する場合、そのAPIのアドレスを知る必要があります。このアドレスを知るために、このランサムウェアでは「GetProcAddress」APIを用いていることが分かりました。処理の流れとしては、GetProcAddresのポインタを取得し、DLLのハンドルと関数名を渡してAPIのポインタを取得し、そのポインタにcallを行うという方法です。この時の関数名は、先ほどの[0003E]の処理を用いています。少し追跡してみましょう。
まず、GetProcAddressの取得方法を探した結果、[00A06]で行っていることが判明しました(【図46】参照)。これは、各処理を追いかける中で、callの結果としてeaxにGetProcAddressのポインタが格納されることを発見することで判明したものです。なお、この[00A06]の処理では、GetModuleHandleAのポインタを得る場合にも用いられていました。
内容としては、VirtualAllocの取得と同様に、dll内部のパラメータを参照して判定しています。判定に用いるパラメータは、やはりローテートやxor処理を行っており、その結果で判定することで判定の意図の解読回避を図っていると考えられます。
[00A06]の処理で得られたGetProcAddressのアドレスを用いて、call eaxで実際に処理を呼び出しています。第2引数を見ると、文字列のアドレスが指定されており、そのアドレスの中身に使用したいAPIの文字列が格納されているのが分かります。そして、GetProcAddressで得られたポインタを用いて、さらにcall eaxを実行することで、所定のWindows APIを実行できるようにしているのです。
< 仮想メモリ内の難読化 | 目 次 | 仮想メモリ内のWindows API使用フロー > |