1

特定のプロセスが使用している DLL のリストを取得しようとしています。VirtualQueryEx を使用してそれを達成しようとしています。私の問題は、DLL のすべてではなく部分的なリストだけが返されることです (プロセス エクスプローラーを使用するか、指定されたプロセスで VirtualQuery を使用してリストを表示できます)。

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

    char szBuf[MAX_PATH * 100] = { 0 };
    PBYTE pb = NULL;
    MEMORY_BASIC_INFORMATION mbi;
    HANDLE h_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, iPID);


    while (VirtualQueryEx(h_process, pb, &mbi, sizeof(mbi)) == sizeof(mbi)) {

        int nLen;
        char szModName[MAX_PATH];

        if (mbi.State == MEM_FREE)
        mbi.AllocationBase = mbi.BaseAddress;

        if ((mbi.AllocationBase == hInstDll) ||
            (mbi.AllocationBase != mbi.BaseAddress) ||
            (mbi.AllocationBase == NULL)) {
        // Do not add the module name to the list
        // if any of the following is true:
        // 1. If this region contains this DLL
        // 2. If this block is NOT the beginning of a region
        // 3. If the address is NULL
        nLen = 0;
        } else {
        nLen = GetModuleFileNameA((HINSTANCE) mbi.AllocationBase, 
            szModName, _countof(szModName));
        }

        if (nLen > 0) {
        wsprintfA(strchr(szBuf, 0), "\n%p-%s", 
            mbi.AllocationBase, szModName);
        }

        pb += mbi.RegionSize;
    }

で結果を取得していszBufます。

この関数は DLL ファイルの一部であるため、デバッグが困難です。

現在、DLL は x64 バイナリとしてコンパイルされており、x64 プロセスに対して使用しています。

PS私はEnumProcessModulesについて知っていますが、理由でそれを使用していません(長すぎます:)。

4

1 に答える 1

1

GetModuleFileName() は、他のプロセスではなく、プロセスにロードされたモジュールの名前のみを提供します。Windows オペレーティング システムの DLL が同じアドレスに読み込まれるため、同じモジュール ハンドル値を持つことになります。

プロセス ハンドルを渡すことができるように、GetModuleFileNameEx() を使用する必要があります。

投稿されたコードの根本的な欠陥に注意してください。別のプロセスで VirtualQueryEx() を安全に使用できるようにするために何もしていません。これには、すべてのスレッドを一時停止して、反復中にメモリを割り当てることができないようにする必要があります。これは、デバッガーが行うようなことです。EnumProcessModules にも必要です。障害モードは厄介で、ランダムであり、同じアドレスを何度も繰り返して、簡単にループがスタックする可能性があります。これが、「スナップショット」に重点を置いた CreateToolHelp32Snapshot() 関数が存在する理由です。

于 2012-12-26T15:33:44.140 に答える