任何人都可以解释我如何从PE映像中正确获取函数地址,然后使用委托调用该函数? 我找到了一个好一块代码google搜索周围的负载从一个DLL库出口,但只得到函数名出来的......所以我修改,如下所示:用PE导出表解决函数地址
[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
这就是问题所在......我不想使用GetProcAddress和LoadLibrary。我知道使用它很容易找到一个名称的函数地址......但这不是我正在寻找的。我看到很多C/C++程序正在这样做,但我无法在.NET中重现它...有其他选择吗?像mh ...从内存中读取DLL? –
@Zarathos - 然后你必须重新编写Windows加载器加载DLL时所做的所有逻辑 - 祝你好运。我不知道为什么你不喜欢使用LoadLibrary/GetProcAddress(他们在.NET中工作正常 - 我自己使用它们)。如果这是一次学习经历,那么请自己解决;如果这是生产代码,则使用LoadLibrary/GetProcAddress。 – shf301