はじめに
FriendlyではDLLインジェクションを用いて、任意のDLLを読み込ませることができます。
DLLインジェクションとは、他のプロセス上でコードを実行する方法の一つです。
DLLインジェクションはクラッキングなどに悪用されることもあるようですが、Friendlyでは上手く使用しています。
今回はそのDLLインジェクションのやり方について調べてみました。
FriendlyのDLLインジェクションの概要
Codeer.Friendly.Windows.InsideパッケージのDllInjector.Load()メソッドが対象プロセスにdllを読み込ませるメソッドです。
このメソッドでは、カーネルを用いて対象プロセスに働きかけることでdllを読み込ませています。
大まかな手順としては、以下の通りです。
- ロードさせるDLL名称を、対象プロセス内にメモリを確保して書き込みます
- カーネルからライブラリを読み込む関数(LoadLibraryW)を取得します
- 対象プロセスの別スレッドにて、DLLをロードします
- DLLのロードが終わるまで待ちます
上記の手順は、以下のWindowsAPIを実行することで実現されています。
- 対象プロセス内にメモリを確保:VirtualAllocEx
- 指定されたプロセスのメモリ領域にデータを書き込み:WriteProcessMemory
- DLLが持つ、指定されたエクスポート済みの関数のアドレスを取得:GetProcAddress
- 別のプロセスのアドレス空間で稼働するスレッドを作成:CreateRemoteThread
- シグナルを待つ:WaitForSingleObject
DLLインジェクションのポイント
FriendlyのコードではありませんがDLLインジェクションの原理自体は参考の記事と同様であるため、詳細を知りたい場合は参考をご覧ください。
以下は、自分が参考を読んでポイントだと思った点を整理したものになります。
- kernel.dllに含まれているLoadLibraryというAPIは全てのプロセス空間で同一アドレスにロードされている。そのため、別プロセスで取得したLoadLibraryのポインタが、対象とするプロセスのLoadLibraryのポインタと同じである。
- CreateRemoteThread APIを用いると指定したプロセスにスレッドを作成し、関数を実行させられる。上記で取得したLoadLibraryのポインタを用いて指定したDLLを読み込める。
おわりに
今回、Friendlyコンポーネントから入り、DLLインジェクションの仕組みについて勉強してみました。おそらく開発で直接活用される機会はなさそうですが、WindowsAPIを詳しく知ることで色々なことができるようになるのだなと思いました。
今後は、FriendlyがDLLインジェクションをした後のことについて、もう少し勉強してみようと思います。
参考
64ビット対応のDLLインジェクション - SIN@SAPPOROWORKSの覚書
http://furuya02.hatenablog.com/entry/20120114/1326484897