Windows ライブラリをロードする方法はいくつかありますが、それぞれの方法は異なる目的を果たします。
LoadLibrary()
and を手動で使用GetProcAddress()
することは、いくつかの異なる動的リンクの状況について実行時に決定できるようにすることを目的としています。これらの呼び出しは、結果の PE ファイルのどの側面にもまったく影響を与えない単純なシステム コールであり、によって返されるアドレスはGetProcAddress()
、コード生成に関して特別なものではありません。これは、呼び出し元がこれらのシンボルを非常に構文レベルで適切に使用する責任があることを意味します (たとえば、適切な呼び出し規則と、関数呼び出しの場合は引数の正しい数、サイズ、および配置を使用します)。
.lib
に関連付けられたファイルに対するリンク.dll
は異なります。クライアント コードは、静的にリンクされたシンボルであるかのように、外部識別子を使用してランタイム コンテンツを参照します。ビルド プロセス中に、リンカーはこれらの識別子をファイル内のシンボルで解決し.lib
ます。原則として、これらのシンボルは (他のシンボルと同様に) あらゆるものを指すことができますが、自動生成された.lib
ファイルは、ロード時に PE ローダーによって埋められるメモリ コンテンツへの小さなプロキシとして機能するシンボルを提供するだけです。
これらのプロキシを実装する方法は、予想されるメモリ アクセスの種類によって異なります。たとえば、 の関数を参照するシンボルは、クライアント コードからの元の命令がコンテンツからの命令にヒットし、によって解決されたアドレスに転送されるように.dll
、単一の間接jmp
命令として実装されます。ロード時の PE ローダー。このアドレスには、動的にロードされる関数のコードが存在します。call
jmp
.lib
詳細はさておき、これはすべて、クライアント コードが単独で行うのと同じジョブを実行するよう PE ローダーに指示するために使用さLoadLibrary()
れます。GetProcAddress()
必要なすべてのシンボルに。PE ローダーは、クライアント実行可能ファイルのインポート テーブルにある情報から、ロード時にこれを自動的に行います。
言い換えると、読み込み時の動的リンクは、実行時の動的リンクよりも、たとえあったとしてもごくわずかでも遅く、太りますが、特に多くのライブラリが常に必要とされるため、通常の開発者にはるかに単純なプログラミング インターフェイスを提供することを目的としています。いつでも利用できます。このような状況では、手動でロードして追加のロジックを提供しようとしても役に立ちません。
要約すると、パフォーマンスや堅牢性が向上しているように見えるという理由だけで、わざわざ使用LoadLibrary()
しないでください。可能な限りファイルGetProcAddress()
にリンクします。.lib
トピックをさらに進めると、インポート テーブルをまったく含まない(システム コールやその他のエクスポートされたルーチンにアクセスできる) PE イメージを作成することさえ可能です。このアプローチは、読み込み時間の情報を削除することで疑わしい API の使用 (Winsock 呼び出しなど) を隠すためにマルウェアによって使用されます。