/// <inheritdoc/> public void WriteTo(BinaryWriter writer) { startOffset = writer.BaseStream.Position; // DOS header writer.Write(dosHeader); // PE magic writer.Write(0x00004550); // Image file header writer.Write((ushort)GetMachine()); writer.Write((ushort)sections.Count); writer.Write(options.TimeDateStamp ?? PEHeadersOptions.CreateNewTimeDateStamp()); writer.Write(0); writer.Write(0); writer.Write((ushort)(Use32BitOptionalHeader() ? 0xE0U : 0xF0)); writer.Write((ushort)GetCharacteristics()); var sectionSizes = new SectionSizes(fileAlignment, sectionAlignment, length, () => GetSectionSizeInfos()); // Image optional header uint ep = StartupStub == null ? 0 : (uint)StartupStub.EntryPointRVA; if (Use32BitOptionalHeader()) { writer.Write((ushort)0x010B); writer.Write(options.MajorLinkerVersion ?? PEHeadersOptions.DEFAULT_MAJOR_LINKER_VERSION); writer.Write(options.MinorLinkerVersion ?? PEHeadersOptions.DEFAULT_MINOR_LINKER_VERSION); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.Write(ep); writer.Write(sectionSizes.BaseOfCode); writer.Write(sectionSizes.BaseOfData); writer.Write((uint)imageBase); writer.Write(sectionAlignment); writer.Write(fileAlignment); writer.Write(options.MajorOperatingSystemVersion ?? 4); writer.Write(options.MinorOperatingSystemVersion ?? 0); writer.Write(options.MajorImageVersion ?? 0); writer.Write(options.MinorImageVersion ?? 0); writer.Write(options.MajorSubsystemVersion ?? 4); writer.Write(options.MinorSubsystemVersion ?? 0); writer.Write(options.Win32VersionValue ?? 0); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum writer.Write((ushort)(options.Subsystem ?? PEHeadersOptions.DEFAULT_SUBSYSTEM)); writer.Write((ushort)(options.DllCharacteristics ?? PEHeadersOptions.DefaultDllCharacteristics)); writer.Write((uint)(options.SizeOfStackReserve ?? 0x00100000)); writer.Write((uint)(options.SizeOfStackCommit ?? 0x00001000)); writer.Write((uint)(options.SizeOfHeapReserve ?? 0x00100000)); writer.Write((uint)(options.SizeOfHeapCommit ?? 0x00001000)); writer.Write(options.LoaderFlags ?? 0x00000000); writer.Write(options.NumberOfRvaAndSizes ?? 0x00000010); } else { writer.Write((ushort)0x020B); writer.Write(options.MajorLinkerVersion ?? PEHeadersOptions.DEFAULT_MAJOR_LINKER_VERSION); writer.Write(options.MinorLinkerVersion ?? PEHeadersOptions.DEFAULT_MINOR_LINKER_VERSION); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.Write(ep); writer.Write(sectionSizes.BaseOfCode); writer.Write(imageBase); writer.Write(sectionAlignment); writer.Write(fileAlignment); writer.Write(options.MajorOperatingSystemVersion ?? 4); writer.Write(options.MinorOperatingSystemVersion ?? 0); writer.Write(options.MajorImageVersion ?? 0); writer.Write(options.MinorImageVersion ?? 0); writer.Write(options.MajorSubsystemVersion ?? 4); writer.Write(options.MinorSubsystemVersion ?? 0); writer.Write(options.Win32VersionValue ?? 0); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum writer.Write((ushort)(options.Subsystem ?? PEHeadersOptions.DEFAULT_SUBSYSTEM)); writer.Write((ushort)(options.DllCharacteristics ?? PEHeadersOptions.DefaultDllCharacteristics)); writer.Write(options.SizeOfStackReserve ?? 0x0000000000400000); writer.Write(options.SizeOfStackCommit ?? 0x0000000000004000); writer.Write(options.SizeOfHeapReserve ?? 0x0000000000100000); writer.Write(options.SizeOfHeapCommit ?? 0x0000000000002000); writer.Write(options.LoaderFlags ?? 0x00000000); writer.Write(options.NumberOfRvaAndSizes ?? 0x00000010); } writer.WriteDataDirectory(null); // Export table writer.WriteDataDirectory(ImportDirectory); writer.WriteDataDirectory(Win32Resources); writer.WriteDataDirectory(null); // Exception table writer.WriteDataDirectory(null); // Certificate table writer.WriteDataDirectory(RelocDirectory); writer.WriteDataDirectory(DebugDirectory, DebugDirectory.HEADER_SIZE); writer.WriteDataDirectory(null); // Architecture-specific data writer.WriteDataDirectory(null); // Global pointer register RVA writer.WriteDataDirectory(null); // Thread local storage writer.WriteDataDirectory(null); // Load configuration table writer.WriteDataDirectory(null); // Bound import table writer.WriteDataDirectory(ImportAddressTable); writer.WriteDataDirectory(null); // Delay import descriptor writer.WriteDataDirectory(ImageCor20Header); writer.WriteDataDirectory(null); // Reserved // Sections uint rva = Utils.AlignUp(sectionSizes.SizeOfHeaders, sectionAlignment); foreach (var section in sections) { rva += section.WriteHeaderTo(writer, fileAlignment, sectionAlignment, rva); } }
/// <summary> /// Updates the PE header and COR20 header fields that need updating. All sections are /// also updated, and the new ones are added. /// </summary> void UpdateHeaderFields(BinaryWriter writer) { long fileHeaderOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.FileHeader.StartOffset; long optionalHeaderOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.StartOffset; long sectionsOffset = destStreamBaseOffset + (long)peImage.ImageSectionHeaders[0].StartOffset; long dataDirOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.EndOffset - 16 * 8; long cor20Offset = destStreamBaseOffset + (long)module.MetaData.ImageCor20Header.StartOffset; uint fileAlignment = peImage.ImageNTHeaders.OptionalHeader.FileAlignment; uint sectionAlignment = peImage.ImageNTHeaders.OptionalHeader.SectionAlignment; // Update PE file header var peOptions = Options.PEHeadersOptions; writer.BaseStream.Position = fileHeaderOffset; writer.Write((ushort)(peOptions.Machine ?? module.Machine)); writer.Write((ushort)(origSections.Count + sections.Count)); WriteUInt32(writer, peOptions.TimeDateStamp); writer.BaseStream.Position += 10; writer.Write((ushort)(peOptions.Characteristics ?? GetCharacteristics())); // Update optional header var sectionSizes = new SectionSizes(fileAlignment, sectionAlignment, headerSection.GetVirtualSize(), () => GetSectionSizeInfos()); writer.BaseStream.Position = optionalHeaderOffset; bool is32BitOptionalHeader = peImage.ImageNTHeaders.OptionalHeader is ImageOptionalHeader32; if (is32BitOptionalHeader) { writer.BaseStream.Position += 2; WriteByte(writer, peOptions.MajorLinkerVersion); WriteByte(writer, peOptions.MinorLinkerVersion); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.BaseStream.Position += 4; // EntryPoint writer.Write(sectionSizes.BaseOfCode); writer.Write(sectionSizes.BaseOfData); WriteUInt32(writer, peOptions.ImageBase); writer.BaseStream.Position += 8; // SectionAlignment, FileAlignment WriteUInt16(writer, peOptions.MajorOperatingSystemVersion); WriteUInt16(writer, peOptions.MinorOperatingSystemVersion); WriteUInt16(writer, peOptions.MajorImageVersion); WriteUInt16(writer, peOptions.MinorImageVersion); WriteUInt16(writer, peOptions.MajorSubsystemVersion); WriteUInt16(writer, peOptions.MinorSubsystemVersion); WriteUInt32(writer, peOptions.Win32VersionValue); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum WriteUInt16(writer, peOptions.Subsystem); WriteUInt16(writer, peOptions.DllCharacteristics); WriteUInt32(writer, peOptions.SizeOfStackReserve); WriteUInt32(writer, peOptions.SizeOfStackCommit); WriteUInt32(writer, peOptions.SizeOfHeapReserve); WriteUInt32(writer, peOptions.SizeOfHeapCommit); WriteUInt32(writer, peOptions.LoaderFlags); WriteUInt32(writer, peOptions.NumberOfRvaAndSizes); } else { writer.BaseStream.Position += 2; WriteByte(writer, peOptions.MajorLinkerVersion); WriteByte(writer, peOptions.MinorLinkerVersion); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.BaseStream.Position += 4; // EntryPoint writer.Write(sectionSizes.BaseOfCode); WriteUInt64(writer, peOptions.ImageBase); writer.BaseStream.Position += 8; // SectionAlignment, FileAlignment WriteUInt16(writer, peOptions.MajorOperatingSystemVersion); WriteUInt16(writer, peOptions.MinorOperatingSystemVersion); WriteUInt16(writer, peOptions.MajorImageVersion); WriteUInt16(writer, peOptions.MinorImageVersion); WriteUInt16(writer, peOptions.MajorSubsystemVersion); WriteUInt16(writer, peOptions.MinorSubsystemVersion); WriteUInt32(writer, peOptions.Win32VersionValue); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum WriteUInt16(writer, peOptions.Subsystem ?? GetSubsystem()); WriteUInt16(writer, peOptions.DllCharacteristics ?? module.DllCharacteristics); WriteUInt64(writer, peOptions.SizeOfStackReserve); WriteUInt64(writer, peOptions.SizeOfStackCommit); WriteUInt64(writer, peOptions.SizeOfHeapReserve); WriteUInt64(writer, peOptions.SizeOfHeapCommit); WriteUInt32(writer, peOptions.LoaderFlags); WriteUInt32(writer, peOptions.NumberOfRvaAndSizes); } // Update Win32 resources data directory, if we wrote a new one if (win32Resources != null) { writer.BaseStream.Position = dataDirOffset + 2 * 8; writer.WriteDataDirectory(win32Resources); } // Update old sections, and add new sections writer.BaseStream.Position = sectionsOffset; foreach (var section in origSections) { writer.BaseStream.Position += 0x14; writer.Write((uint)section.chunk.FileOffset); // PointerToRawData writer.BaseStream.Position += 0x10; } foreach (var section in sections) { section.WriteHeaderTo(writer, fileAlignment, sectionAlignment, (uint)section.RVA); } // Update .NET header writer.BaseStream.Position = cor20Offset + 4; WriteUInt16(writer, Options.Cor20HeaderOptions.MajorRuntimeVersion); WriteUInt16(writer, Options.Cor20HeaderOptions.MinorRuntimeVersion); writer.WriteDataDirectory(metaData); uint entryPoint; writer.Write((uint)GetComImageFlags(GetEntryPoint(out entryPoint))); writer.Write(Options.Cor20HeaderOptions.EntryPoint ?? entryPoint); writer.WriteDataDirectory(netResources); if (Options.StrongNameKey != null) { if (strongNameSignature != null) { writer.WriteDataDirectory(strongNameSignature); } else if (strongNameSigOffset != null) { // RVA is the same. Only need to update size. writer.BaseStream.Position += 4; writer.Write(Options.StrongNameKey.SignatureSize); } } UpdateVTableFixups(writer); }
/// <summary> /// Updates the PE header and COR20 header fields that need updating. All sections are /// also updated, and the new ones are added. /// </summary> void UpdateHeaderFields(BinaryWriter writer) { long fileHeaderOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.FileHeader.StartOffset; long optionalHeaderOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.StartOffset; long sectionsOffset = destStreamBaseOffset + (long)peImage.ImageSectionHeaders[0].StartOffset; long dataDirOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.EndOffset - 16 * 8; long cor20Offset = destStreamBaseOffset + (long)module.MetaData.ImageCor20Header.StartOffset; uint fileAlignment = peImage.ImageNTHeaders.OptionalHeader.FileAlignment; uint sectionAlignment = peImage.ImageNTHeaders.OptionalHeader.SectionAlignment; // Update PE file header var peOptions = Options.PEHeadersOptions; writer.BaseStream.Position = fileHeaderOffset; writer.Write((ushort)(peOptions.Machine ?? module.Machine)); writer.Write((ushort)(origSections.Count + sections.Count)); WriteUInt32(writer, peOptions.TimeDateStamp); writer.BaseStream.Position += 10; writer.Write((ushort)(peOptions.Characteristics ?? GetCharacteristics())); // Update optional header var sectionSizes = new SectionSizes(fileAlignment, sectionAlignment, headerSection.GetVirtualSize(), () => GetSectionSizeInfos()); writer.BaseStream.Position = optionalHeaderOffset; bool is32BitOptionalHeader = peImage.ImageNTHeaders.OptionalHeader is ImageOptionalHeader32; if (is32BitOptionalHeader) { writer.BaseStream.Position += 2; WriteByte(writer, peOptions.MajorLinkerVersion); WriteByte(writer, peOptions.MinorLinkerVersion); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.BaseStream.Position += 4; // EntryPoint writer.Write(sectionSizes.BaseOfCode); writer.Write(sectionSizes.BaseOfData); WriteUInt32(writer, peOptions.ImageBase); writer.BaseStream.Position += 8; // SectionAlignment, FileAlignment WriteUInt16(writer, peOptions.MajorOperatingSystemVersion); WriteUInt16(writer, peOptions.MinorOperatingSystemVersion); WriteUInt16(writer, peOptions.MajorImageVersion); WriteUInt16(writer, peOptions.MinorImageVersion); WriteUInt16(writer, peOptions.MajorSubsystemVersion); WriteUInt16(writer, peOptions.MinorSubsystemVersion); WriteUInt32(writer, peOptions.Win32VersionValue); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum WriteUInt16(writer, peOptions.Subsystem); WriteUInt16(writer, peOptions.DllCharacteristics); WriteUInt32(writer, peOptions.SizeOfStackReserve); WriteUInt32(writer, peOptions.SizeOfStackCommit); WriteUInt32(writer, peOptions.SizeOfHeapReserve); WriteUInt32(writer, peOptions.SizeOfHeapCommit); WriteUInt32(writer, peOptions.LoaderFlags); WriteUInt32(writer, peOptions.NumberOfRvaAndSizes); } else { writer.BaseStream.Position += 2; WriteByte(writer, peOptions.MajorLinkerVersion); WriteByte(writer, peOptions.MinorLinkerVersion); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.BaseStream.Position += 4; // EntryPoint writer.Write(sectionSizes.BaseOfCode); WriteUInt64(writer, peOptions.ImageBase); writer.BaseStream.Position += 8; // SectionAlignment, FileAlignment WriteUInt16(writer, peOptions.MajorOperatingSystemVersion); WriteUInt16(writer, peOptions.MinorOperatingSystemVersion); WriteUInt16(writer, peOptions.MajorImageVersion); WriteUInt16(writer, peOptions.MinorImageVersion); WriteUInt16(writer, peOptions.MajorSubsystemVersion); WriteUInt16(writer, peOptions.MinorSubsystemVersion); WriteUInt32(writer, peOptions.Win32VersionValue); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum WriteUInt16(writer, peOptions.Subsystem ?? GetSubsystem()); WriteUInt16(writer, peOptions.DllCharacteristics ?? module.DllCharacteristics); WriteUInt64(writer, peOptions.SizeOfStackReserve); WriteUInt64(writer, peOptions.SizeOfStackCommit); WriteUInt64(writer, peOptions.SizeOfHeapReserve); WriteUInt64(writer, peOptions.SizeOfHeapCommit); WriteUInt32(writer, peOptions.LoaderFlags); WriteUInt32(writer, peOptions.NumberOfRvaAndSizes); } // Update Win32 resources data directory, if we wrote a new one if (win32Resources != null) { writer.BaseStream.Position = dataDirOffset + 2 * 8; writer.WriteDataDirectory(win32Resources); } // Update old sections, and add new sections writer.BaseStream.Position = sectionsOffset; foreach (var section in origSections) { writer.BaseStream.Position += 0x14; writer.Write((uint)section.chunk.FileOffset); // PointerToRawData writer.BaseStream.Position += 0x10; } foreach (var section in sections) section.WriteHeaderTo(writer, fileAlignment, sectionAlignment, (uint)section.RVA); // Update .NET header writer.BaseStream.Position = cor20Offset + 4; WriteUInt16(writer, Options.Cor20HeaderOptions.MajorRuntimeVersion); WriteUInt16(writer, Options.Cor20HeaderOptions.MinorRuntimeVersion); writer.WriteDataDirectory(metaData); uint entryPoint; writer.Write((uint)GetComImageFlags(GetEntryPoint(out entryPoint))); writer.Write(Options.Cor20HeaderOptions.EntryPoint ?? entryPoint); writer.WriteDataDirectory(netResources); if (Options.StrongNameKey != null) { if (strongNameSignature != null) writer.WriteDataDirectory(strongNameSignature); else if (strongNameSigOffset != null) { // RVA is the same. Only need to update size. writer.BaseStream.Position += 4; writer.Write(Options.StrongNameKey.SignatureSize); } } UpdateVTableFixups(writer); }
/// <inheritdoc/> public void WriteTo(BinaryWriter writer) { startOffset = writer.BaseStream.Position; // DOS header writer.Write(dosHeader); // PE magic writer.Write(0x00004550); // Image file header writer.Write((ushort)GetMachine()); writer.Write((ushort)sections.Count); writer.Write(options.TimeDateStamp ?? PEHeadersOptions.CreateNewTimeDateStamp()); writer.Write(options.PointerToSymbolTable ?? 0); writer.Write(options.NumberOfSymbols ?? 0); writer.Write((ushort)(Use32BitOptionalHeader() ? 0xE0U : 0xF0)); writer.Write((ushort)GetCharacteristics()); var sectionSizes = new SectionSizes(fileAlignment, sectionAlignment, length, () => GetSectionSizeInfos()); // Image optional header uint ep = StartupStub == null ? 0 : (uint)StartupStub.EntryPointRVA; if (Use32BitOptionalHeader()) { writer.Write((ushort)0x010B); writer.Write(options.MajorLinkerVersion ?? PEHeadersOptions.DEFAULT_MAJOR_LINKER_VERSION); writer.Write(options.MinorLinkerVersion ?? PEHeadersOptions.DEFAULT_MINOR_LINKER_VERSION); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.Write(ep); writer.Write(sectionSizes.BaseOfCode); writer.Write(sectionSizes.BaseOfData); writer.Write((uint)imageBase); writer.Write(sectionAlignment); writer.Write(fileAlignment); writer.Write(options.MajorOperatingSystemVersion ?? 4); writer.Write(options.MinorOperatingSystemVersion ?? 0); writer.Write(options.MajorImageVersion ?? 0); writer.Write(options.MinorImageVersion ?? 0); writer.Write(options.MajorSubsystemVersion ?? 4); writer.Write(options.MinorSubsystemVersion ?? 0); writer.Write(options.Win32VersionValue ?? 0); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum writer.Write((ushort)(options.Subsystem ?? PEHeadersOptions.DEFAULT_SUBSYSTEM)); writer.Write((ushort)(options.DllCharacteristics ?? PEHeadersOptions.DefaultDllCharacteristics)); writer.Write((uint)(options.SizeOfStackReserve ?? 0x00100000)); writer.Write((uint)(options.SizeOfStackCommit ?? 0x00001000)); writer.Write((uint)(options.SizeOfHeapReserve ?? 0x00100000)); writer.Write((uint)(options.SizeOfHeapCommit ?? 0x00001000)); writer.Write(options.LoaderFlags ?? 0x00000000); writer.Write(options.NumberOfRvaAndSizes ?? 0x00000010); } else { writer.Write((ushort)0x020B); writer.Write(options.MajorLinkerVersion ?? PEHeadersOptions.DEFAULT_MAJOR_LINKER_VERSION); writer.Write(options.MinorLinkerVersion ?? PEHeadersOptions.DEFAULT_MINOR_LINKER_VERSION); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.Write(ep); writer.Write(sectionSizes.BaseOfCode); writer.Write(imageBase); writer.Write(sectionAlignment); writer.Write(fileAlignment); writer.Write(options.MajorOperatingSystemVersion ?? 4); writer.Write(options.MinorOperatingSystemVersion ?? 0); writer.Write(options.MajorImageVersion ?? 0); writer.Write(options.MinorImageVersion ?? 0); writer.Write(options.MajorSubsystemVersion ?? 4); writer.Write(options.MinorSubsystemVersion ?? 0); writer.Write(options.Win32VersionValue ?? 0); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum writer.Write((ushort)(options.Subsystem ?? PEHeadersOptions.DEFAULT_SUBSYSTEM)); writer.Write((ushort)(options.DllCharacteristics ?? PEHeadersOptions.DefaultDllCharacteristics)); writer.Write(options.SizeOfStackReserve ?? 0x0000000000400000); writer.Write(options.SizeOfStackCommit ?? 0x0000000000004000); writer.Write(options.SizeOfHeapReserve ?? 0x0000000000100000); writer.Write(options.SizeOfHeapCommit ?? 0x0000000000002000); writer.Write(options.LoaderFlags ?? 0x00000000); writer.Write(options.NumberOfRvaAndSizes ?? 0x00000010); } writer.WriteDataDirectory(null); // Export table writer.WriteDataDirectory(ImportDirectory); writer.WriteDataDirectory(Win32Resources); writer.WriteDataDirectory(null); // Exception table writer.WriteDataDirectory(null); // Certificate table writer.WriteDataDirectory(RelocDirectory); writer.WriteDataDirectory(DebugDirectory, DebugDirectory.HEADER_SIZE); writer.WriteDataDirectory(null); // Architecture-specific data writer.WriteDataDirectory(null); // Global pointer register RVA writer.WriteDataDirectory(null); // Thread local storage writer.WriteDataDirectory(null); // Load configuration table writer.WriteDataDirectory(null); // Bound import table writer.WriteDataDirectory(ImportAddressTable); writer.WriteDataDirectory(null); // Delay import descriptor writer.WriteDataDirectory(ImageCor20Header); writer.WriteDataDirectory(null); // Reserved // Sections uint rva = Utils.AlignUp(sectionSizes.SizeOfHeaders, sectionAlignment); foreach (var section in sections) rva += section.WriteHeaderTo(writer, fileAlignment, sectionAlignment, rva); }
/// <summary> /// Updates the PE header and COR20 header fields that need updating. All sections are /// also updated, and the new ones are added. /// </summary> void UpdateHeaderFields(BinaryWriter writer) { long fileHeaderOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.FileHeader.StartOffset; long optionalHeaderOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.StartOffset; long sectionsOffset = destStreamBaseOffset + (long)peImage.ImageSectionHeaders[0].StartOffset; long dataDirOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.EndOffset - 16 * 8; long cor20Offset = destStreamBaseOffset + (long)imageCor20Header.FileOffset; uint fileAlignment = peImage.ImageNTHeaders.OptionalHeader.FileAlignment; uint sectionAlignment = peImage.ImageNTHeaders.OptionalHeader.SectionAlignment; // Update PE file header var peOptions = Options.PEHeadersOptions; writer.BaseStream.Position = fileHeaderOffset; writer.Write((ushort)(peOptions.Machine ?? module.Machine)); writer.Write((ushort)(origSections.Count + sections.Count)); WriteUInt32(writer, peOptions.TimeDateStamp); WriteUInt32(writer, peOptions.PointerToSymbolTable); WriteUInt32(writer, peOptions.NumberOfSymbols); writer.BaseStream.Position += 2; // sizeof(SizeOfOptionalHeader) writer.Write((ushort)(peOptions.Characteristics ?? GetCharacteristics())); // Update optional header var sectionSizes = new SectionSizes(fileAlignment, sectionAlignment, headerSection.GetVirtualSize(), GetSectionSizeInfos); writer.BaseStream.Position = optionalHeaderOffset; bool is32BitOptionalHeader = peImage.ImageNTHeaders.OptionalHeader is ImageOptionalHeader32; if (is32BitOptionalHeader) { writer.BaseStream.Position += 2; WriteByte(writer, peOptions.MajorLinkerVersion); WriteByte(writer, peOptions.MinorLinkerVersion); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.BaseStream.Position += 4; // EntryPoint writer.Write(sectionSizes.BaseOfCode); writer.Write(sectionSizes.BaseOfData); WriteUInt32(writer, peOptions.ImageBase); writer.BaseStream.Position += 8; // SectionAlignment, FileAlignment WriteUInt16(writer, peOptions.MajorOperatingSystemVersion); WriteUInt16(writer, peOptions.MinorOperatingSystemVersion); WriteUInt16(writer, peOptions.MajorImageVersion); WriteUInt16(writer, peOptions.MinorImageVersion); WriteUInt16(writer, peOptions.MajorSubsystemVersion); WriteUInt16(writer, peOptions.MinorSubsystemVersion); WriteUInt32(writer, peOptions.Win32VersionValue); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum WriteUInt16(writer, peOptions.Subsystem); WriteUInt16(writer, peOptions.DllCharacteristics); WriteUInt32(writer, peOptions.SizeOfStackReserve); WriteUInt32(writer, peOptions.SizeOfStackCommit); WriteUInt32(writer, peOptions.SizeOfHeapReserve); WriteUInt32(writer, peOptions.SizeOfHeapCommit); WriteUInt32(writer, peOptions.LoaderFlags); WriteUInt32(writer, peOptions.NumberOfRvaAndSizes); } else { writer.BaseStream.Position += 2; WriteByte(writer, peOptions.MajorLinkerVersion); WriteByte(writer, peOptions.MinorLinkerVersion); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.BaseStream.Position += 4; // EntryPoint writer.Write(sectionSizes.BaseOfCode); WriteUInt64(writer, peOptions.ImageBase); writer.BaseStream.Position += 8; // SectionAlignment, FileAlignment WriteUInt16(writer, peOptions.MajorOperatingSystemVersion); WriteUInt16(writer, peOptions.MinorOperatingSystemVersion); WriteUInt16(writer, peOptions.MajorImageVersion); WriteUInt16(writer, peOptions.MinorImageVersion); WriteUInt16(writer, peOptions.MajorSubsystemVersion); WriteUInt16(writer, peOptions.MinorSubsystemVersion); WriteUInt32(writer, peOptions.Win32VersionValue); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum WriteUInt16(writer, peOptions.Subsystem ?? GetSubsystem()); WriteUInt16(writer, peOptions.DllCharacteristics ?? module.DllCharacteristics); WriteUInt64(writer, peOptions.SizeOfStackReserve); WriteUInt64(writer, peOptions.SizeOfStackCommit); WriteUInt64(writer, peOptions.SizeOfHeapReserve); WriteUInt64(writer, peOptions.SizeOfHeapCommit); WriteUInt32(writer, peOptions.LoaderFlags); WriteUInt32(writer, peOptions.NumberOfRvaAndSizes); } // Update Win32 resources data directory, if we wrote a new one if (win32Resources != null) { writer.BaseStream.Position = dataDirOffset + 2 * 8; writer.WriteDataDirectory(win32Resources); } // Clear the security descriptor directory writer.BaseStream.Position = dataDirOffset + 4 * 8; writer.WriteDataDirectory(null); // Write a new debug directory writer.BaseStream.Position = dataDirOffset + 6 * 8; writer.WriteDataDirectory(debugDirectory, DebugDirectory.HEADER_SIZE); // Write a new Metadata data directory writer.BaseStream.Position = dataDirOffset + 14 * 8; writer.WriteDataDirectory(imageCor20Header); // Update old sections, and add new sections writer.BaseStream.Position = sectionsOffset; foreach (var section in origSections) { writer.BaseStream.Position += 0x14; writer.Write((uint)section.Chunk.FileOffset); // PointerToRawData writer.BaseStream.Position += 0x10; } foreach (var section in sections) section.WriteHeaderTo(writer, fileAlignment, sectionAlignment, (uint)section.RVA); // Write the .NET header writer.BaseStream.Position = cor20Offset; writer.Write(0x48); // cb WriteUInt16(writer, Options.Cor20HeaderOptions.MajorRuntimeVersion); WriteUInt16(writer, Options.Cor20HeaderOptions.MinorRuntimeVersion); writer.WriteDataDirectory(metaData); uint entryPoint; writer.Write((uint)GetComImageFlags(GetEntryPoint(out entryPoint))); writer.Write(Options.Cor20HeaderOptions.EntryPoint ?? entryPoint); writer.WriteDataDirectory(netResources); writer.WriteDataDirectory(strongNameSignature); WriteDataDirectory(writer, module.MetaData.ImageCor20Header.CodeManagerTable); WriteDataDirectory(writer, module.MetaData.ImageCor20Header.VTableFixups); WriteDataDirectory(writer, module.MetaData.ImageCor20Header.ExportAddressTableJumps); WriteDataDirectory(writer, module.MetaData.ImageCor20Header.ManagedNativeHeader); UpdateVTableFixups(writer); }
/// <summary> /// Updates the PE header and COR20 header fields that need updating. All sections are /// also updated, and the new ones are added. /// </summary> private void UpdateHeaderFields(BinaryWriter writer) { var fileHeaderOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.FileHeader.StartOffset; var optionalHeaderOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.StartOffset; var sectionsOffset = destStreamBaseOffset + (long)peImage.ImageSectionHeaders[0].StartOffset; var dataDirOffset = destStreamBaseOffset + (long)peImage.ImageNTHeaders.OptionalHeader.EndOffset - 16 * 8; var cor20Offset = destStreamBaseOffset + (long)imageCor20Header.FileOffset; var fileAlignment = peImage.ImageNTHeaders.OptionalHeader.FileAlignment; var sectionAlignment = peImage.ImageNTHeaders.OptionalHeader.SectionAlignment; // Update PE file header var peOptions = Options.PEHeadersOptions; writer.BaseStream.Position = fileHeaderOffset; writer.Write((ushort)(peOptions.Machine ?? module.Machine)); writer.Write((ushort)(origSections.Count + sections.Count)); WriteUInt32(writer, peOptions.TimeDateStamp); WriteUInt32(writer, peOptions.PointerToSymbolTable); WriteUInt32(writer, peOptions.NumberOfSymbols); writer.BaseStream.Position += 2; // sizeof(SizeOfOptionalHeader) writer.Write((ushort)(peOptions.Characteristics ?? GetCharacteristics())); // Update optional header var sectionSizes = new SectionSizes(fileAlignment, sectionAlignment, headerSection.GetVirtualSize(), GetSectionSizeInfos); writer.BaseStream.Position = optionalHeaderOffset; var is32BitOptionalHeader = peImage.ImageNTHeaders.OptionalHeader is ImageOptionalHeader32; if (is32BitOptionalHeader) { writer.BaseStream.Position += 2; WriteByte(writer, peOptions.MajorLinkerVersion); WriteByte(writer, peOptions.MinorLinkerVersion); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.BaseStream.Position += 4; // EntryPoint writer.Write(sectionSizes.BaseOfCode); writer.Write(sectionSizes.BaseOfData); WriteUInt32(writer, peOptions.ImageBase); writer.BaseStream.Position += 8; // SectionAlignment, FileAlignment WriteUInt16(writer, peOptions.MajorOperatingSystemVersion); WriteUInt16(writer, peOptions.MinorOperatingSystemVersion); WriteUInt16(writer, peOptions.MajorImageVersion); WriteUInt16(writer, peOptions.MinorImageVersion); WriteUInt16(writer, peOptions.MajorSubsystemVersion); WriteUInt16(writer, peOptions.MinorSubsystemVersion); WriteUInt32(writer, peOptions.Win32VersionValue); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum WriteUInt16(writer, peOptions.Subsystem); WriteUInt16(writer, peOptions.DllCharacteristics); WriteUInt32(writer, peOptions.SizeOfStackReserve); WriteUInt32(writer, peOptions.SizeOfStackCommit); WriteUInt32(writer, peOptions.SizeOfHeapReserve); WriteUInt32(writer, peOptions.SizeOfHeapCommit); WriteUInt32(writer, peOptions.LoaderFlags); WriteUInt32(writer, peOptions.NumberOfRvaAndSizes); } else { writer.BaseStream.Position += 2; WriteByte(writer, peOptions.MajorLinkerVersion); WriteByte(writer, peOptions.MinorLinkerVersion); writer.Write(sectionSizes.SizeOfCode); writer.Write(sectionSizes.SizeOfInitdData); writer.Write(sectionSizes.SizeOfUninitdData); writer.BaseStream.Position += 4; // EntryPoint writer.Write(sectionSizes.BaseOfCode); WriteUInt64(writer, peOptions.ImageBase); writer.BaseStream.Position += 8; // SectionAlignment, FileAlignment WriteUInt16(writer, peOptions.MajorOperatingSystemVersion); WriteUInt16(writer, peOptions.MinorOperatingSystemVersion); WriteUInt16(writer, peOptions.MajorImageVersion); WriteUInt16(writer, peOptions.MinorImageVersion); WriteUInt16(writer, peOptions.MajorSubsystemVersion); WriteUInt16(writer, peOptions.MinorSubsystemVersion); WriteUInt32(writer, peOptions.Win32VersionValue); writer.Write(sectionSizes.SizeOfImage); writer.Write(sectionSizes.SizeOfHeaders); checkSumOffset = writer.BaseStream.Position; writer.Write(0); // CheckSum WriteUInt16(writer, peOptions.Subsystem ?? GetSubsystem()); WriteUInt16(writer, peOptions.DllCharacteristics ?? module.DllCharacteristics); WriteUInt64(writer, peOptions.SizeOfStackReserve); WriteUInt64(writer, peOptions.SizeOfStackCommit); WriteUInt64(writer, peOptions.SizeOfHeapReserve); WriteUInt64(writer, peOptions.SizeOfHeapCommit); WriteUInt32(writer, peOptions.LoaderFlags); WriteUInt32(writer, peOptions.NumberOfRvaAndSizes); } // Update Win32 resources data directory, if we wrote a new one if (win32Resources != null) { writer.BaseStream.Position = dataDirOffset + 2 * 8; writer.WriteDataDirectory(win32Resources); } // Clear the security descriptor directory writer.BaseStream.Position = dataDirOffset + 4 * 8; writer.WriteDataDirectory(null); // Write a new debug directory writer.BaseStream.Position = dataDirOffset + 6 * 8; writer.WriteDataDirectory(debugDirectory, DebugDirectory.HEADER_SIZE); // Write a new Metadata data directory writer.BaseStream.Position = dataDirOffset + 14 * 8; writer.WriteDataDirectory(imageCor20Header); // Update old sections, and add new sections writer.BaseStream.Position = sectionsOffset; foreach (var section in origSections) { writer.BaseStream.Position += 0x14; writer.Write((uint)section.Chunk.FileOffset); // PointerToRawData writer.BaseStream.Position += 0x10; } foreach (var section in sections) { section.WriteHeaderTo(writer, fileAlignment, sectionAlignment, (uint)section.RVA); } // Write the .NET header writer.BaseStream.Position = cor20Offset; writer.Write(0x48); // cb WriteUInt16(writer, Options.Cor20HeaderOptions.MajorRuntimeVersion); WriteUInt16(writer, Options.Cor20HeaderOptions.MinorRuntimeVersion); writer.WriteDataDirectory(metaData); uint entryPoint; writer.Write((uint)GetComImageFlags(GetEntryPoint(out entryPoint))); writer.Write(Options.Cor20HeaderOptions.EntryPoint ?? entryPoint); writer.WriteDataDirectory(netResources); writer.WriteDataDirectory(strongNameSignature); WriteDataDirectory(writer, module.MetaData.ImageCor20Header.CodeManagerTable); WriteDataDirectory(writer, module.MetaData.ImageCor20Header.VTableFixups); WriteDataDirectory(writer, module.MetaData.ImageCor20Header.ExportAddressTableJumps); WriteDataDirectory(writer, module.MetaData.ImageCor20Header.ManagedNativeHeader); UpdateVTableFixups(writer); }