64ビット対応dllインジェクション

24

Upload: sin-furuya02

Post on 10-Jul-2015

3.911 views

Category:

Documents


3 download

DESCRIPTION

CLR/H66で担当させて頂いたセッションの資料です。pdf用に一部編集されています。

TRANSCRIPT

DLLInjectionの利用例

動作イメージ

Windows メモ帳

メモ帳

メモ帳

パワー ポイント

ブラウザ

動作イメージ

各プロセスのメモリ空間内には、当該プロセスの独自コード・カーネル・DLLがロード

プロセスBプロセスA

カーネルコード

プロセスAのコード

Other.dll

user32.dll

kernel32.dll

カーネルコード

プロセスBのコード

test.dll

user32.dll

kernel32.dll

2種類のDLL配置

ダイナミックにロードする

//test.dllをロードする HMODULE hDll = ::LoadLibrary( "test.dll" ); if ( hDll != NULL ){ //DLLを使用するコードをここに記述 //test.dllをアンロードする ::FreeLibrary( hDll ); }

AのコードでBのメモリ空間に

ロードすればインジェクション成立

プロセスBプロセスA

プロセスAのコード

LoadLibrary() プロセスBのコード

test.dll

他プロセスでスレッド実行

HANDLE CreateRemoteThread( HANDLE hProcess, // 挿入先プロセスハンドル LPSECURITY_ATTRIBUTES lpAttr,// セキュリティ属性 DWORD dwStackSize, // スタックサイズ LPTHREAD_START_ROUTINE lpAddr,//関数ポインタ LPVOID lpParameter, // 引数ポインタ DWORD dwCreationFlags, // 作成フラグ LPDWORD lpThreadId // スレッド識別子 );

LPTHREAD_START_ROUTINE lpAddr,//関数ポインタ

LPTHREAD_START_ROUTINE 型

typedef DWORD (

__stdcall *LPTHREAD_START_ROUTINE)

( [in] LPVOID lpThreadParameter );

HMODULE LoadLibrary( LPCTSTR lpFileName //モジュール名 ); BOOL FreeLibrary( HMODULE hModule // DLLハンドル );

関数のアドレス

カーネルコード

プロセスAのコード

0x75230000 kernel32.dll

カーネルコード

プロセスBのコード

0x75230000 kernel32.dll

0x75230xxx

Loadribrary()

0x75230xxx

Loadribrary()

プロセスBプロセスA

インジェクション・コード //kernel32のモジュールハンドル取得 IntPtr m = GetModuleHandle("kernel32.dll"); //LoadLibrary()のアドレス取得 UIntPtr a = GetProcAddress(m, "LoadLibraryA"); //スレッド実行 IntPtr t = CreateRemoteThread( hProcess,IntPtr.Zero, 0, a, param, 0, out b); //スレッド完了待ち(DllMainから返るのを待つ) WaitForSingleObject(t,INFINITE); //DLLハンドルの取得 if (GetExitCodeThread(t, out hDll)) { if(hDll!=IntPtr.Zero)result = true;//成功 } //スレッドクローズ CloseHandle(t);

LoadLibraryのパラメータ

HMODULE hDll = ::LoadLibrary( "test.dll" );

自プロセスのメモリ空間に展開された文字列へのポインタ プロセスBのスレッドにはプロセスB上のアドレスが必要

プロセスA

0x02583000

“test.dll”

プロセスB

0x02583000

Int x=100

他プロセスでメモリ操作 VirtualAllocEx() 挿入先プロセスでメモリ確保

プロセスA プロセスB

VirtualAllocEx

WriteProcessMemory() 挿入先のメモリ空間に書き込む

WriteProcessMemory

書き込んだメモリを使用する Loadribrary()のパラメータ

VirtualFreeEx() 確保したメモリの開放

0x000034000

“test.dll”

メモリ操作・コード UInt32 MEM_COMMIT = 0x1000; UInt32 PAGE_EXECUTE_READWRITE = 0x40; IntPtr m = (IntPtr)VirtualAllocEx( hProcess, IntPtr.Zero, (uint)len, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (m != IntPtr.Zero) { //確保した挿入先の領域にDLL名を書き込む WriteProcessMemory( hProcess, m, dllName, (UIntPtr)len, out b); //確保したメモリをここで使用する //(挿入先でLoadLibraryを呼び出す) //確保したメモリの開放 VirtualFreeEx(hProcess, m, 0, 0x8000); }

64bitOSの問題(混在) 64ビットOSでは、従来の32ビットプログラムもWOW64によりそのまま使用することができるため、両者が混在している

64ビットEXEは、64ビットDLLのみ使用可能 32ビットEXEは、32ビットDLLのみ使用可能

Dllインジェクションも、挿入先に合わせたDLLが必要

64bitOSの問題 (ERROR_ACCESS_DENIED)

WOW64上からは、CreateRemoteThread()は、 ERROR_ACCESS_DENIEDが発生して使用できません。 使用できないという正規のドキュメントは、見つけられませんでしたが、 同一趣旨のコメントが多数検索にヒットします。

64bit上では、64bitのEXEしか使用できない

64bitOSの問題 (kernel32.dllのアドレスが違う)

WOW64上の32bitプロセスは、違うkernel32.dllを ロードしている。

64ビット上から32ビットプロセスのアドレスが分からない

c:¥>listdlls POWERPNT.EXE 32ビットプロセス

ListDLLs v3.1 - List loaded DLLs

Base Size Path

0x00000000776b0000 0x160000 C:¥Windows¥SysWOW64¥ntdll.dll

0x0000000075230000 0x110000 C:¥Windows¥syswow64¥kernel32.dll

>ListDlls notepad 64ビットプロセス

ListDLLs v3.1 - List loaded DLLs

Base Size Path

0x0000000077650000 0x186000 C:¥Windows¥system32¥ntdll.dll

0x00000000771c0000 0x12d000 C:¥Windows¥system32¥kernel32.dll

64bitOSの問題(まとめ) マトリックスにしてみると、下記の3種類しか動作できないことが分かる

挿入先に応じたDLLが必要 WOW64で動作させない 64bitのEXE上で32bitのkernel32ロードのアドレスが必要

挿入先に応じたDLLが必要 64bitOS上では、64bitの「notepad.exe」が動作している

OSにより違う場合は、2種類用意して実行時に選択する

WOW64で動作させない OSに合わせたEXEを用意する

.NETの「AnyCPU」で作成すれば解決

//ポインタが8バイトの場合 If(IntPtr.Size == 8){ //64bit環境で動作中 }

64bitから32bitの kernel32.dllのアドレス取得

32bitでコンパイルした下記のEXEを実行して アドレスを取得する

参考「64bitプロセスから32bitプロセスにDLL Injection (C言語) 」http://nazochu.blogspot.com/2011/09/64bit32bitdll-injection.html

#include <windows.h>

int main(int, char**){

return(int) =

GetProcAddress(

GetModuleHandle(“kernel32”), “LoadLibraryA”);

}

4G超のアドレスに注意が必要

kernel32.dllのアドレスは幸い32bitで表現可能だった

>ListDlls notepad 64ビットプロセス

ListDLLs v3.1 - List loaded DLLs

Base Size Path

0x0000000077650000 0x186000 C:¥Windows¥system32¥ntdll.dll

0x00000000771c0000 0x12d000 C:¥Windows¥system32¥kernel32.dll

Dllハンドルは32bitで表現できない