/// <summary> /// Retrieves the address of an exported function or variable from loaded module. /// </summary> /// <param name="procName">The function or variable name.</param> /// <returns> /// If the function succeeds, the return value is the address of the exported function or variable. /// If the function fails, the return value is IntPtr.Zero. /// </returns> private IntPtr GetProcAddress(string procName) { if (_loadedModuleHandle == IntPtr.Zero) { return(IntPtr.Zero); } if (!_loadedFromMemory) { return(WinBase.GetProcAddress(_loadedModuleHandle, procName)); } MEMORY_MODULE *memory_module = (MEMORY_MODULE *)_loadedModuleHandle; byte *codeBase = memory_module->codeBase; int idx = -1; uint i; uint * nameRef; ushort *ordinal; WinNT.IMAGE_DATA_DIRECTORY *directory = this.GET_HEADER_DIRECTORY(memory_module, WinNT.IMAGE_DIRECTORY_ENTRY_EXPORT); if (directory->Size == 0) { // no export table found return(IntPtr.Zero); } WinNT.IMAGE_EXPORT_DIRECTORY *exports = (WinNT.IMAGE_EXPORT_DIRECTORY *)(codeBase + directory->VirtualAddress); if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) { // DLL doesn't export anything return(IntPtr.Zero); } // search function name in list of exported names nameRef = (uint *)(codeBase + exports->AddressOfNames); ordinal = (ushort *)(codeBase + exports->AddressOfNameOrdinals); for (i = 0; i < exports->NumberOfNames; i++, nameRef++, ordinal++) { IntPtr procNameHandle = (IntPtr)((byte *)((ulong)codeBase + *nameRef)); string testProcName = Marshal.PtrToStringAnsi(procNameHandle); if (testProcName == procName) { idx = *ordinal; break; } } if (idx == -1) { // exported symbol not found return(IntPtr.Zero); } if ((uint)idx > exports->NumberOfFunctions) { // name <-> ordinal number don't match return(IntPtr.Zero); } // AddressOfFunctions contains the RVAs to the "real" functions //return (IntPtr)((uint)codeBase + *(uint*)((uint)codeBase + exports->AddressOfFunctions + (idx * 4))); return((IntPtr)(codeBase + *(uint *)(codeBase + exports->AddressOfFunctions + (idx * 4)))); }
/// <summary> /// Loads required dlls and adjust function table of the imports. /// </summary> /// <param name="memory_module">Pointer to a memory module.</param> /// <returns>If the function succeeds, the return value is true.</returns> private bool BuildImportTable(MEMORY_MODULE *memory_module) { bool result = true; WinNT.IMAGE_DATA_DIRECTORY *directory = this.GET_HEADER_DIRECTORY(memory_module, WinNT.IMAGE_DIRECTORY_ENTRY_IMPORT); if (directory->Size > 0) { WinNT.IMAGE_IMPORT_DESCRIPTOR *importDesc = (WinNT.IMAGE_IMPORT_DESCRIPTOR *)(memory_module->codeBase + directory->VirtualAddress); for (; importDesc->Name != 0; importDesc++) { IntPtr *thunkRef; IntPtr *funcRef; string moduleName = Marshal.PtrToStringAnsi((IntPtr)(memory_module->codeBase + importDesc->Name)); IntPtr handle = WinBase.LoadLibrary(moduleName); if (handle == IntPtr.Zero) { result = false; break; } int size_of_pointer = sizeof(IntPtr); memory_module->modules = (IntPtr *)memory.realloc((byte *)memory_module->modules, (uint)((memory_module->numModules) * size_of_pointer), (uint)((memory_module->numModules + 1) * size_of_pointer)); if (memory_module->modules == null) { result = false; break; } memory_module->modules[memory_module->numModules++] = handle; if (importDesc->Characteristics != 0) { thunkRef = (IntPtr *)(memory_module->codeBase + importDesc->Characteristics); funcRef = (IntPtr *)(memory_module->codeBase + importDesc->FirstThunk); } else { thunkRef = (IntPtr *)(memory_module->codeBase + importDesc->FirstThunk); funcRef = (IntPtr *)(memory_module->codeBase + importDesc->FirstThunk); } for (; *thunkRef != IntPtr.Zero; thunkRef++, funcRef++) { if (WinNT.IMAGE_SNAP_BY_ORDINAL(thunkRef)) { *funcRef = WinBase.GetProcAddress(handle, (byte *)WinNT.IMAGE_ORDINAL(thunkRef)); } else { WinNT.IMAGE_IMPORT_BY_NAME *thunkData = (WinNT.IMAGE_IMPORT_BY_NAME *)(memory_module->codeBase + (ulong)*thunkRef); //string procName = Marshal.PtrToStringAnsi((IntPtr)(byte*)(thunkData) + 2); IntPtr a = (IntPtr)(byte *)(thunkData); string procName = Marshal.PtrToStringAnsi(new IntPtr(a.ToInt64() + 2)); * funcRef = WinBase.GetProcAddress(handle, procName); } if (*funcRef == IntPtr.Zero) { result = false; break; } } if (!result) { break; } } } return(result); }