void CopySections(byte[] data, IMAGE_NT_HEADERS32 *ntHeader) { if (data == null) { throw new ArgumentNullException("data"); } if (ntHeader->Signature != NativeDeclarations.IMAGE_NT_SIGNATURE) { throw new BadImageFormatException("Inavlid PE-Header"); } uint size; int *dest; IMAGE_SECTION_HEADER *section = NativeDeclarations.IMAGE_FIRST_SECTION(this.headers); for (int i = 0; i < this.headers->FileHeader.NumberOfSections; i++, section++) { if (section->SizeOfRawData == 0) { // section doesn't contain data in the dll itself, but may define // uninitialized data size = ntHeader->OptionalHeader.SectionAlignment; if (size > 0) { dest = (int *)NativeDeclarations.VirtualAlloc( new IntPtr(this.codeBase + section->VirtualAddress), size, AllocationType.COMMIT, MemoryProtection.READWRITE).ToPointer(); section->PhysicalAddress = (uint)dest; NativeDeclarations.MemSet(new IntPtr(dest), 0, new IntPtr(size)); } continue; } dest = (int *)NativeDeclarations.VirtualAlloc( new IntPtr((int)this.codeBase + section->VirtualAddress), section->SizeOfRawData, AllocationType.COMMIT, MemoryProtection.READWRITE).ToPointer(); Marshal.Copy(data, (int)section->PointerToRawData, new IntPtr(dest), (int)section->SizeOfRawData); section->PhysicalAddress = (uint)dest; } }
private void MemoryLoadLibrary(byte[] data) { IMAGE_DOS_HEADER32 *dosHeader; IMAGE_NT_HEADERS32 *ntHeader; IntPtr dllEntryPtr; byte * code, headers, dataPtr; uint locationDelta; this.dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); dataPtr = (byte *)this.dataHandle.AddrOfPinnedObject().ToPointer(); dosHeader = (IMAGE_DOS_HEADER32 *)dataPtr; if (dosHeader->e_magic != NativeDeclarations.IMAGE_DOS_SIGNATURE) { throw new BadImageFormatException("Not a valid executable file."); } ntHeader = (IMAGE_NT_HEADERS32 *)(dataPtr + dosHeader->e_lfanew); if (ntHeader->Signature != NativeDeclarations.IMAGE_NT_SIGNATURE) { throw new BadImageFormatException("Not a valid PE file."); } code = (byte *)NativeDeclarations.VirtualAlloc( new IntPtr(ntHeader->OptionalHeader.ImageBase), ntHeader->OptionalHeader.SizeOfImage, AllocationType.RESERVE, MemoryProtection.READWRITE).ToPointer(); if (code == null) { code = (byte *)NativeDeclarations.VirtualAlloc( IntPtr.Zero, ntHeader->OptionalHeader.SizeOfImage, AllocationType.RESERVE, MemoryProtection.READWRITE).ToPointer(); } if (code == null) { throw new Win32Exception(); } NativeDeclarations.VirtualAlloc( new IntPtr(code), ntHeader->OptionalHeader.SizeOfImage, AllocationType.COMMIT, MemoryProtection.READWRITE); this.codeBase = code; headers = (byte *)NativeDeclarations.VirtualAlloc( new IntPtr(code), ntHeader->OptionalHeader.SizeOfHeaders, AllocationType.COMMIT, MemoryProtection.READWRITE).ToPointer(); if (headers == null) { throw new Win32Exception(); } Marshal.Copy(data, 0, new IntPtr(headers), (int)(dosHeader->e_lfanew + ntHeader->OptionalHeader.SizeOfHeaders)); this.headers = (IMAGE_NT_HEADERS32 *)&((byte *)(headers))[dosHeader->e_lfanew]; this.headers->OptionalHeader.ImageBase = (uint)code; this.CopySections(data, ntHeader); locationDelta = (uint)(code - ntHeader->OptionalHeader.ImageBase); if (locationDelta != 0) { PerformBaseRelocation(locationDelta); } this.BuildImportTable(); this.FinalizeSections(); if (this.headers->OptionalHeader.AddressOfEntryPoint == 0) { throw new NativeDllLoadException("DLL has no entry point"); } dllEntryPtr = new IntPtr(code + this.headers->OptionalHeader.AddressOfEntryPoint); this.dllEntry = (DllEntryDelegate)Marshal.GetDelegateForFunctionPointer(dllEntryPtr, typeof(DllEntryDelegate)); if (dllEntry(new IntPtr(code), DllReason.DLL_PROCESS_ATTACH, IntPtr.Zero)) { this.initialized = true; } else { this.initialized = false; throw new NativeDllLoadException("Can't attach DLL to process."); } }