private void FinalizeSections64(IntPtr codeBase, IntPtr headers, IMAGE_DOS_HEADER dosHeader, IMAGE_NT_HEADERS64 header64) { var section = headers.ToStruct<IMAGE_SECTION_HEADER>((uint)(24 + dosHeader.e_lfanew + header64.FileHeader.SizeOfOptionalHeader)); for (int i = 0; i < header64.FileHeader.NumberOfSections; i++) { //Console.WriteLine("Finalize section " + Encoding.UTF8.GetString(section.Name)); if ((section.Characteristics & 0x02000000) > 0) { bool aa = Native.VirtualFree(codeBase.Add(section.VirtualAddress), (UIntPtr)section.SizeOfRawData, 0x4000); continue; } int execute = (section.Characteristics & 0x20000000) != 0 ? 1 : 0; int readable = (section.Characteristics & 0x40000000) != 0 ? 1 : 0; int writeable = (section.Characteristics & 0x80000000) != 0 ? 1 : 0; var protect = (uint)ProtectionFlags[execute][readable][writeable]; if ((section.Characteristics & 0x04000000) > 0) protect |= 0x200; var size = (int)section.SizeOfRawData; if (size == 0) { if ((section.Characteristics & 0x00000040) > 0) { size = (int)header64.OptionalHeader.SizeOfInitializedData; } else if ((section.Characteristics & 0x00000080) > 0) { size = (int)header64.OptionalHeader.SizeOfUninitializedData; } } if (size > 0) { uint oldProtect; IntPtr physicalAddress = codeBase.Add(section.VirtualAddress); if (!Native.VirtualProtect(physicalAddress, section.SizeOfRawData, protect, out oldProtect)) { Log.Error("Error protecting memory page of physical address 0x" + physicalAddress.ToString("X16")); } } section = headers.ToStruct<IMAGE_SECTION_HEADER>((uint)((24 + dosHeader.e_lfanew + header64.FileHeader.SizeOfOptionalHeader) + (Marshal.SizeOf(typeof(IMAGE_SECTION_HEADER)) * (i + 1)))); } }
private void CopySections64(byte[] data, IntPtr codeBase, IMAGE_NT_HEADERS64 header64, IntPtr headers, IMAGE_DOS_HEADER dosHeader) { IMAGE_SECTION_HEADER section = headers.ToStruct<IMAGE_SECTION_HEADER>(24 + dosHeader.e_lfanew + header64.FileHeader.SizeOfOptionalHeader); for (int i = 0; i < header64.FileHeader.NumberOfSections; i++) { //ConsoleWindow.Pause("Section " + i + "/"+ (header64.FileHeader.NumberOfSections-1) + " (" + Encoding.UTF8.GetString(section.Name) + ") -> 0x"+ section.VirtualAddress.ToString("X16") + "..."); IntPtr dest; if (section.SizeOfRawData == 0) { uint sectionSize = header64.OptionalHeader.SectionAlignment; if (sectionSize > 0) { dest = Native.VirtualAlloc(codeBase.Add(section.VirtualAddress), sectionSize, MEM_COMMIT, PAGE_READWRITE); Marshal.Copy(new byte[sectionSize + 1], 0, dest, (int)sectionSize); //section.PhysicalAddress = (uint)dest; //ConsoleWindow.WriteLine("section(NoRaw).PhysicalAddress=0x" + section.PhysicalAddress.ToString("X16")+", dest=0x" + dest.ToString("X16")); //write = headers.Add(32 + dosHeader.e_lfanew + header64.FileHeader.SizeOfOptionalHeader + (Marshal.SizeOf(typeof(IMAGE_SECTION_HEADER)) * i)); //Marshal.WriteInt64(write, (long)dest); } } else { dest = Native.VirtualAlloc(codeBase.Add(section.VirtualAddress), section.SizeOfRawData, MEM_COMMIT, PAGE_READWRITE); Marshal.Copy(data, (int)section.PointerToRawData, dest, (int)section.SizeOfRawData); //section.PhysicalAddress = (uint)dest; //ConsoleWindow.WriteLine("section.PhysicalAddress=0x" + section.PhysicalAddress.ToString("X16") + ", dest=0x" + dest.ToString("X16")); //write = headers.Add(32 + dosHeader.e_lfanew + header64.FileHeader.SizeOfOptionalHeader + (Marshal.SizeOf(typeof(IMAGE_SECTION_HEADER)) * i)); //Marshal.WriteInt64(write, (long)dest); } section = headers.ToStruct<IMAGE_SECTION_HEADER>(24 + dosHeader.e_lfanew + header64.FileHeader.SizeOfOptionalHeader + (Marshal.SizeOf(typeof(IMAGE_SECTION_HEADER)) * (i+1))); } }
public MemoryModule(byte[] bytes) { IntPtr address = IntPtr.Zero; IntPtr dllEntryPoint = IntPtr.Zero; ProtectionFlags[0] = new int[2][]; ProtectionFlags[1] = new int[2][]; ProtectionFlags[0][0] = new int[2]; ProtectionFlags[0][1] = new int[2]; ProtectionFlags[1][0] = new int[2]; ProtectionFlags[1][1] = new int[2]; ProtectionFlags[0][0][0] = 0x01; ProtectionFlags[0][0][1] = 0x08; ProtectionFlags[0][1][0] = 0x02; ProtectionFlags[0][1][1] = 0x04; ProtectionFlags[1][0][0] = 0x10; ProtectionFlags[1][0][1] = 0x80; ProtectionFlags[1][1][0] = 0x20; ProtectionFlags[1][1][1] = 0x40; IMAGE_DOS_HEADER dosHeader = bytes.ToStruct<IMAGE_DOS_HEADER>(); IMAGE_NT_HEADERS32 ntHeader = bytes.ToStruct<IMAGE_NT_HEADERS32>((uint)dosHeader.e_lfanew); Is64Bit = (ntHeader.OptionalHeader.Magic == 0x020B || ntHeader.FileHeader.Machine == 0x8664); #region [ Load x64 Machine Dynamic Link Library ] if (Is64Bit) { IMAGE_NT_HEADERS64 header64 = bytes.ToStruct<IMAGE_NT_HEADERS64>((uint)dosHeader.e_lfanew); address = Native.VirtualAlloc((IntPtr)header64.OptionalHeader.ImageBase, header64.OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (address == IntPtr.Zero) address = Native.VirtualAlloc(address, header64.OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (address != IntPtr.Zero) { //Log.Console("Memory Address: 0x" + address.ToString("X16")); IntPtr headers = Native.VirtualAlloc(address, header64.OptionalHeader.SizeOfHeaders, MEM_COMMIT, PAGE_READWRITE); Marshal.Copy(bytes, 0, headers, (int)(dosHeader.e_lfanew + header64.OptionalHeader.SizeOfHeaders)); CopySections64(bytes, address, header64, headers, dosHeader); int moduleCount = GetModuleCount(address, header64.OptionalHeader.ImportTable); module64 = new MEMORYMODULE64 { codeBase = address, numModules = moduleCount, modules = Marshal.AllocHGlobal(moduleCount * sizeof(int)), initialized = 0 }; module64.headers = headers.ToStruct<IMAGE_NT_HEADERS64>((uint)dosHeader.e_lfanew); module64.headers.OptionalHeader.ImageBase = (ulong)address; ulong locationDelta = (ulong)address - header64.OptionalHeader.ImageBase; if (locationDelta != 0) PerformBaseRelocation64(locationDelta); BuildImportTable64(module64); FinalizeSections64(address, headers, dosHeader, header64); dllEntryPoint = address.Add(header64.OptionalHeader.AddressOfEntryPoint); } } #endregion #region [ Load x86 Machine Dynamic Link Library ] else { IMAGE_NT_HEADERS32 header32 = bytes.ToStruct<IMAGE_NT_HEADERS32>((uint)dosHeader.e_lfanew); address = Native.VirtualAlloc((IntPtr)header32.OptionalHeader.ImageBase, header32.OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (address == IntPtr.Zero) address = Native.VirtualAlloc(address, header32.OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (address != IntPtr.Zero) { //Log.Console("Memory Address: 0x" + address.ToString("X16")); IntPtr headers = Native.VirtualAlloc(address, header32.OptionalHeader.SizeOfHeaders, MEM_COMMIT, PAGE_READWRITE); Marshal.Copy(bytes, 0, headers, (int)(dosHeader.e_lfanew + header32.OptionalHeader.SizeOfHeaders)); CopySections32(bytes, address, header32, headers, dosHeader); int moduleCount = GetModuleCount(address, header32.OptionalHeader.ImportTable); module32 = new MEMORYMODULE32 { codeBase = address, numModules = 0, modules = new IntPtr(0), initialized = 0 }; module32.headers = headers.ToStruct<IMAGE_NT_HEADERS32>((uint)dosHeader.e_lfanew); module32.headers.OptionalHeader.ImageBase = (uint)address; ulong locationDelta = (ulong)address - header32.OptionalHeader.ImageBase; if (locationDelta != 0) PerformBaseRelocation32(locationDelta); BuildImportTable32(module32); FinalizeSections32(address, headers, dosHeader, header32); dllEntryPoint = address.Add(header32.OptionalHeader.AddressOfEntryPoint); } } #endregion //Log.Console("DllEntryPoint: 0x" + dllEntryPoint.ToString("X16")); DllEntry dllEntry = (DllEntry)Marshal.GetDelegateForFunctionPointer(dllEntryPoint, typeof(DllEntry)); dllEntry(address, 1, IntPtr.Zero); }