Ejemplo n.º 1
0
        /// <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(PE.CLI_HEADER.SymbolName).VirtualAddress.ToInt64();
            ntHeaders.OptionalHeader.DataDirectory[14].Size = PE.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);
        }
Ejemplo n.º 2
0
        /// <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(PE.CLI_HEADER.SymbolName).VirtualAddress.ToInt64();
            ntHeaders.OptionalHeader.DataDirectory[14].Size           = PE.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);
        }