PE ファイルの静的と動的リンク ライブラリ

本章の内容はインポート表とエクスポート表の準備知識です。

静的リンク ライブラリ

静的リンク ライブラリの作成

VC6 を例として、静的リンク ライブラリを作成します。

VC6 でプロジェクトを作成し、Win32 Static Library を選択します。

現在はまだ何も必要ありませんので、オプションを選択せずに「フィニッシュ」をクリックします。

プロジェクト内で「ClassView」をクリックし、右クリックから新規プロジェクトを作成します。

新規クラスを作成し、名前を付けます。すると、対応するソースファイルとヘッダーファイル(xxx.h と xxx.cpp)が生成されます。

以下に示すように、加減乗除の関数を定義します。

「F7」を押してコンパイルします。生成されたプロジェクト フォルダー内に xxx.h というヘッダーファイルが存在します。

「Debug」フォルダー内には xxx.lib というライブラリファイルが存在します。

静的リンク ライブラリの使用

静的リンク ライブラリを使用することで、他のプログラムが簡単にコードを再利用できます。

使用方法 1

  1. xxx.h と xxx.lib を、静的リンク ライブラリを使用する .cpp ファイルのルート ディレクトリにコピーします。
  2. .cpp ファイル内に #include "xxx.h" を追加します。
  3. .cpp ファイル内に #pragma comment(lib, "xxx.lib") を追加します。

使用方法 2

  1. xxx.h と xxx.lib を、プロジェクトのルート ディレクトリにコピーします。
  2. .cpp ファイル内に #include "xxx.h" を追加します。
  3. プロジェクトの設定から「Link」タブを選択し、ライブラリ モジュールに TestLib.lib を追加します。

通常、printf 関数などはすでにこれらのライブラリがリンクされているため、直接使用できます。

静的リンク ライブラリの特徴

  • 利点:コードの再利用を実現します。
  • 欠点:生成される可執行ファイルのサイズが大きくなります。

静的リンク ライブラリは、コードを直接可執行ファイルに埋め込むため、モジュール化ではありません。

OD を使用して PE ファイルを確認すると、静的リンク ライブラリの関数は exe ファイル内部に存在します。

動的リンク ライブラリ

動的リンク ライブラリの作成

動的リンク ライブラリを使用して関数をエクスポートする方法は 2 種類あります。

名前指定でのエクスポート

  1. Win32 Dynamic-Link Library プロジェクトを作成します。
  2. クラス ビューから新規クラスを作成します。
  3. .cpp ファイル内に関数を定義します。
  4. .h ファイル内に extern "C" を使用して関数を宣言します。
  5. コンパイル後、DEPEND.exe を使用してDLLの関数を確認します。

定義ファイル (.def) を使用したエクスポート

  1. .def ファイルを作成します。
  2. 関数の番号を定義します。

この方法は関数名を隠すことができ、セキュリティが向上します。

動的リンク ライブラリの使用

明示的リンク


// DLL ファイルをプロジェクト ディレクトリにコピー
typedef int (*lpPlus)(int, int);
lpPlus myPlus = NULL;
HINSTANCE hDll = LoadLibrary("dllTest.dll");
myPlus = (lpPlus)GetProcAddress(hDll, "Plus");
int result = myPlus(10, 2);
FreeLibrary(hDll);

暗黙的リンク

  1. DLL ファイルと .lib ファイルをプロジェクト ディレクトリにコピーします。
  2. #pragma comment(lib, "xxx.lib") を追加します。
  3. 関数を宣言します。

この方法はコンパイル時にインポート表にDLLの情報を記録します。

DLL のリモート スレッド注入


#include <windows.h>
#include <iostream>

void DllInjector(DWORD pid, const wchar_t* dllPath) {
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    LPVOID allocAddr = VirtualAllocEx(hProcess, NULL, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    SIZE_T written = 0;
    WriteProcessMemory(hProcess, allocAddr, dllPath, (wcslen(dllPath) + 1) * 2, &written);
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryW, allocAddr, NULL, NULL);
    WaitForSingleObject(hThread, INFINITE);
    VirtualFreeEx(hProcess, allocAddr, 0, MEM_RELEASE);
    CloseHandle(hProcess);
    CloseHandle(hThread);
}

int main() {
    DllInjector(1234, L"C:\\example\\test.dll");
    return 0;
}

モジュールの列挙


#include <windows.h>
#include <tlhelp32.h>
#include <iostream>

void ListModules(DWORD processId) {
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processId);
    MODULEENTRY32 moduleEntry = { sizeof(MODULEENTRY32) };
    while (Module32Next(snapshot, &moduleEntry)) {
        std::wcout << "モジュール名: " << moduleEntry.szModule << std::endl;
        std::wcout << "パス: " << moduleEntry.szExePath << std::endl;
        std::wcout << "基底アドレス: 0x" << std::hex << moduleEntry.modBaseAddr << std::endl;
    }
    CloseHandle(snapshot);
}

int main() {
    ListModules(5678);
    return 0;
}

タグ: スタティック ライブラリ ダイナミック リンク ライブラリ DLL インジェクション PE ファイル解析

6月4日 22:29 投稿