/// <summary> /// Marks memory pages depending on section headers and release sections that are marked as "discardable". /// </summary> /// <param name="memory_module">Pointer to a memory module.</param> private void FinalizeSections(MEMORY_MODULE *memory_module) { WinNT.IMAGE_SECTION_HEADER *section = WinNT.IMAGE_FIRST_SECTION(memory_module->headers);; ushort number_of_sections; uint size_of_initialized_data; uint size_of_uninitialized_data; long image_offset = 0; if (Environment.Is64BitProcess) { WinNT.IMAGE_NT_HEADERS64 *headers = (WinNT.IMAGE_NT_HEADERS64 *)memory_module->headers; number_of_sections = headers->FileHeader.NumberOfSections; size_of_initialized_data = headers->OptionalHeader.SizeOfInitializedData; size_of_uninitialized_data = headers->OptionalHeader.SizeOfUninitializedData; image_offset = (long)((ulong)headers->OptionalHeader.ImageBase & 0xffffffff00000000); } else { WinNT.IMAGE_NT_HEADERS32 *headers = (WinNT.IMAGE_NT_HEADERS32 *)memory_module->headers; number_of_sections = headers->FileHeader.NumberOfSections; size_of_initialized_data = headers->OptionalHeader.SizeOfInitializedData; size_of_uninitialized_data = headers->OptionalHeader.SizeOfUninitializedData; } for (int i = 0; i < number_of_sections; i++, section++) { uint protect, oldProtect, rawDataSize; uint executable = Convert.ToUInt32((section->Characteristics & WinNT.IMAGE_SCN_MEM_EXECUTE) != 0); uint readable = Convert.ToUInt32((section->Characteristics & WinNT.IMAGE_SCN_MEM_READ) != 0); uint writeable = Convert.ToUInt32((section->Characteristics & WinNT.IMAGE_SCN_MEM_WRITE) != 0); if ((section->Characteristics & WinNT.IMAGE_SCN_MEM_DISCARDABLE) != 0) { // section is not needed any more and can safely be freed WinBase.VirtualFree((IntPtr)(void *)((long)section->PhysicalAddress | (long)image_offset), section->SizeOfRawData, WinNT.MEM_DECOMMIT); continue; } protect = _protectionFlags[executable, readable, writeable]; if ((section->Characteristics & WinNT.IMAGE_SCN_MEM_NOT_CACHED) != 0) { protect |= WinNT.PAGE_NOCACHE; } // determine size of region rawDataSize = section->SizeOfRawData; if (rawDataSize == 0) { if ((section->Characteristics & WinNT.IMAGE_SCN_CNT_INITIALIZED_DATA) != 0) { rawDataSize = size_of_initialized_data; } else if ((section->Characteristics & WinNT.IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0) { rawDataSize = size_of_uninitialized_data; } } if (rawDataSize > 0) { // change memory access flags WinBase.VirtualProtect((IntPtr)(void *)((long)section->PhysicalAddress | (long)image_offset), rawDataSize, protect, &oldProtect); } } }