wivern ロゴ

サイバーセキュリティ研究所

サイバーセキュリティを中心に、軍事、防犯、サーバーの管理と監視、その他、最新技術を研究しています。


「リバースエンジニアリングバイブル」勉強メモ#4

DLL の分析

「リバースエンジニアリングバイブル」#4

前回に続き、「リバースエンジニアリングバイブル」の勉強メモ第4弾です。 実行環境は、Windows7(64bit版)です。実行環境は、Windows7(64bit版)です。

4章 DLL の分析
[ DLL のアドレス計算方法]
DLL の ImageBase は 0x10000000 番地になっている。
これは DLL 作成時にコンパイラがデフォルトで指定してくれるアドレスで、EXE ファイルは通常 0x400000 番地にロードされる。
※ビルドオプションで変更可能。
(DLL のアドレス計算は)ImageBase と BaseOfCode だけを見る。

「ImageBase」は「Base Address」の誤りではないか?
まず、現在の DLL がメモリにロードされているアドレス( Base Address )を確認し、 次に、そのファイルの PE ヘッダーを見て BaseOfCode を足せばよい。
DLL のロードアドレス= Base Address + BaseOfCode

[再配置(re-allocation)された DLL のアドレス計算方法]
PE → Optional Header → ImageBase:この DLL がロードされるときのアドレス
PE ヘッダーでは、ベースアドレスにロードできなかった場合に備えて、再配置セクションと呼ばれるものを用意している。

[誤植]
p.66 16行目
誤「Dll Base : 0x10000000」
正「Dll.dll : 0x10000000」
p.66 下段
「オフセット 19000 を足して・・・」
→このオフセットはどこから出てきた?
リバーサーがオペコードであるパターンを探すとき、グローバル変数やジャンプ命令に対応する絶対アドレスの部分は読み飛ばす必要がある。
メモリにロードされるたびに値が変わる場合があるので、すべてのオペコードを見つけたとしても何の結果にも結びつかない可能性がある。
また、CRC(Cyclic Redundancy Check) やチェックサム(checksum)検査をするときも、この部分がメモリにロードされるたびに値が変わるので、計算するたびに異なる値が出てくる可能性がある。

[ DLL のロードアドレスを固定する方法]
「#pragma comment()」の /base: オプションと /fixed: リンカー(linker)オプションを指定すると、DLL が再配置されずにプログラマが指定したアドレスに入る。
例:#pragma comment(linker, "/base:0x23400000 /fixed" )
こうすると再配置の処理を必要としないため、DLL の特徴の1つである IMAGE_DIR_ENTRY_BASERELOC フィールドの RVA と Size の値が割り当てられず、通常の EXE ファイルのように0で埋められる。

[ DLL のエクスポート関数]
DLL には、外部から呼び出すためのエクスポート関数がある。バイナリで確認するときにはこれも1つのエントリポイントになる。
EXE のような場合には、スタートアドレスが基本的に WinMain() しかないが( TLS Callback 等を使用した場合を除く)、DLL の場合はエクスポート関数の数だけエントリが存在する。

Dependency Walker
http://www.dependencywalker.com/

Dependency Walker 日本語化パッチ( 2.2.6000.0 の x86版のみ)
http://blog.livedoor.jp/blackwingcat/archives/1000078.html

PE Tools
http://sourceforge.net/projects/pe-tools/
DLL にエクスポート関数がある場合には、Dependency Walker や PE Tools 等で関数の名前まで確認でき、関数のエントリはアドレスが表示されるため、逆アセンブラやデバッガ等で簡単に見つけることができる。

[逆アセンブラ]
IDA Pro Freeware Version 6.1
http://www.weeebs.com/software/ida-pro-freeware-version-2381.html
Win32dasm (Win32 disassembler)
http://www.angelfire.com/dc/vashala/hacks%20pages/hack_programs/Win32dasm.html

[デバッガ]
OllyDbg
http://www.ollydbg.de/

OllyDbg1.10用日本語化パッチ
http://hp.vector.co.jp/authors/VA028184/#TOOL

WinDbg(32ビット版)
http://msdn.microsoft.com/ja-jp/windows/hardware/gg463016

WinDbg(64ビット版)
http://msdn.microsoft.com/ja-jp/windows/hardware/gg463012

[DllAtach/DllDetach 探索]
DllMain のプロトタイプ:

BOOL WINAPI DllMain(
 HINSTANCE hinstDLL, // DLL モジュールのハンドル
 DWORD fdwReason,   // 関数を呼び出す理由
 LPVOID lpvReserved  // 予約済み
) ;

最も重要なのは引数の fdwReason で、値として4つの定数があるため、DllMain() の中には fdwReason を利用した switch/case 文が存在する。

fdwReason の4つの定数:DLL_PROCESS_ATACH, DLL_PROCESS_DETACH, DLL_THREAD_ATACH, DLL_THREAD_DETACH
IDA を使用する場合には DllMain() の位置を親切に解析してくれるので、探し回る必要はない。

[パッキングされた DLL の DllMain() を探索]
プログラマが DllMain() を作成するときには、最初に switch/case 文を作成するはずなので、次のようなパターンのアセンブラコードが生成されるはずである。

8B 44 24 08 mov eax,[esp+8]
83 E8 00   sub eax,0
74 XX    jz short loc_xxxxxxxx

バイナリのコードセクションで「8B 44 24 08 83 E8 00 74」というオペコードを持ったパターンを見つける。
解析が困難な Themida でパッキングしても結果は同じになる。

Themida - Advanced Windows Software Proection System
http://www.oreans.com/themida.php

この方法は通常ウイルスソフトで使うヒューリスティックパターン(heuristic pattern)と呼ばれる手法を応用したもの。 特定の機能のためには、あるコードを採用するしかなかったりするが、そのようなパターンのコードの存在を把握することで、ウイルスが頻繁に使用する重要パターンをワクチンに持たせておいて、そのパターンをコードが持っているかを確認する方法である。

DisableThreadLibraryCalls()
マイクロソフトが、スレッドが生成されたり呼び出されたときに DllMain() が呼び出されないように提供している関数。
→その DLL にスレッドが非常に多く存在したり、生成と消滅を繰り返したりする場合は、システムの内部で連続して DllMain() が呼び出されているはずなので、最終的には処理に負荷がかかる可能性がある。

DLL_PROCESS_ATACH/DLL_PROCESS_DETACH
 プロセスに DLL がロードされるときに呼び出される
DLL_THREAD_ATACH/DLL_THREAD_DETACH
 スレッドが生成されるか終了するたびに1回呼び出される

多くのプログラマが習慣的にこの関数を DllMain() の DLL_THREAD_ATACH に入れている。
この関数はその位置でなければ呼び出されることもほとんどないので、DisableThreadLibraryCalls() を呼び出しているところを見つけたら、そこが DllMain() であることがほぼ確実である。
IAT で DisableThreadLibraryCalls() がどこから呼び出されているかを見つけることもできるし、DisableThreadLibraryCalls() に API フッキングを仕掛けて実行した後でリターンアドレスをフィルタリングすれば。そのリターンアドレスが DllMain() の中にあると判断することもできる。

・IAT( Import Address Table)
「Advanced Windows 改訂第4版(2001/5/1)」に詳細が書かれている。
http://amazon.co.jp/dp/4756138055


記述に際しては、細心の注意をしたつもりですが、間違いやご指摘がありましたら、こちらからお知らせいただけると幸いです。


→「リバースエンジニアリングバイブル」勉強メモ#5
←「リバースエンジニアリングバイブル」勉強メモ#3


« 戻る