web-dev-qa-db-ja.com

注入されたシェルコードからWin32 APIをインポートするためのより良い方法

バイナリイメージの TLSコールバック を介して、ネイティブx86コードを.NETアプリケーションに注入しています。残念ながら、.NET実行可能ファイルはPE内でmscorlib.dllのみをインポートし、実行時にkernel32.dllをメモリスペースに自動的にマップします。インポートを注入したくありません。これにより、LoadLibraryGetProcAddressのアドレスを見つけにくくなります。

私が最初に解決策を考えたのは、mov eax, dword ptr [fs:030h]を介してPEBを見つけ、そこからPEB->LdrPEB->Ldr.InMemoryOrderModuleList.Flinkをロードし、それらを使用してメモリ内のモジュールを見つけることでした。そこから、メモリ内のkernel32.dllのベースアドレスを取得し、PEヘッダーへのオフセットとエクスポートディレクトリRVAを取得できます。そこから、エクスポートのインポートエントリを名前でスキャンして、アドレスを見つけることができます。

これには次の問題があります。

  • API呼び出しと同じくらい簡単なものの多くのコード。
  • API名を表すASCII文字列をコードに埋め込む必要があります。
  • 長いランタイム/複数のスレッドで見つかったアドレスをキャッシュするのは厄介です。

輸入注入に頼らずにこれらの問題を解決するこれを行うよりきれいな方法はありますか? CLRはEPがマネージドILへのジャンプであることに依存しているため、イメージのEPを変更できないことに注意してください。

9
Polynomial

説明されている手動バインディングプロセスで問題(2)と(3)を解決する良い方法がありますが、ここでStackExchangeでシェルコードを設計することに関する優れた手の込んだパブリックチュートリアルを公開するのは仕方がありません。 ^ _ ^つまり、(2)にcrcsを使用し、(3)に間接呼び出しを使用するヒントがあります。これらの2つの概念を適用する正確な方法を推測するには、手動バインディングプロセスに十分慣れているようです。

(1)に関しては問題ではありませんが、誤った仮定です。エクスポートをインポートにバインドし、プログラマーがシステムAPIを呼び出す機能を提供することは、どんな意味でもnotのことは簡単です。問題は、誰がすべての汚い仕事をするかだけです。プレーンテキストの名前に依存しているためにWindowsリンカーのサービスを拒否するとすぐに、独自の方法でダーティディテールを実装する必要があります。

とにかくバイナリを変更する場合、インポートインジェクションが最もクリーンな方法のように見えますが、プレーンテキストのAPI名が追加されるので、それはあなたの検討の範囲外だと思います。

3
Van Jone