1

dliNotePreLoadLibrary実際に読み込む前に、読み込まれる DLL のコード署名を検証するために、独自の遅延読み込みフックを使用しています。コードが実行されるのを避けるために、フックLoadLibraryExA(...,...,LOAD_LIBRARY_AS_DATAFILE)はANSI名のみを提供するので問題ありません)を使用してロードし、検証後にアンロードして、コード付きのDLLとしてロードできるようにします。

デバッガーでコードをステップ実行すると、ハンドルを受け取り、そのハンドルが<baseaddress>+1"データ モジュール" に期待されるものであることがわかります。ただし、このハンドルをライブラリ関数内に渡そうとするとGetModuleFileName(これが、名前を渡すことができず、モジュール ハンドルのみを渡すことができない理由でもあります)、関数が戻り0、GetLastError が返されますERROR_MOD_NOT_FOUND。しかし、モジュールはロードされたので、確実に見つかりました。また、これは現在のプロセスにあるため、「対象プロセス」へのアクセスはここでは問題ありません。

そのため、ロードしたばかりの DLLVirtualQueryの実際のベース アドレス ( ) を取得するために使用しない理由を考えましたが (これが問題の場合)、結果は同じままです: .MEMORY_BASIC_INFORMATION::BaseAddress<baseaddress>+1ERROR_MOD_NOT_FOUND

私はアイデアがありません。ここで何が起こっているのか誰にも考えがありますか?

テストのプラットフォーム: Windows 7 SP1、x64 (最新のパッチ)

のコードは次のとおりです。

FARPROC WINAPI MyDliHook(unsigned dliNotify, PDelayLoadInfo pdli)
{
    switch(dliNotify)
    {
    case dliNotePreLoadLibrary:
        if(0 == lstrcmpiA(pdli->szDll, "DLLNAME.dll"))
        {
            HMODULE hVerifiedDll = LoadLibraryExA(pdli->szDll, NULL, LOAD_LIBRARY_AS_DATAFILE);
            if(hVerifiedDll)
            {
                MEMORY_BASIC_INFORMATION mbi;
                if(0 != VirtualQuery(hVerifiedDll, &mbi, sizeof(mbi)));
                {
                    VerifyModuleSignature((HMODULE)mbi.BaseAddress, pdli->szDll);
                }
                FreeLibrary(hVerifiedDll);
            }
        }
        break;
    default:
        break;
    }
    return NULL;
}
PfnDliHook __pfnDliNotifyHook2 = MyDliHook;

この関数VerifyModuleSignatureは、最初にGetModuleFileNameファイル名を取得するために呼び出しますが、その段階で失敗します。.exeプロセスを作成する で、コード署名の検証が正常に機能することを確認しました。

補足:ERROR_MOD_NOT_FOUNDエラーの原因GetModuleFileNameLoadLibraryExA. 「汚染された」最後のエラーコードを取得しないようにするためにSetLastError(ERROR_SUCCESS)、 への呼び出しの直前に呼び出しましたGetModuleFileName

4

1 に答える 1

3

MSDNで説明されているように、LOAD_LIBRARY_AS_DATAFILE が使用されている場合、GetModuleHandle を使用してモジュールを取得することはできません。

この値が使用される場合、システムはファイルをデータ ファイルであるかのように、呼び出しプロセスの仮想アドレス空間にマップします。マップされたファイルの実行または実行の準備は何も行われません。したがって、この DLL で GetModuleFileName、GetModuleHandle、GetProcAddress などの関数を呼び出すことはできません。

編集:実際、Hans Passant は、この回答よりも理由に少し近かったです。この回答はMSが述べていることを繰り返していますが、理由はありません。ただし、その理由は、GetModuleFileName基本的にのLDR_MODULEリストをたどり、 PEB「コードをロード」したときにのみ詳細が入力されるためです。

于 2012-08-21T06:56:37.627 に答える