セキュリティ系の勉強、その他開発メモとか雑談. GithubはUnity触っていた頃ものがメイン Twitterフォローもよろしくです

アナライジングマルウェア 2.3パックから メモ

//

パックされたプログラムの特徴

パックされたプログラムは、パック前と同様に問題なく実行されるがファイルサイズが減少する。書籍ではUPXを使用して電卓をパックし、それをLordPEで確認している。パック前には.textや.dataというセクションテーブルが見られたが、パック後にはUPX0,UPX1というセクションテーブルが確認され、サイズ等も変化している。インポートテーブルを確認するとパック前よりインポートされるAPIは確実に減少し、LoadLibraryA,GetProcAddress,ExitProcessの3つのみになっていた。

パックされたプログラムの実行フロー

パックされたプログラムが実行可能なのは、プログラムのエントリポイント付近にオリジナルコードを展開するための処理が追加されているから。一般に「展開ルーチン」と「圧縮されたオリジナルコード」で構成され以下のような流れをたどる。

f:id:thinline196:20180827223438p:plain


IAT(インポートアドレステーブル)は通常のプログラムはインポートしている関数のアドレスをローダが変換してくれるが、パックされているものの場合、展開ルーチン用のIATは変換されるけれど、オリジナルコードがインポートしている関数のIATは変更してくれない。ので、ローダが本来行ってくれるIATの書き換え処理(再構築)を展開ルーチンの中で行わなければならない。

アンパックに使うツール

アンパックを行うにはデバッガ、メモリダンプツール、IAT再構築ツールを用いる。

OllyDbg

デバッガ。2014年で更新は止まっているようだけれど、今の所(2018)使えそう。64bit版も出てた。

OllyDump

OllyDbgでアタッチしているプロセスのメモリダンプを取得するためのプラグイン。OllyDbgに追加する形で使用するが、僕は一部本通りには動作しない部分があり困った、どうしよう。

ImportStudio

メモリダンプとIATの再構築を行うOllyDbgのプラグイン。ダンプ時に設定できるオプションやIATを探す際のオプションを詳細に設定できる。ダウンロードリンクは生きてました。




マニュアルアンパック

主な流れは以下.

1.デバッガでマルウェアにアタッチしOEP(オリジナルエントリーポイント)まで実行する。

展開ルーチンがオリジナルコードを復元し終わるところまで実行させるため、デバッガでアンパックを行いたいプログラムにアタッチする。展開ルーチンでどのような処理が行われるかはパッカーによって違う.OEPを見つけ出すには

  1. pushad命令と対応するpopad命令に注目する

pushad命令は汎用レジスタの値をスタックにプッシュする命令。popad命令はスタックから汎用レジスタに値をポップする命令。パッカーには展開ルーチンの先頭と末尾でそれぞれが呼ばれる場合があるので、これを見つける。popadの後にはOEPへのjmpがある可能性がある。

  1. 動的に生成された箇所に制御が映る瞬間に着目する

パックされたプログラムを実行するにはオリジナルのコードをどこかに展開しなければならいため、動的に生成された箇所は怪しい。そこにアクセスした場合にブレークするメモリブレークポイントなどを仕込むと良い。

  1. jmp/call命令に着目する

展開ルーチンではデコード処理や再構築処理の過程で同じようなコードを繰り返す箇所が多いため、その辺りは読み飛ばしjmp/call命令でどこに制御が飛ぶかだけ見ているとOEPが探しやすくなる。特にOEPに制御を移すようなjmp/call命令では、オペランドが即値であったり汎用レジスタであったりする場合が多い。

2.OEPに到達した後のメモリをダンプし、ファイルに保存する。

LordPEやOllyDump等、ツールはたくさんある。

3.ダンプしたファイルのIATを再構築する。

IATをロード前に修復する。PEヘッダはそのままだとパックされたIATを指しているのでオリジナルコードのIATをさすように変更する必要がある。IAT再構築はツールを使用するのが一般的。ImportRecが紹介されていたが、更新が2010になっていたのでおそらく更新されていない。ImportStudioでもできると書いてあった。






アンパックを妨害するテクニック

Stolen Bytes (Stolen Codes)

動的に確保された領域にオリジナルコードの一部をあらかじめコピーしておき、コピーしたコードを実行した後で元のコードを続けて実行する方法。これにより、発見したOEPが本来のOEPとズレてしまっていたり、正常なメモリダンプを取得できなくなったりする。ASProtectというパッカーで利用されている。

SizeOfImageの改変

SizeOfImageはPEヘッダ内のOptionalHeader構造体に含まれていて、メモリ上にロードされるファイルのサイズを示している。SizeOfImageの値が非常に大きいとデバッガでのアタッチやメモリダンプがうまくいかないことがある。

Import Redirection

IAT再構築時や逆アセンブラでの解析時にインポートしているAPIをわかりにくくする手法。これが行われると、IATはAPIのエントリポイントのアドレスではなく、APIを呼び出すための関数のアドレスとなり、どんなAPIが呼ばれているかわかりにくくなる。また、APIを呼び出す関数内では単純にcall命令だけでAPIに制御を移すのではなく、一旦汎用レジスタAPIアドレスを格納してからjmp命令で関数を呼び出すといったことをする場合もある。
mov -> jmpで呼び出す方法やAPIアドレスをpush→retでAPIのエントリポイントに飛ぶ方法など。tELockというパッカーなどで使用されている。
IATに格納されている値をAPIのアドレスに書き換えることでこの妨害は回避することができる。



参照元