/// <inheritdoc/>
		public void WriteTo(BinaryWriter writer) {
			writer.Write(0x48);	// cb
			writer.Write(options.MajorRuntimeVersion ?? Cor20HeaderOptions.DEFAULT_MAJOR_RT_VER);
			writer.Write(options.MinorRuntimeVersion ?? Cor20HeaderOptions.DEFAULT_MINOR_RT_VER);
			writer.WriteDataDirectory(MetaData);
			writer.Write((uint)(options.Flags ?? ComImageFlags.ILOnly));
			writer.Write(options.EntryPoint ?? 0);
			writer.WriteDataDirectory(NetResources);
			writer.WriteDataDirectory(StrongNameSignature);
			writer.WriteDataDirectory(null);	// Code manager table
			writer.WriteDataDirectory(null);	// Vtable fixups
			writer.WriteDataDirectory(null);	// Export address table jumps
			writer.WriteDataDirectory(null);	// Managed native header
		}
Example #2
0
		/// <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)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);
		}
Example #4
0
        /// <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);
        }