/// <summary> /// Writes the PE _header. /// </summary> /// <param name="writer">The writer.</param> private void WritePEHeader(BinaryWriter writer) { // Write the PE signature and headers ntHeaders.Signature = IMAGE_NT_HEADERS.PE_SIGNATURE; // Prepare the file _header ntHeaders.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386; ntHeaders.FileHeader.NumberOfSections = CountSections(); ntHeaders.FileHeader.TimeDateStamp = (uint)(DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds; ntHeaders.FileHeader.PointerToSymbolTable = 0; ntHeaders.FileHeader.NumberOfSymbols = 0; ntHeaders.FileHeader.SizeOfOptionalHeader = 0x00E0; ntHeaders.FileHeader.Characteristics = 0x010E; // FIXME: Use an enum here // Prepare the "optional" headers ntHeaders.OptionalHeader.Magic = IMAGE_OPTIONAL_HEADER.IMAGE_OPTIONAL_HEADER_MAGIC; ntHeaders.OptionalHeader.MajorLinkerVersion = 6; ntHeaders.OptionalHeader.MinorLinkerVersion = 0; ntHeaders.OptionalHeader.SizeOfCode = AlignValue(GetSectionLength(SectionKind.Text), this.sectionAlignment); ntHeaders.OptionalHeader.SizeOfInitializedData = AlignValue(GetSectionLength(SectionKind.Data) + GetSectionLength(SectionKind.ROData), this.sectionAlignment); ntHeaders.OptionalHeader.SizeOfUninitializedData = AlignValue(GetSectionLength(SectionKind.BSS), this.sectionAlignment); ntHeaders.OptionalHeader.AddressOfEntryPoint = (uint)(this.EntryPoint.VirtualAddress.ToInt64() - this.BaseAddress); ntHeaders.OptionalHeader.BaseOfCode = (uint)(GetSectionAddress(SectionKind.Text) - this.BaseAddress); long sectionAddress = GetSectionAddress(SectionKind.Data); if (sectionAddress != 0) { ntHeaders.OptionalHeader.BaseOfData = (uint)(sectionAddress - this.BaseAddress); } ntHeaders.OptionalHeader.ImageBase = (uint)this.BaseAddress; // FIXME: Linker Script/cmdline ntHeaders.OptionalHeader.SectionAlignment = this.sectionAlignment; // FIXME: Linker Script/cmdline ntHeaders.OptionalHeader.FileAlignment = this.fileAlignment; // FIXME: Linker Script/cmdline ntHeaders.OptionalHeader.MajorOperatingSystemVersion = 4; ntHeaders.OptionalHeader.MinorOperatingSystemVersion = 0; ntHeaders.OptionalHeader.MajorImageVersion = 0; ntHeaders.OptionalHeader.MinorImageVersion = 0; ntHeaders.OptionalHeader.MajorSubsystemVersion = 4; ntHeaders.OptionalHeader.MinorSubsystemVersion = 0; ntHeaders.OptionalHeader.Win32VersionValue = 0; ntHeaders.OptionalHeader.SizeOfImage = CalculateSizeOfImage(); ntHeaders.OptionalHeader.SizeOfHeaders = this.fileAlignment; // FIXME: Use the full _header size ntHeaders.OptionalHeader.CheckSum = 0; ntHeaders.OptionalHeader.Subsystem = 0x03; ntHeaders.OptionalHeader.DllCharacteristics = 0x0540; ntHeaders.OptionalHeader.SizeOfStackReserve = 0x100000; ntHeaders.OptionalHeader.SizeOfStackCommit = 0x1000; ntHeaders.OptionalHeader.SizeOfHeapReserve = 0x100000; ntHeaders.OptionalHeader.SizeOfHeapCommit = 0x1000; ntHeaders.OptionalHeader.LoaderFlags = 0; ntHeaders.OptionalHeader.NumberOfRvaAndSizes = IMAGE_OPTIONAL_HEADER.IMAGE_NUMBEROF_DIRECTORY_ENTRIES; ntHeaders.OptionalHeader.DataDirectory = new IMAGE_DATA_DIRECTORY[IMAGE_OPTIONAL_HEADER.IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; // Populate the CIL data directory ntHeaders.OptionalHeader.DataDirectory[14].VirtualAddress = (uint)GetSymbol(CLI_HEADER.SymbolName).VirtualAddress.ToInt64(); ntHeaders.OptionalHeader.DataDirectory[14].Size = CLI_HEADER.Length; ntHeaders.Write(writer); // Write the section headers uint address = this.fileAlignment; foreach (LinkerSection section in this.sections.Values) { if (section.Length > 0) { IMAGE_SECTION_HEADER ish = new IMAGE_SECTION_HEADER(); ish.Name = section.Name; ish.VirtualSize = (uint)section.Length; ish.VirtualAddress = (uint)(section.VirtualAddress.ToInt64() - this.BaseAddress); if (section.SectionKind != SectionKind.BSS) { ish.SizeOfRawData = (uint)section.Length; } ish.PointerToRawData = address; ish.PointerToRelocations = 0; ish.PointerToLinenumbers = 0; ish.NumberOfRelocations = 0; ish.NumberOfLinenumbers = 0; switch (section.SectionKind) { case SectionKind.BSS: ish.Characteristics = 0x40000000 | 0x80000000 | 0x00000080; break; case SectionKind.Data: ish.Characteristics = 0x40000000 | 0x80000000 | 0x00000040; break; case SectionKind.ROData: ish.Characteristics = 0x40000000 | 0x00000040; break; case SectionKind.Text: ish.Characteristics = 0x20000000 | 0x40000000 | 0x80000000 | 0x00000020; break; } ish.Write(writer); address += (uint)section.Length; address = AlignValue(address, this.fileAlignment); } } WritePaddingToPosition(writer, this.fileAlignment); }
/// <summary> /// Writes the PE _header. /// </summary> /// <param name="writer">The writer.</param> private void WritePEHeader(BinaryWriter writer) { // Write the PE signature and headers ntHeaders.Signature = IMAGE_NT_HEADERS.PE_SIGNATURE; // Prepare the file _header ntHeaders.FileHeader.Machine = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_I386; ntHeaders.FileHeader.NumberOfSections = CountSections(); ntHeaders.FileHeader.TimeDateStamp = (uint)(DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds; ntHeaders.FileHeader.PointerToSymbolTable = 0; ntHeaders.FileHeader.NumberOfSymbols = 0; ntHeaders.FileHeader.SizeOfOptionalHeader = 0x00E0; ntHeaders.FileHeader.Characteristics = 0x010E; // FIXME: Use an enum here // Prepare the "optional" headers ntHeaders.OptionalHeader.Magic = IMAGE_OPTIONAL_HEADER.IMAGE_OPTIONAL_HEADER_MAGIC; ntHeaders.OptionalHeader.MajorLinkerVersion = 6; ntHeaders.OptionalHeader.MinorLinkerVersion = 0; ntHeaders.OptionalHeader.SizeOfCode = AlignValue(GetSectionLength(SectionKind.Text), this.sectionAlignment); ntHeaders.OptionalHeader.SizeOfInitializedData = AlignValue(GetSectionLength(SectionKind.Data) + GetSectionLength(SectionKind.ROData), this.sectionAlignment); ntHeaders.OptionalHeader.SizeOfUninitializedData = AlignValue(GetSectionLength(SectionKind.BSS), this.sectionAlignment); ntHeaders.OptionalHeader.AddressOfEntryPoint = (uint)(this.EntryPoint.VirtualAddress.ToInt64() - this.BaseAddress); ntHeaders.OptionalHeader.BaseOfCode = (uint)(GetSectionAddress(SectionKind.Text) - this.BaseAddress); long sectionAddress = GetSectionAddress(SectionKind.Data); if (sectionAddress != 0) ntHeaders.OptionalHeader.BaseOfData = (uint)(sectionAddress - this.BaseAddress); ntHeaders.OptionalHeader.ImageBase = (uint)this.BaseAddress; // FIXME: Linker Script/cmdline ntHeaders.OptionalHeader.SectionAlignment = this.sectionAlignment; // FIXME: Linker Script/cmdline ntHeaders.OptionalHeader.FileAlignment = this.fileAlignment; // FIXME: Linker Script/cmdline ntHeaders.OptionalHeader.MajorOperatingSystemVersion = 4; ntHeaders.OptionalHeader.MinorOperatingSystemVersion = 0; ntHeaders.OptionalHeader.MajorImageVersion = 0; ntHeaders.OptionalHeader.MinorImageVersion = 0; ntHeaders.OptionalHeader.MajorSubsystemVersion = 4; ntHeaders.OptionalHeader.MinorSubsystemVersion = 0; ntHeaders.OptionalHeader.Win32VersionValue = 0; ntHeaders.OptionalHeader.SizeOfImage = CalculateSizeOfImage(); ntHeaders.OptionalHeader.SizeOfHeaders = this.fileAlignment; // FIXME: Use the full _header size ntHeaders.OptionalHeader.CheckSum = 0; ntHeaders.OptionalHeader.Subsystem = 0x03; ntHeaders.OptionalHeader.DllCharacteristics = 0x0540; ntHeaders.OptionalHeader.SizeOfStackReserve = 0x100000; ntHeaders.OptionalHeader.SizeOfStackCommit = 0x1000; ntHeaders.OptionalHeader.SizeOfHeapReserve = 0x100000; ntHeaders.OptionalHeader.SizeOfHeapCommit = 0x1000; ntHeaders.OptionalHeader.LoaderFlags = 0; ntHeaders.OptionalHeader.NumberOfRvaAndSizes = IMAGE_OPTIONAL_HEADER.IMAGE_NUMBEROF_DIRECTORY_ENTRIES; ntHeaders.OptionalHeader.DataDirectory = new IMAGE_DATA_DIRECTORY[IMAGE_OPTIONAL_HEADER.IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; // Populate the CIL data directory ntHeaders.OptionalHeader.DataDirectory[14].VirtualAddress = (uint)GetSymbol(CLI_HEADER.SymbolName).VirtualAddress.ToInt64(); ntHeaders.OptionalHeader.DataDirectory[14].Size = CLI_HEADER.Length; ntHeaders.Write(writer); // Write the section headers uint address = this.fileAlignment; foreach (LinkerSection section in this.sections.Values) { if (section.Length > 0) { IMAGE_SECTION_HEADER ish = new IMAGE_SECTION_HEADER(); ish.Name = section.Name; ish.VirtualSize = (uint)section.Length; ish.VirtualAddress = (uint)(section.VirtualAddress.ToInt64() - this.BaseAddress); if (section.SectionKind != SectionKind.BSS) ish.SizeOfRawData = (uint)section.Length; ish.PointerToRawData = address; ish.PointerToRelocations = 0; ish.PointerToLinenumbers = 0; ish.NumberOfRelocations = 0; ish.NumberOfLinenumbers = 0; switch (section.SectionKind) { case SectionKind.BSS: ish.Characteristics = 0x40000000 | 0x80000000 | 0x00000080; break; case SectionKind.Data: ish.Characteristics = 0x40000000 | 0x80000000 | 0x00000040; break; case SectionKind.ROData: ish.Characteristics = 0x40000000 | 0x00000040; break; case SectionKind.Text: ish.Characteristics = 0x20000000 | 0x40000000 | 0x80000000 | 0x00000020; break; } ish.Write(writer); address += (uint)section.Length; address = AlignValue(address, this.fileAlignment); } } WritePaddingToPosition(writer, this.fileAlignment); }