1

PE イメージから関数アドレスを適切に取得し、その関数をデリゲートで呼び出す方法を誰かに説明してもらえますか? DLLライブラリからエクスポートをロードする良いコードをグーグルで見つけましたが、それは関数名しか取得しません...したがって、次のように変更しました:

[DllImport("ImageHlp", CallingConvention = CallingConvention.Winapi), SuppressUnmanagedCodeSecurity]
public static extern bool MapAndLoad(string imageName, string dllPath, out LOADED_IMAGE loadedImage, bool dotDll, bool readOnly);

public static IntPtr CustomGetProcAddress(string modulePath, string moduleProc)
{
    LOADED_IMAGE loadedImage;

    if (MapAndLoad(modulePath, null, out loadedImage, true, true))
        return GetAddr(loadedImage, moduleProc);
    else
        return IntPtr.Zero;
}

private static IntPtr GetAddr(LOADED_IMAGE loadedImage, string moduleProc)
{
    var hMod = (void*)loadedImage.MappedAddress;

    if (hMod != null)
    {
        uint size;
        var pExportDir = (IMAGE_EXPORT_DIRECTORY*)ImageDirectoryEntryToData(
            (void*)loadedImage.MappedAddress,
            false,
            IMAGE_DIRECTORY_ENTRY_EXPORT,
            out size);

        uint* pFuncNames = (uint*)RvaToVa(loadedImage, pExportDir->AddressOfNames);
        ushort* pFuncOrdinals = (ushort*)RvaToVa(loadedImage, pExportDir->AddressOfNameOrdinals);
        uint* pFuncAddr = (uint*)RvaToVa(loadedImage, pExportDir->AddressOfFunctions);

        for (uint i = 0; i < pExportDir->NumberOfNames; i++)
        {
            uint funcNameRva = pFuncNames[i];

            if (funcNameRva != 0)
            {
                char* funcName = (char*)RvaToVa(loadedImage, funcNameRva);
                string name = Marshal.PtrToStringAnsi((IntPtr)funcName);
                _exports.Add(name);

                if (name == wantedFunction)
                    return addr = new IntPtr(*(uint*)(pFuncAddr + (*pFuncOrdinals * 4)));
            }
        }
    }

    return IntPtr.Zero;
}

私は解決策に近いと確信しています...しかし、私は常に AccessViolationException (間違ったポインターを使用した場合) または InvalidFunctionPointerInDelegate と PInvokeStackImbalance (Marshal.GetDelegateForFunctionPointer を使用してポインターをデリゲートにキャストしてから実行しようとした場合) を取得します。 )。すべてを試しましたが、うまくいきません (LoadLibrary と GetProcAddress を使用して、探している関数の正しいアドレスを既に引き出したので、結果を比較できますが、それらを使用したくありません)。機能)。

[編集] 別の例を見つけましたが、探していることができるかどうかはわかりません: http://www.rohitab.com/discuss/topic/39366-c-loadlibary-from-byte/page_ k _bb2fe024f8a71424996db6d9af08c1fc_settingNewSkin_19 _ _

4

2 に答える 2

1

そんなことはできません。ライブラリのMapAndLoadand 関数はImageHlp、PE ファイルをデータ ファイルとしてメモリにロードするだけなので、それを調べることができます。DLL をロードして実行可能にする (RVA フィックスアップなど) ときに、Windows ローダーのすべてのロジックを実行するわけではありません。

DLL をロードし、名前で関数を検索し、その関数への呼び出し可能なポインターを取得する場合は、 and を使用LoadLibraryGetProcAddressます。これらの機能は、あなたがしようとしていることを正確に行うように設計されています。

于 2013-01-01T18:04:07.797 に答える
0

前に述べたように、MapAndLoad関数はファイルをデータとしてロードするだけです。ロード先のメモリ ページは実行可能ではないため、このメモリ内の場所にジャンプしようとしても、ほぼ確実に機能しません。を使用して回避したい場合は、かなり複雑な方法が必要になりますLoadLibraryが、最初のステップは、PE ファイルの実行可能セクションが実行可能メモリにロードされていることを確認することです (その後、PE ファイルの他のすべての機能を実装します)。 Windows ローダー!) 私はこれを試みたことはありませんが、簡単な検索でわかることから、Windows DEP (データ実行防止) などの問題を回避することに関連する多くの問題があります。

于 2013-02-10T02:45:19.550 に答える