拾い物のコンパス

まともに書いたメモ

セキュリティキャンプ講義「仮想化技術を用いたマルウェア解析」にチャレンジしてみた(準備編)

今年の八月中旬に行われたセキュリティキャンプ全国大会2015の解析トラック15・16-Dでの講義「仮想化技術を用いたマルウェア解析」にチャレンジして、一通りできた。
発表者の黒米さんの許可が戴けたのでその流れを書き残す。
発表で使われたスライドは黒米さんの技術ブログ" 一生あとで読んでろ "に置いてある。

構成

プラグインを書くことよりも環境の準備に相当手間取ったので、準備編とプラグイン開発編の二段階で書いていく。
内容は以下の通り。
* 準備編
DECAFの導入と操作方法、注意点。
* プラグイン開発編
DECAF上で動かしているWindows仮想マシンで、仮想化検知を施されたプログラムblue.exeの検知を回避するプラグインを開発していく。

DECAFの準備

DECAFとは

DECAFは"Dynamic Executable Code Analysis Framework)の略で、QEMUにテイント解析機能を追加したTEMUの後継として作成されたバイナリ解析フレームワークのこと。詳しくはBitBlazeプロジェクトを検索。

インストール

インストールした環境は以下の通り。
* Ubuntu 14.04 LTS 64bit
他にはUbuntu 14.04 LTS 32bitArch Linux 64bitでインストールを試みたが、コンパイルが上手くいかず断念した。

まず、適当なディレクトリに移動してから以下のコマンドを実行していく。

$ sudo apt-get update
$ git clone https://github.com/sycurelab/DECAF
$ cd DECAF/decaf
$ pwd
/home/<user>/DECAF/decaf
$ sudo apt-get install qemu
$ sudo apt-get install build-dep qemu
$ sudo apt-get install binutils-dev
$ sudo apt-get install libboost-all-dev
$ ./configure # スライドの方にはテイント解析などをオンにするオプションが載っているが、今回はなくても問題なかった。  
$ make

もしもpython関係のエラーが出たら、コマンドのpythonが3系にリンクが張られていないかを確認すること。DECAFのスクリプトは2系で書かれていて、例外処理関係でエラーが出る。
具体的にはconfig-host.makPYTHON=pythonPYTHON=python2.7とかに書き換える。
これ以外のエラーが出たら・・・頑張れ!
DECAF自体のインストールはmakeが上手くいけばおしまい。
次はWindows仮想マシンを用意する。

仮想マシンの準備

Developer Resources : Microsoft Edge Devで30日だけ動作するWindows仮想マシンを配布しているので、ダウンロードする。
トップページ下にある"Virtual Machine"をクリック。
Windowsタブで
* Virtual Machine => IE8 on XP
* Select Platform => VMWare
と設定し、"Download .zip"からダウンロード。

$ pwd
/home/<user>/DECAF/decaf
$ mkdir ../VMs
$ mv $HOME/Downloads/IE8.XP.For.Windows.VMware.zip $HOME/DECAF/VMs
$ cd ../VMs
$ unzip IE8.XP.For.Windows.VMware.zip

VMWare用の仮想マシンからqemu用の仮想マシンを作成する.
作成には少々時間がかかる.容量も7GBほど食われた覚えがあるから注意.

$ qemu-img convert <name of VM>.vmdk -O qcow2 pre_ie8.qcow2
$ qemu-img convert -p -f qcow2 -O qcow2 -o compat=0.10 pre_ie8.qcow2 ie8.qcow2

qcowに変換しても動作するが,スナップショットが使えない.
作成が終わったら,下のコマンドで起動してみる.
$ $HOME/DECAF/decaf/i386-softmmu/qemu-system-i386 $HOME/DECAF/decaf/VMs/ie8.qcow2 -m 2048 -monitor stdio

これでWindowsXPが立ち上がることを確認する。-mオプションは割り当てるメモリの量を指定する.1GBでは動作が遅い。
また,今回は1つしかプロセッサを与えていないため,しばらくは処理が重いが時間を置くと落ち着く.
画面が引き延ばされるのを修正したいならCtrl+Alt+uを押す。
マウスが暴走するようなら
$ export SDL_VIDEO_X11_DGAMOUSE=0
Windowsが立ち上がることを確認したらシャットダウンする。
次に問題のプログラムをWindnowsにコピーする。

$ git clone https://github.com/ntddk/blue.git
$ sudo modprobe nbd
$ sudo qemu-nbd -c /dev/nbd0 ie8.qcow2
$ sudo /sbin/fdisk -l /dev/nbd0
$ sudo mount -o loop,offset=$((63*512)) /dev/nbd0 /mnt
$ sudo cp -r blue /mnt/Documents and Settings/All Users/Desktop
$ sudo umount /mnt
$ sudo qemu-nbd -d /dev/nbd0
$ sudo rmmod nbd

これで起動したときのデスクトップにblueのフォルダが出るようになる。
また,プラグインコンパイルしておく.

$ pwd
/home/<user>/DECAF/VMs
$ cd ../decaf/plugins
$ git clone https://github.com/ntddk/geteip
$ cd geteip
$ ./configure --decaf-path=/home/<user>/DECAF/decaf
$ make

このプラグインはIsDebuggerPresentをフックする.関数フックのテンプレートとして勉強になる.
今後の起動はDECAFの公式HPやスライドに載っている自動化スクリプトを使ってもできる.
下のスクリプトも同じ動作をするのでHaskell好きな人はどうぞ.

-- decaf_auto.hs
import System.IO
import System.Process         -- createProcess
import System.Posix.Directory -- changeWorkingDirectory
import Control.Concurrent (forkIO, threadDelay)

inputCmd p_in p_out cmd = do
    hPutStrLn p_in cmd
    threadDelay (1000 * 1000)
    -- Nonblocking
    forkIO $ putStrLn =<< hGetContents p_out

rawInput msg = do
    putStr msg                                             
    getLine

main :: IO ()
main = do
    hSetBuffering stdout NoBuffering
    decaf_path <- rawInput "*** Enter the root directory of DECAF (i386-softmmu/qemu-system-i386 should be there): "
    image_path <- rawInput "*** Enter the image path: "
    changeWorkingDirectory decaf_path
    (Just p_stdin, Just p_stdout, _, _) <- 
        createProcess (shell $ "i386-softmmu/qemu-system-i386 " ++ image_path ++ " -m 2048 -monitor stdio") { std_in = CreatePipe, std_out = CreatePipe }
    hSetBuffering p_stdin NoBuffering
    hSetBuffering p_stdout NoBuffering
    threadDelay (3 * 1000 * 1000)
    inputCmd p_stdin p_stdout "ps"
    inputCmd p_stdin p_stdout "help"
    return ()
-- E.O.F.

やっていることはqemu-system-i386のプロセスを作成し,そのプロセスの標準入力・標準出力に対しての操作を行っている.
しかしこのスクリプト(Python版も含めて)は使わないほうがいいと感じた.
これは実行すると書いてある動作以外をせず,qemuのプロンプトが出ないで入力・出力が閉じてしまう.
使うなら下のコマンドで普通に実行したほうがいい.

$ pwd
/home/<user>/DECAF/VMs
$ ../decaf/i386-softmmu/qemu-system-i386 ie8.qcow2 -m 2048 -monitor stdio

出力が一段落ついたあたりで一回Enterを押すと,(qemu)のプロンプトが出る.
プロンプトを表示させてプラグインを読みこませる.

(qemu) load_plugin ../decaf/plugins/geteip/geteip.so
(qemu) geteip blue.exe

これでblue.exeを実行した時にgeteip.cの内容が実行される.blue.exeblue/Release/blue.exeにある.
何もいじっていなければIsDebuggerPresentの実行時と実行後にそれぞれフックしたメッセージが出るだけのはず.
この辺はどうにも不安定で,いじっていなくてもIsDebuggerPresentを回避できたりした.
詳しいことはプラグイン開発編で書く.

最後に

ここまでがうまく行けば,準備は終わり.
誤字やうまく行かないところがあれば気軽に言ってくれると嬉しい.
ここまで長い記事を書いたことがないので,どこか間違いがありそうな気がする.
次は,blue.exeのソースを参考にプラグインを書いていく.