/// <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> private 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); }