private static bool ExecuteTLS(MEMORYMODULE module) { byte *codeBase = module.codeBase; IMAGE_TLS_DIRECTORY tls; void **callback; IMAGE_DATA_DIRECTORY *directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_TLS); if (directory->VirtualAddress == 0) { return(true); } tls = *(IMAGE_TLS_DIRECTORY *)((ulong)codeBase + directory->VirtualAddress); callback = (void **)tls.AddressOfCallBacks; if (callback != null) { while (*callback != null) { ((IMAGE_TLS_CALLBACK)Marshal.GetDelegateForFunctionPointer((IntPtr)(*callback), typeof(IMAGE_TLS_CALLBACK)))((void *)codeBase, DLL_PROCESS_ATTACH, null); callback++; } } return(true); }
/// <summary> /// Returns a delegate for a function inside the DLL. /// </summary> /// <param name="funcName">The Name of the function to be searched.</param> /// <param name="t">The type of the delegate to be returned.</param> /// <returns>A delegate instance that can be cast to the appropriate delegate type.</returns> public Delegate GetDelegateFromFuncName(int inputOrdinal, Type t) { if (t == null) { throw new ArgumentNullException("t"); } if (this.Disposed) { throw new ObjectDisposedException("MemoryModule"); } if (!this.initialized) { throw new InvalidOperationException("Dll is not initialized."); } int idx = -1; uint * nameRef; ushort *ordinal; IMAGE_EXPORT_DIRECTORY *exports; IntPtr funcPtr; IMAGE_DATA_DIRECTORY *directory = &this.headers->OptionalHeader.ExportTable; if (directory->Size == 0) { throw new NativeDllLoadException("Dll has no export table."); } exports = (IMAGE_EXPORT_DIRECTORY *)(this.codeBase + directory->VirtualAddress); if (exports->NumberOfFunctions == 0 || exports->NumberOfNames == 0) { throw new NativeDllLoadException("Dll exports no functions."); } nameRef = (uint *)(this.codeBase + exports->AddressOfNames); ordinal = (ushort *)(this.codeBase + exports->AddressOfNameOrdinals); ordinal += inputOrdinal; idx = *ordinal; /* * for (int i = 0; i < exports->NumberOfNames; i++, nameRef++, ordinal++) { * string curFuncName = Marshal.PtrToStringAnsi(new IntPtr(this.codeBase + *nameRef)); * if (curFuncName == funcName) { * idx = *ordinal; * break; * } * } */ if (idx > exports->NumberOfFunctions) { throw new NativeDllLoadException("IDX don't match number of funtions."); } funcPtr = new IntPtr(this.codeBase + (*(uint *)(this.codeBase + exports->AddressOfFunctions + (idx * 4)))); return(Marshal.GetDelegateForFunctionPointer(funcPtr, t)); }
public static void *MemoryFindResourceEx(MEMORYMODULE module, byte *name, byte *type, ushort language, bool unicode) { byte *codeBase = module.codeBase; IMAGE_DATA_DIRECTORY * directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_RESOURCE); IMAGE_RESOURCE_DIRECTORY * rootResources; IMAGE_RESOURCE_DIRECTORY * nameResources; IMAGE_RESOURCE_DIRECTORY * typeResources; IMAGE_RESOURCE_DIRECTORY_ENTRY *foundType; IMAGE_RESOURCE_DIRECTORY_ENTRY *foundName; IMAGE_RESOURCE_DIRECTORY_ENTRY *foundLanguage; if (directory->Size == 0) { // no resource table found return(null); } if (language == DEFAULT_LANGUAGE) { // use language from current thread language = LANGIDFROMLCID(GetThreadLocale()); } // resources are stored as three-level tree // - first node is the type // - second node is the name // - third node is the language rootResources = (IMAGE_RESOURCE_DIRECTORY *)(codeBase + directory->VirtualAddress); foundType = _MemorySearchResourceEntry(rootResources, rootResources, type, unicode); if (foundType == null) { return(null); } typeResources = (IMAGE_RESOURCE_DIRECTORY *)(codeBase + directory->VirtualAddress + (foundType->OffsetToData & 0x7fffffff)); foundName = _MemorySearchResourceEntry(rootResources, typeResources, name, unicode); if (foundName == null) { return(null); } nameResources = (IMAGE_RESOURCE_DIRECTORY *)(codeBase + directory->VirtualAddress + (foundName->OffsetToData & 0x7fffffff)); foundLanguage = _MemorySearchResourceEntry(rootResources, nameResources, (byte *)language, unicode); if (foundLanguage == null) { // requested language not found, use first available if (nameResources->NumberOfIdEntries == 0) { return(null); } foundLanguage = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(nameResources + 1); } return(codeBase + directory->VirtualAddress + (foundLanguage->OffsetToData & 0x7fffffff)); }
/// <summary> /// 获取数据目录 /// </summary> /// <param name="index"></param> /// <returns></returns> public IMAGE_DATA_DIRECTORY GetDirectory(IMAGE_DIRECTORY_ENTRY eEntryIndex) { fixed(int *pTemp = this.DataDirectory) { IMAGE_DATA_DIRECTORY *pDataDirectory = (IMAGE_DATA_DIRECTORY *)pTemp; pDataDirectory += (Int32)eEntryIndex; return(*pDataDirectory); } }
private static bool PerformBaseRelocation(MEMORYMODULE module, void *delta) { byte *codeBase = module.codeBase; IMAGE_BASE_RELOCATION *relocation; IMAGE_DATA_DIRECTORY *directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC); if (directory->Size == 0) { return(delta == null); } relocation = (IMAGE_BASE_RELOCATION *)((ulong)codeBase + directory->VirtualAddress); for (; relocation->VirtualAddress > 0;) { uint i; byte * dest = codeBase + relocation->VirtualAddress; ushort *relInfo = (ushort *)OffsetPointer(relocation, (void *)IMAGE_BASE_RELOCATION.UnmanagedSize); for (i = 0; i < ((relocation->SizeOfBlock - IMAGE_BASE_RELOCATION.UnmanagedSize) / 2); i++, relInfo++) { // the upper 4 bits define the type of relocation uint type = (uint)(*relInfo) >> 12; // the lower 12 bits define the offset uint offset = (uint)(*relInfo) & 0xfff; switch (type) { case IMAGE_REL_BASED_ABSOLUTE: // skip relocation break; case IMAGE_REL_BASED_HIGHLOW: // change complete 32 bit address uint *patchAddrHL = (uint *)(dest + offset); * patchAddrHL += (uint)delta; break; case IMAGE_REL_BASED_DIR64: if (WIN64) { ulong *patchAddr64 = (ulong *)(dest + offset); * patchAddr64 += (ulong)delta; } break; default: break; } } // advance to next relocation block relocation = (IMAGE_BASE_RELOCATION *)OffsetPointer(relocation, (void *)relocation->SizeOfBlock); } return(true); }
private void BuildImportTable() { IMAGE_DATA_DIRECTORY *directory = &this.headers->OptionalHeader.ImportTable; if (directory->Size > 0) { IMAGE_IMPORT_DESCRIPTOR *importDesc = (IMAGE_IMPORT_DESCRIPTOR *)(this.codeBase + directory->VirtualAddress); for (; !NativeDeclarations.IsBadReadPtr(new IntPtr(importDesc), (uint)Marshal.SizeOf(typeof(IMAGE_IMPORT_DESCRIPTOR))) && importDesc->Name > 0; importDesc++) { uint *thunkRef; int * funcRef; string funcName = Marshal.PtrToStringAnsi(new IntPtr(this.codeBase + importDesc->Name)); IntPtr handle = NativeDeclarations.LoadLibrary(funcName); if (handle == IntPtr.Zero) { throw new NativeDllLoadException("Can't load libary " + funcName); } this.modules.Add(handle); if (importDesc->OriginalFirstThunk > 0) { thunkRef = (uint *)(codeBase + importDesc->OriginalFirstThunk); funcRef = (int *)(codeBase + importDesc->FirstThunk); } else { // no hint table thunkRef = (uint *)(codeBase + importDesc->FirstThunk); funcRef = (int *)(codeBase + importDesc->FirstThunk); } for (; *thunkRef > 0; thunkRef++, funcRef++) { string procName; if (NativeDeclarations.IMAGE_SNAP_BY_ORDINAL32(*thunkRef)) { procName = Marshal.PtrToStringAnsi(new IntPtr(NativeDeclarations.IMAGE_ORDINAL32(*thunkRef))); *funcRef = (int)NativeDeclarations.GetProcAddress(handle, procName); } else { IMAGE_IMPORT_BY_NAME *thunkData = (IMAGE_IMPORT_BY_NAME *)(codeBase + (*thunkRef)); procName = Marshal.PtrToStringAnsi(new IntPtr(thunkData->Name)); *funcRef = (int)NativeDeclarations.GetProcAddress(handle, procName); } if (*funcRef == 0) { throw new NativeDllLoadException("Can't get adress for " + procName); } } } } }
private void PerformBaseRelocation(uint delta) { if (delta == 0) { return; } int imageSizeOfBaseRelocation = Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION)); IMAGE_DATA_DIRECTORY *directory = &this.headers->OptionalHeader.BaseRelocationTable; if (directory->Size > 0) { IMAGE_BASE_RELOCATION *relocation = (IMAGE_BASE_RELOCATION *)(this.codeBase + directory->VirtualAddress); while (relocation->VirtualAdress > 0) { byte * dest = this.codeBase + relocation->VirtualAdress; ushort *relInfo = (ushort *)((byte *)relocation + imageSizeOfBaseRelocation); for (int i = 0; i < ((relocation->SizeOfBlock - imageSizeOfBaseRelocation) / 2); i++, relInfo++) { uint *patchAddrHL; BasedRelocationType type; int offset; // the upper 4 bits define the type of relocation type = (BasedRelocationType)(*relInfo >> 12); // the lower 12 bits define the offset offset = *relInfo & 0xfff; switch (type) { case BasedRelocationType.IMAGE_REL_BASED_ABSOLUTE: break; case BasedRelocationType.IMAGE_REL_BASED_HIGHLOW: patchAddrHL = (uint *)(dest + offset); *patchAddrHL += delta; break; default: break; } } // advance to next relocation block relocation = (IMAGE_BASE_RELOCATION *)(((byte *)relocation) + relocation->SizeOfBlock); } } }
private void ExecuteTLS() { IMAGE_TLS_DIRECTORY *tlsDir; UIntPtrT * callbackPtr; ImageTlsDelegate tls; IMAGE_DATA_DIRECTORY *directory = &_headers->OptionalHeader.TLSTable; if (directory->VirtualAddress == 0) { return; } tlsDir = (IMAGE_TLS_DIRECTORY *)(_codeBase + directory->VirtualAddress); callbackPtr = (UIntPtrT *)tlsDir->AddressOfCallBacks; if (callbackPtr != null) { for (; *callbackPtr > 0; callbackPtr++) { tls = Marshal.GetDelegateForFunctionPointer <ImageTlsDelegate>((IntPtr)(*callbackPtr)); tls(_codeBase, DllReason.DLL_PROCESS_ATTACH, null); } } }
internal static void* MemoryGetProcAddress(MEMORYMODULE mod, byte* name) { MEMORYMODULE module = mod; byte* codeBase = module.codeBase; uint idx = 0; IMAGE_EXPORT_DIRECTORY* exports; IMAGE_DATA_DIRECTORY* directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_EXPORT); if (directory->Size == 0) // no export table found return null; exports = (IMAGE_EXPORT_DIRECTORY*)(codeBase + directory->VirtualAddress); if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) // DLL doesn't export anything return null; if (HIWORD(name) == 0) { // load function by ordinal value if (LOWORD(name) < exports->Base) return null; idx = LOWORD(name) - exports->Base; } else if (exports->NumberOfNames == 0) return null; else { ExportNameEntry found; // Lazily build name table and sort it by names if (module.nameExportsTable == null) { uint i; uint* nameRef = (uint*)(codeBase + exports->AddressOfNames); ushort* ordinal = (ushort*)(codeBase + exports->AddressOfNameOrdinals); ExportNameEntry[] entry = new ExportNameEntry[exports->NumberOfNames]; module.nameExportsTable = entry; for (i = 0; i < exports->NumberOfNames; i++, nameRef++, ordinal++) entry[i] = new ExportNameEntry { name = codeBase + (*nameRef), idx = *ordinal }; Array.Sort(module.nameExportsTable, _compare); } // search function name in list of exported names with binary search ExportNameEntry tmp = new ExportNameEntry { name = name }; int foundIndex = Array.BinarySearch(module.nameExportsTable, tmp, tmp); found = foundIndex < 0 ? null : module.nameExportsTable[foundIndex]; if (found == null) // exported symbol not found return null; idx = found.idx; } if (idx > exports->NumberOfFunctions) // name <. ordinal number don't match return null; // AddressOfFunctions contains the RVAs to the "real" functions return (void*)(codeBase + (*(uint*)(codeBase + exports->AddressOfFunctions + (idx * 4)))); }
private static bool BuildImportTable(MEMORYMODULE module) { byte* codeBase = module.codeBase; IMAGE_IMPORT_DESCRIPTOR* importDesc; bool result = true; IMAGE_DATA_DIRECTORY* directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT); if (directory->Size == 0) { return true; } importDesc = (IMAGE_IMPORT_DESCRIPTOR*)(codeBase + directory->VirtualAddress); for (; !IsBadReadPtr(importDesc, (void*)IMAGE_IMPORT_DESCRIPTOR.UnmanagedSize) && importDesc->Name != 0; importDesc++) { void** thunkRef; void** funcRef; void** tmp; void* handle = module.loadLibrary(codeBase + importDesc->Name, module.userdata); if (handle == null) { result = false; break; } tmp = (void**)realloc(module.modules, (void*)((module.numModules + 1) * sizeof(void*))); if (tmp == null) { module.freeLibrary(handle, module.userdata); result = false; break; } module.modules = tmp; module.modules[module.numModules++] = handle; if (importDesc->OriginalFirstThunk != 0) { thunkRef = (void**)(codeBase + importDesc->OriginalFirstThunk); funcRef = (void**)(codeBase + importDesc->FirstThunk); } else { // no hint table thunkRef = (void**)(codeBase + importDesc->FirstThunk); funcRef = (void**)(codeBase + importDesc->FirstThunk); } for (; *thunkRef != null; thunkRef++, funcRef++) { if (IMAGE_SNAP_BY_ORDINAL(*thunkRef)) { *funcRef = module.getProcAddress(handle, (byte*)IMAGE_ORDINAL(*thunkRef), module.userdata); } else { IMAGE_IMPORT_BY_NAME* thunkData = (IMAGE_IMPORT_BY_NAME*)(codeBase + (ulong)(*thunkRef)); *funcRef = module.getProcAddress(handle, thunkData->Name, module.userdata); } if (*funcRef == null) { result = false; break; } } if (!result) { module.freeLibrary(handle, module.userdata); break; } } return result; }
public static unsafe List <uint> GetStaticImportNameOffsets(byte[] fileBytes, string arch) { // This function walks the PE header to get the offset of the Import Address Table // (IAT) and then resolves the imports' names fixed(byte *ptr_data = fileBytes) { // Initial validation UnsafeHelpers.IMAGE_DOS_HEADER *dos_header = (UnsafeHelpers.IMAGE_DOS_HEADER *)ptr_data; if (dos_header->e_magic != UnsafeHelpers.IMAGE_DOS_SIGNATURE) { Console.WriteLine("[-] Magic bytes don't match"); return(null); } // We'll split here because much of the work we need to do uses offsets from the NT headers if (arch == "x64") { UnsafeHelpers.IMAGE_NT_HEADERS64 *nt_header = (UnsafeHelpers.IMAGE_NT_HEADERS64 *)(ptr_data + dos_header->e_lfanew); if (nt_header->Signature != UnsafeHelpers.IMAGE_NT_SIGNATURE) { Console.WriteLine("[-] NT Header signature mismatch"); return(null); } IMAGE_DATA_DIRECTORY *DataDirectory = (IMAGE_DATA_DIRECTORY *)(&nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]); // Safety check in case others fail. This will happen on x86 EXEs and some .NET assemblies. uint itRVA = DataDirectory->VirtualAddress; if (itRVA == 0) { Console.WriteLine("[!] Import Table RVA is 0. Something is wrong..."); return(null); } // Do the conversion from the RVA to the offsets we'll need to do some math Offset iatOffsets = RvaToOffset(nt_header, null, itRVA, "IAT"); // Math to get the true offset to the name of the DLL // https://ired.team/miscellaneous-reversing-forensics/pe-file-header-parser-in-c++#pimage_import_descriptor uint offset = iatOffsets.RawOffset + (itRVA - iatOffsets.RVA); UnsafeHelpers.IMAGE_IMPORT_DESCRIPTOR *firstModule = (UnsafeHelpers.IMAGE_IMPORT_DESCRIPTOR *)(ptr_data + offset); List <uint> nameOffsets = new List <uint>(); while (firstModule->Name != 0) { uint trueOffset = 0 + iatOffsets.RawOffset + (firstModule->Name - iatOffsets.RVA); nameOffsets.Add(trueOffset); firstModule++; } return(nameOffsets); } else // x86 { UnsafeHelpers.IMAGE_NT_HEADERS32 *nt_header = (UnsafeHelpers.IMAGE_NT_HEADERS32 *)(ptr_data + dos_header->e_lfanew); if (nt_header->Signature != UnsafeHelpers.IMAGE_NT_SIGNATURE) { Console.WriteLine("[-] NT Header signature mismatch"); return(null); } UnsafeHelpers.IMAGE_DATA_DIRECTORY *DataDirectory = (UnsafeHelpers.IMAGE_DATA_DIRECTORY *)(&nt_header->OptionalHeader.DataDirectory[UnsafeHelpers.IMAGE_DIRECTORY_ENTRY_IMPORT]); // Safety check in case others fail. This will happen on x86 EXEs and some .NET assemblies. uint itRVA = DataDirectory->VirtualAddress; if (itRVA == 0) { Console.WriteLine("[!] Import Table RVA is 0. Something is wrong..."); return(null); } // Do the conversion from the RVA to the offsets we'll need to do some math Offset iatOffsets = RvaToOffset(null, nt_header, itRVA, "IAT"); // Math to get the true offset to the name of the DLL // https://ired.team/miscellaneous-reversing-forensics/pe-file-header-parser-in-c++#pimage_import_descriptor uint offset = iatOffsets.RawOffset + (itRVA - iatOffsets.RVA); UnsafeHelpers.IMAGE_IMPORT_DESCRIPTOR *firstModule = (UnsafeHelpers.IMAGE_IMPORT_DESCRIPTOR *)(ptr_data + offset); //uint nameOffset = 0 + rdataRawOffset + (firstModule->Name - rdataRVA); List <uint> nameOffsets = new List <uint>(); while (firstModule->Name != 0) { uint trueOffset = 0 + iatOffsets.RawOffset + (firstModule->Name - iatOffsets.RVA); nameOffsets.Add(trueOffset); firstModule++; } return(nameOffsets); } } }
public static unsafe List <string> GetDynamicImports(byte[] fileBytes, string arch) { // This function walks the PE header to get the offset of the Delay-Load Descriptor Table // (DLDT) and then resolves the imports' names List <string> dynamicModuleNames = new List <string>(); fixed(byte *ptr_data = fileBytes) { // Initial validation UnsafeHelpers.IMAGE_DOS_HEADER *dos_header = (UnsafeHelpers.IMAGE_DOS_HEADER *)ptr_data; if (dos_header->e_magic != UnsafeHelpers.IMAGE_DOS_SIGNATURE) { Console.WriteLine("[-] Magic bytes don't match"); return(dynamicModuleNames); } // Get the NT headers if (arch == "x64") { IMAGE_NT_HEADERS64 *nt_header = (IMAGE_NT_HEADERS64 *)(ptr_data + dos_header->e_lfanew); if (nt_header->Signature != IMAGE_NT_SIGNATURE) { Console.WriteLine("[-] NT Header signature mismatch"); return(dynamicModuleNames); } // Get the offset for the delay-load import tables ulong *DataDirectory = nt_header->OptionalHeader.DataDirectory; IMAGE_DATA_DIRECTORY *dldt = (IMAGE_DATA_DIRECTORY *)(&nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]); uint dldtRVA = dldt->VirtualAddress; if (dldtRVA == 0) // No delayed imports found { return(dynamicModuleNames); } Offset offsets = RvaToOffset(nt_header, null, dldtRVA, "DLDT"); uint offset = offsets.RawOffset + (dldtRVA - offsets.RVA); // Iterate over the list of delay-loaded modules IMAGE_DELAY_IMPORT_DESCRIPTOR *firstModule = (UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR *)(ptr_data + offset); while (firstModule->szName != 0) { Offset offsetToNames = RvaToOffset(nt_header, null, firstModule->szName, "szName"); uint offset2 = offsetToNames.RawOffset + (firstModule->szName - offsetToNames.RVA); dynamicModuleNames.Add(Marshal.PtrToStringAnsi((IntPtr)(ptr_data + offset2))); firstModule = (UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR *)((long)firstModule + (long)Marshal.SizeOf(typeof(UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR))); } } else // x86 { IMAGE_NT_HEADERS32 *nt_header = (IMAGE_NT_HEADERS32 *)(ptr_data + dos_header->e_lfanew); if (nt_header->Signature != IMAGE_NT_SIGNATURE) { Console.WriteLine("[-] NT Header signature mismatch"); return(dynamicModuleNames); } // Get the offset for the delay-load import tables ulong *DataDirectory = nt_header->OptionalHeader.DataDirectory; IMAGE_DATA_DIRECTORY *dldt = (IMAGE_DATA_DIRECTORY *)(&nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]); uint dldtRVA = dldt->VirtualAddress; if (dldtRVA == 0) // No delayed imports found { return(dynamicModuleNames); } Offset offsets = RvaToOffset(null, nt_header, dldtRVA, "DLDT"); uint offset = offsets.RawOffset + (dldtRVA - offsets.RVA); // Iterate over the list of delay-loaded modules IMAGE_DELAY_IMPORT_DESCRIPTOR *firstModule = (IMAGE_DELAY_IMPORT_DESCRIPTOR *)(ptr_data + offset); while (firstModule->szName != 0) { Offset offsetToNames = RvaToOffset(null, nt_header, firstModule->szName, "szName"); uint offset2 = offsetToNames.RawOffset + (firstModule->szName - offsetToNames.RVA); dynamicModuleNames.Add(Marshal.PtrToStringAnsi((IntPtr)(ptr_data + offset2))); firstModule = (IMAGE_DELAY_IMPORT_DESCRIPTOR *)((long)firstModule + (long)Marshal.SizeOf(typeof(UnsafeHelpers.IMAGE_DELAY_IMPORT_DESCRIPTOR))); } } return(dynamicModuleNames); } }
private void BuildImportTable() { IMAGE_DATA_DIRECTORY *directory = &_headers->OptionalHeader.ImportTable; if (directory->Size == 0) { throw new NativeDllLoadException("Invalid import table."); } IMAGE_IMPORT_DESCRIPTOR *importDesc = (IMAGE_IMPORT_DESCRIPTOR *)(_codeBase + directory->VirtualAddress); for (; !Win.IsBadReadPtr((importDesc), (UIntPtrT)Marshal.SizeOf(typeof(IMAGE_IMPORT_DESCRIPTOR))) && importDesc->Name > 0; importDesc++) { UIntPtrT *thunkRef; Farproc * funcRef; HCoustomMudule handle = Win.LoadLibrary(_codeBase + importDesc->Name); if (InvalidHandle(handle)) { if (_modules.Any()) { _modules.ForEach(m => Win.FreeLibrary(m)); } throw new NativeDllLoadException("Can't load libary " + Marshal.PtrToStringAnsi(new IntPtr(_codeBase + importDesc->Name))); } _modules.Add(handle); if (importDesc->OriginalFirstThunk > 0) { thunkRef = (UIntPtrT *)(_codeBase + importDesc->OriginalFirstThunk); funcRef = (Farproc *)(_codeBase + importDesc->FirstThunk); } else { // no hint table thunkRef = (UIntPtrT *)(_codeBase + importDesc->FirstThunk); funcRef = (Farproc *)(_codeBase + importDesc->FirstThunk); } for (; *thunkRef > 0; thunkRef++, funcRef++) { string procName; if (Win.IMAGE_SNAP_BY_ORDINAL(*thunkRef)) { procName = Marshal.PtrToStringAnsi(new IntPtr()); *funcRef = (Farproc)Win.GetProcAddress(handle, (byte *)Win.IMAGE_ORDINAL(*thunkRef)); } else { IMAGE_IMPORT_BY_NAME *thunkData = (IMAGE_IMPORT_BY_NAME *)(_codeBase + (*thunkRef)); *funcRef = (Farproc)Win.GetProcAddress(handle, thunkData->Name); } if (*funcRef == 0) { throw new NativeDllLoadException("Can't get adress for imported function."); } } } }
private void *GetPtrFromFuncName(string funcName) { if (Disposed) { throw new InvalidOperationException("Object disposed"); } if (!IsDll) { throw new InvalidOperationException("Loaded Module is not a DLL"); } if (string.IsNullOrEmpty(funcName)) { throw new ArgumentException("funcName"); } if (Disposed) { throw new ObjectDisposedException("MemoryModule"); } if (!_initialized) { throw new InvalidOperationException("Dll is not initialized."); } int idx = -1; uint * nameRef; ushort *ordinal; IMAGE_EXPORT_DIRECTORY * exports; Dictionary <string, int> exportEntrys = new Dictionary <string, int>(); IMAGE_DATA_DIRECTORY *directory = &_headers->OptionalHeader.ExportTable; if (directory->Size == 0) { throw new NativeDllLoadException("Dll has no export table."); } exports = (IMAGE_EXPORT_DIRECTORY *)(_codeBase + directory->VirtualAddress); if (exports->NumberOfFunctions == 0 || exports->NumberOfNames == 0) { throw new NativeDllLoadException("Dll exports no functions."); } nameRef = (uint *)(_codeBase + exports->AddressOfNames); ordinal = (ushort *)(_codeBase + exports->AddressOfNameOrdinals); for (int i = 0; i < exports->NumberOfNames; i++, nameRef++, ordinal++) { string curFuncName = Marshal.PtrToStringAnsi((IntPtr)(_codeBase + *nameRef)); exportEntrys.Add(curFuncName, *ordinal); } if (!exportEntrys.Keys.Contains(funcName)) { throw new NativeDllLoadException("Dll exports no function named " + funcName); } idx = exportEntrys[funcName]; if (idx > exports->NumberOfFunctions) { throw new NativeDllLoadException("IDX don't match number of funtions."); } return(_codeBase + (*(uint *)(_codeBase + exports->AddressOfFunctions + (idx * 4)))); }