public void Write() { var peImage = mdEditor.RealMetadata.PEImage; bool is32Bit = peImage.ImageNTHeaders.OptionalHeader is ImageOptionalHeader32; sections.Add(textSection = new PESection(".text", 0x60000020)); StrongNameSignatureSectionData snData = null; var cor20 = mdEditor.RealMetadata.ImageCor20Header; if ((cor20.Flags & ComImageFlags.StrongNameSigned) != 0 && cor20.StrongNameSignature.Size != 0 && cor20.StrongNameSignature.VirtualAddress != 0) { snData = new StrongNameSignatureSectionData(cor20.StrongNameSignature.Size); } if (snData != null) { textSection.SectionData.Add(snData); } var mdData = new DotNetMetadataSectionData(mdEditor); textSection.SectionData.Add(new ImageCor20HeaderSectionData(mdData, snData)); textSection.SectionData.Add(mdData); // DOS MZ header stream.Write(dosHeader); // PE\0\0 Debug.Assert(stream.Position == BitConverter.ToUInt32(dosHeader, 0x7C)); stream.Write(0x00004550); // IMAGE_FILE_HEADER var ifh = peImage.ImageNTHeaders.FileHeader; stream.Write((ushort)ifh.Machine); Debug.Assert(sections.Count <= ushort.MaxValue); stream.Write((ushort)sections.Count); stream.Write(ifh.TimeDateStamp); stream.Position += 8; // PointerToSymbolTable & NumberOfSymbols stream.Write((ushort)(is32Bit ? 0xE0 : 0xF0)); stream.Write((ushort)ifh.Characteristics); // IMAGE_OPTIONAL_HEADER var optHeaderPos = stream.Position; if (is32Bit) { var opt = (ImageOptionalHeader32)peImage.ImageNTHeaders.OptionalHeader; var start = stream.Position; stream.Write(opt.Magic); stream.Write(opt.MajorLinkerVersion); stream.Write(opt.MinorLinkerVersion); // SizeOfCode, SizeOfInitializedData, SizeOfUninitializedData // AddressOfEntryPoint, BaseOfCode, BaseOfData stream.Position += 6 * 4; stream.Write((uint)opt.ImageBase); stream.Write((uint)SectionAlignment); stream.Write((uint)FileAlignment); stream.Write(opt.MajorOperatingSystemVersion); stream.Write(opt.MinorOperatingSystemVersion); stream.Write(opt.MajorImageVersion); stream.Write(opt.MinorImageVersion); stream.Write(opt.MajorSubsystemVersion); stream.Write(opt.MinorSubsystemVersion); stream.Write(opt.Win32VersionValue); // SizeOfImage, SizeOfHeaders, CheckSum stream.Position += 3 * 4; stream.Write((ushort)opt.Subsystem); stream.Write((ushort)opt.DllCharacteristics); stream.Write((uint)opt.SizeOfStackReserve); stream.Write((uint)opt.SizeOfStackCommit); stream.Write((uint)opt.SizeOfHeapReserve); stream.Write((uint)opt.SizeOfHeapCommit); stream.Write(opt.LoaderFlags); stream.Write(0x10); // NumberOfRvaAndSizes Debug.Assert((stream.Position - start) == 0x60); } else { var opt = (ImageOptionalHeader64)peImage.ImageNTHeaders.OptionalHeader; var start = stream.Position; stream.Write(opt.Magic); stream.Write(opt.MajorLinkerVersion); stream.Write(opt.MinorLinkerVersion); // SizeOfCode, SizeOfInitializedData, SizeOfUninitializedData // AddressOfEntryPoint, BaseOfCode stream.Position += 5 * 4; stream.Write(opt.ImageBase); stream.Write((uint)SectionAlignment); stream.Write((uint)FileAlignment); stream.Write(opt.MajorOperatingSystemVersion); stream.Write(opt.MinorOperatingSystemVersion); stream.Write(opt.MajorImageVersion); stream.Write(opt.MinorImageVersion); stream.Write(opt.MajorSubsystemVersion); stream.Write(opt.MinorSubsystemVersion); stream.Write(opt.Win32VersionValue); // SizeOfImage, SizeOfHeaders, CheckSum stream.Position += 3 * 4; stream.Write((ushort)opt.Subsystem); stream.Write((ushort)opt.DllCharacteristics); stream.Write(opt.SizeOfStackReserve); stream.Write(opt.SizeOfStackCommit); stream.Write(opt.SizeOfHeapReserve); stream.Write(opt.SizeOfHeapCommit); stream.Write(opt.LoaderFlags); stream.Write(0x10); // NumberOfRvaAndSizes Debug.Assert((stream.Position - start) == 0x70); } // IMAGE_DATA_DIRECTORY dataDirPosition = stream.Position; stream.Position += 0x10 * 8; // IMAGE_SECTION_HEADER var sectionPos = stream.Position; foreach (var section in sections) { Debug.Assert(section.Name.Length == 8); stream.Write(section.Name); // VirtualSize, VirtualAddress, SizeOfRawData, PointerToRawData // PointerToRelocations, PointerToLinenumbers, NumberOfRelocations, NumberOfLinenumbers stream.Position += 6 * 4 + 2 * 2; stream.Write(section.Characteristics); } uint headerLength = (uint)stream.Position; AlignUp(FileAlignment); // Write all sections uint rva = SectionAlignment; foreach (var section in sections) { section.VirtualAddress = rva; section.PointerToRawData = (uint)stream.Position; foreach (var data in section.SectionData) { var pos = stream.Position; AlignUp(data.Alignment); rva += (uint)(stream.Position - pos); pos = stream.Position; data.Write(this, rva, stream); rva += (uint)(stream.Position - pos); } Debug.Assert(stream.Position != section.PointerToRawData); if (stream.Position == section.PointerToRawData) { stream.Position++; } section.VirtualSize = (uint)stream.Position - section.PointerToRawData; section.SizeOfRawData = ((uint)stream.Position - section.PointerToRawData + FileAlignment - 1) & ~(FileAlignment - 1); rva = (rva + SectionAlignment - 1) & ~(SectionAlignment - 1); AlignUp(FileAlignment); } stream.Length = stream.Position; // Update IMAGE_SECTION_HEADER stream.Position = sectionPos; foreach (var section in sections) { stream.Position += 8; stream.Write(section.VirtualSize); stream.Write(section.VirtualAddress); stream.Write(section.SizeOfRawData); stream.Write(section.PointerToRawData); stream.Position += 16; } // Update IMAGE_OPTIONAL_HEADER var sectionSizes = new SectionSizes(FileAlignment, SectionAlignment, headerLength, () => GetSectionSizeInfos()); stream.Position = optHeaderPos; if (is32Bit) { var opt = (ImageOptionalHeader32)peImage.ImageNTHeaders.OptionalHeader; stream.Position += 4; stream.Write(sectionSizes.SizeOfCode); stream.Write(sectionSizes.SizeOfInitdData); stream.Write(sectionSizes.SizeOfUninitdData); stream.Position += 4; stream.Write(sectionSizes.BaseOfCode); stream.Write(sectionSizes.BaseOfData); stream.Position += 0x1C; stream.Write(sectionSizes.SizeOfImage); stream.Write(sectionSizes.SizeOfHeaders); } else { var opt = (ImageOptionalHeader64)peImage.ImageNTHeaders.OptionalHeader; stream.Position += 4; stream.Write(sectionSizes.SizeOfCode); stream.Write(sectionSizes.SizeOfInitdData); stream.Write(sectionSizes.SizeOfUninitdData); stream.Position += 4; stream.Write(sectionSizes.BaseOfCode); stream.Position += 0x20; stream.Write(sectionSizes.SizeOfImage); stream.Write(sectionSizes.SizeOfHeaders); } foreach (var section in sections) { foreach (var data in section.SectionData) { data.Finish(this, stream); } } }
public ImageCor20HeaderSectionData(DotNetMetadataSectionData mdData, StrongNameSignatureSectionData?snData) { this.mdData = mdData; this.snData = snData; }