예제 #1
0
파일: PeWriter.cs 프로젝트: noahfalk/roslyn
        private void WriteHeaders(Stream peStream, NtHeader ntHeader, CoffHeader coffHeader, List<SectionHeader> sectionHeaders, out long ntHeaderTimestampPosition)
        {
            var writer = PooledBlobBuilder.GetInstance();

            // MS-DOS stub (128 bytes)
            writer.WriteBytes(s_dosHeader);

            // PE Signature "PE\0\0" 
            writer.WriteUInt32(0x00004550);

            // COFF Header (20 bytes)
            writer.WriteUInt16((ushort)coffHeader.Machine);
            writer.WriteUInt16((ushort)coffHeader.NumberOfSections);
            ntHeaderTimestampPosition = writer.Position + peStream.Position;
            writer.WriteUInt32((uint)coffHeader.TimeDateStamp);
            writer.WriteUInt32((uint)coffHeader.PointerToSymbolTable);
            writer.WriteUInt32((uint)coffHeader.NumberOfSymbols);
            writer.WriteUInt16((ushort)(_is32bit ? 224 : 240)); // SizeOfOptionalHeader
            writer.WriteUInt16((ushort)coffHeader.Characteristics);

            // PE Headers:
            writer.WriteUInt16((ushort)(_is32bit ? PEMagic.PE32 : PEMagic.PE32Plus)); // 2
            writer.WriteByte(ntHeader.MajorLinkerVersion); // 3
            writer.WriteByte(ntHeader.MinorLinkerVersion); // 4
            writer.WriteUInt32((uint)ntHeader.SizeOfCode); // 8
            writer.WriteUInt32((uint)ntHeader.SizeOfInitializedData); // 12
            writer.WriteUInt32((uint)ntHeader.SizeOfUninitializedData); // 16
            writer.WriteUInt32((uint)ntHeader.AddressOfEntryPoint); // 20
            writer.WriteUInt32((uint)ntHeader.BaseOfCode); // 24

            if (_is32bit)
            {
                writer.WriteUInt32((uint)ntHeader.BaseOfData); // 28
                writer.WriteUInt32((uint)ntHeader.ImageBase); // 32
            }
            else
            {
                writer.WriteUInt64(ntHeader.ImageBase); // 32
            }

            // NT additional fields:
            writer.WriteUInt32((uint)ntHeader.SectionAlignment); // 36
            writer.WriteUInt32((uint)ntHeader.FileAlignment); // 40
            writer.WriteUInt16(ntHeader.MajorOperatingSystemVersion); // 42
            writer.WriteUInt16(ntHeader.MinorOperatingSystemVersion); // 44
            writer.WriteUInt16(ntHeader.MajorImageVersion); // 46
            writer.WriteUInt16(ntHeader.MinorImageVersion); // 48
            writer.WriteUInt16(ntHeader.MajorSubsystemVersion); // MajorSubsystemVersion 50
            writer.WriteUInt16(ntHeader.MinorSubsystemVersion); // MinorSubsystemVersion 52

            // Win32VersionValue (reserved, should be 0)
            writer.WriteUInt32(0); // 56

            writer.WriteUInt32((uint)ntHeader.SizeOfImage); // 60
            writer.WriteUInt32((uint)ntHeader.SizeOfHeaders); // 64
            writer.WriteUInt32(ntHeader.Checksum); // 68            
            writer.WriteUInt16((ushort)ntHeader.Subsystem); // 70
            writer.WriteUInt16((ushort)ntHeader.DllCharacteristics);

            if (_is32bit)
            {
                writer.WriteUInt32((uint)ntHeader.SizeOfStackReserve); // 76
                writer.WriteUInt32((uint)ntHeader.SizeOfStackCommit); // 80
                writer.WriteUInt32((uint)ntHeader.SizeOfHeapReserve); // 84
                writer.WriteUInt32((uint)ntHeader.SizeOfHeapCommit); // 88
            }
            else
            {
                writer.WriteUInt64(ntHeader.SizeOfStackReserve); // 80
                writer.WriteUInt64(ntHeader.SizeOfStackCommit); // 88
                writer.WriteUInt64(ntHeader.SizeOfHeapReserve); // 96
                writer.WriteUInt64(ntHeader.SizeOfHeapCommit); // 104
            }

            // LoaderFlags
            writer.WriteUInt32(0); // 92|108

            // The number of data-directory entries in the remainder of the header.
            writer.WriteUInt32(16); //  96|112

            // directory entries:
            writer.WriteUInt32((uint)ntHeader.ExportTable.RelativeVirtualAddress); // 100|116
            writer.WriteUInt32((uint)ntHeader.ExportTable.Size); // 104|120
            writer.WriteUInt32((uint)ntHeader.ImportTable.RelativeVirtualAddress); // 108|124
            writer.WriteUInt32((uint)ntHeader.ImportTable.Size); // 112|128
            writer.WriteUInt32((uint)ntHeader.ResourceTable.RelativeVirtualAddress); // 116|132
            writer.WriteUInt32((uint)ntHeader.ResourceTable.Size); // 120|136
            writer.WriteUInt32((uint)ntHeader.ExceptionTable.RelativeVirtualAddress); // 124|140
            writer.WriteUInt32((uint)ntHeader.ExceptionTable.Size); // 128|144
            writer.WriteUInt32((uint)ntHeader.CertificateTable.RelativeVirtualAddress); // 132|148
            writer.WriteUInt32((uint)ntHeader.CertificateTable.Size); // 136|152
            writer.WriteUInt32((uint)ntHeader.BaseRelocationTable.RelativeVirtualAddress); // 140|156
            writer.WriteUInt32((uint)ntHeader.BaseRelocationTable.Size); // 144|160
            writer.WriteUInt32((uint)ntHeader.DebugTable.RelativeVirtualAddress); // 148|164
            writer.WriteUInt32((uint)ntHeader.DebugTable.Size); // 152|168
            writer.WriteUInt32((uint)ntHeader.CopyrightTable.RelativeVirtualAddress); // 156|172
            writer.WriteUInt32((uint)ntHeader.CopyrightTable.Size); // 160|176
            writer.WriteUInt32((uint)ntHeader.GlobalPointerTable.RelativeVirtualAddress); // 164|180
            writer.WriteUInt32((uint)ntHeader.GlobalPointerTable.Size); // 168|184
            writer.WriteUInt32((uint)ntHeader.ThreadLocalStorageTable.RelativeVirtualAddress); // 172|188
            writer.WriteUInt32((uint)ntHeader.ThreadLocalStorageTable.Size); // 176|192
            writer.WriteUInt32((uint)ntHeader.LoadConfigTable.RelativeVirtualAddress); // 180|196
            writer.WriteUInt32((uint)ntHeader.LoadConfigTable.Size); // 184|200
            writer.WriteUInt32((uint)ntHeader.BoundImportTable.RelativeVirtualAddress); // 188|204
            writer.WriteUInt32((uint)ntHeader.BoundImportTable.Size); // 192|208
            writer.WriteUInt32((uint)ntHeader.ImportAddressTable.RelativeVirtualAddress); // 196|212
            writer.WriteUInt32((uint)ntHeader.ImportAddressTable.Size); // 200|216
            writer.WriteUInt32((uint)ntHeader.DelayImportTable.RelativeVirtualAddress); // 204|220
            writer.WriteUInt32((uint)ntHeader.DelayImportTable.Size); // 208|224
            writer.WriteUInt32((uint)ntHeader.CliHeaderTable.RelativeVirtualAddress); // 212|228
            writer.WriteUInt32((uint)ntHeader.CliHeaderTable.Size); // 216|232
            writer.WriteUInt64(0); // 224|240

            // Section Headers
            foreach (var sectionHeader in sectionHeaders)
            {
                WriteSectionHeader(sectionHeader, writer);
            }

            writer.WriteContentTo(peStream);
            writer.Free();
        }
예제 #2
0
파일: PeWriter.cs 프로젝트: noahfalk/roslyn
        private void FillInNtHeader(
            List<SectionHeader> sectionHeaders, 
            int entryPointAddress,
            DirectoryEntry corHeader,
            DirectoryEntry importTable,
            DirectoryEntry importAddressTable,
            DirectoryEntry debugTable,
            out CoffHeader coffHeader,
            out NtHeader ntHeader)
        {
            short sectionCount = (short)sectionHeaders.Count;

            coffHeader = new CoffHeader(
                machine: (_properties.Machine == 0) ? Machine.I386 : _properties.Machine,
                numberOfSections: sectionCount,
                timeDateStamp: _timeStamp,
                pointerToSymbolTable: 0,
                numberOfSymbols: 0,
                sizeOfOptionalHeader: (short)(_is32bit ? 224 : 240), // TODO: constants
                characteristics: _properties.ImageCharacteristics);

            SectionHeader codeSection = sectionHeaders.FirstOrDefault(sh => (sh.Characteristics & SectionCharacteristics.ContainsCode) != 0);
            SectionHeader dataSection = sectionHeaders.FirstOrDefault(sh => (sh.Characteristics & SectionCharacteristics.ContainsInitializedData) != 0);

            ntHeader = new NtHeader();
            ntHeader.Magic = _is32bit ? PEMagic.PE32 : PEMagic.PE32Plus;
            ntHeader.MajorLinkerVersion = _properties.LinkerMajorVersion;
            ntHeader.MinorLinkerVersion = _properties.LinkerMinorVersion;
            ntHeader.AddressOfEntryPoint = entryPointAddress;
            ntHeader.BaseOfCode = codeSection?.RelativeVirtualAddress ?? 0;
            ntHeader.BaseOfData = dataSection?.RelativeVirtualAddress ?? 0;
            ntHeader.ImageBase = _properties.BaseAddress;
            ntHeader.FileAlignment = _properties.FileAlignment;
            ntHeader.MajorSubsystemVersion = _properties.MajorSubsystemVersion;
            ntHeader.MinorSubsystemVersion = _properties.MinorSubsystemVersion;

            ntHeader.Subsystem = _properties.Subsystem;
            ntHeader.DllCharacteristics = _properties.DllCharacteristics;

            ntHeader.SizeOfStackReserve = _properties.SizeOfStackReserve;
            ntHeader.SizeOfStackCommit = _properties.SizeOfStackCommit;
            ntHeader.SizeOfHeapReserve = _properties.SizeOfHeapReserve; 
            ntHeader.SizeOfHeapCommit = _properties.SizeOfHeapCommit;

            ntHeader.SizeOfCode = codeSection?.SizeOfRawData ?? 0;

            ntHeader.SizeOfInitializedData = sectionHeaders.Sum(
                sectionHeader => (sectionHeader.Characteristics & SectionCharacteristics.ContainsInitializedData) != 0 ? sectionHeader.SizeOfRawData : 0);

            ntHeader.SizeOfHeaders = BitArithmeticUtilities.Align(ComputeSizeOfPeHeaders(sectionCount), _properties.FileAlignment);

            var lastSection = sectionHeaders.Last();
            ntHeader.SizeOfImage = BitArithmeticUtilities.Align(lastSection.RelativeVirtualAddress + lastSection.VirtualSize, _properties.SectionAlignment);
            ntHeader.SizeOfUninitializedData = 0;

            ntHeader.ImportAddressTable = importAddressTable;
            ntHeader.CliHeaderTable = corHeader;
            ntHeader.ImportTable = importTable;

            var relocSection = sectionHeaders.FirstOrDefault(sectionHeader => sectionHeader.Name == RelocationSectionName);
            if (relocSection != null)
            {
                ntHeader.BaseRelocationTable = new DirectoryEntry(relocSection.RelativeVirtualAddress, relocSection.VirtualSize);
            }

            ntHeader.DebugTable = debugTable;

            var resourceSection = sectionHeaders.FirstOrDefault(sectionHeader => sectionHeader.Name == ResourceSectionName);
            if (resourceSection != null)
            {
                ntHeader.ResourceTable = new DirectoryEntry(resourceSection.RelativeVirtualAddress, resourceSection.VirtualSize);
            }
        }
예제 #3
0
        private void FillInNtHeader(MetadataSizes metadataSizes, int mappedFieldDataStreamRva)
        {
            // In the PE File Header this is a "Time/Date Stamp" whose description is "Time and date
            // the file was created in seconds since January 1st 1970 00:00:00 or 0"
            // However, when we want to make it deterministic we fill it in (later) with bits from the hash of the full PE file.
            int timeStamp = _deterministic ? 0 : (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;

            int textSectionRva = _textSection.RelativeVirtualAddress;
            
            _coffHeader = new CoffHeader(
                machine: (_properties.Machine == 0) ? Machine.I386 : _properties.Machine,
                numberOfSections: GetSectionCount(),
                timeDateStamp: timeStamp,
                pointerToSymbolTable: 0,
                numberOfSymbols: 0,
                sizeOfOptionalHeader: (short)(_is32bit ? 224 : 240), // TODO: constants
                characteristics: _properties.ImageCharacteristics);

            var ntHeader = _ntHeader = new NtHeader();
            ntHeader.Magic = _is32bit ? PEMagic.PE32 : PEMagic.PE32Plus;
            ntHeader.MajorLinkerVersion = _properties.LinkerMajorVersion;
            ntHeader.MinorLinkerVersion = _properties.LinkerMinorVersion;
            ntHeader.AddressOfEntryPoint = _properties.RequiresStartupStub ? mappedFieldDataStreamRva - (_is32bit ? 6 : 10) : 0; // TODO: constants
            ntHeader.BaseOfCode = textSectionRva;
            ntHeader.BaseOfData = _rdataSection.RelativeVirtualAddress;
            ntHeader.ImageBase = _properties.BaseAddress;
            ntHeader.FileAlignment = _properties.FileAlignment;
            ntHeader.MajorSubsystemVersion = _properties.MajorSubsystemVersion;
            ntHeader.MinorSubsystemVersion = _properties.MinorSubsystemVersion;

            ntHeader.Subsystem = _properties.Subsystem;
            ntHeader.DllCharacteristics = _properties.DllCharacteristics;

            ntHeader.SizeOfStackReserve = _properties.SizeOfStackReserve;
            ntHeader.SizeOfStackCommit = _properties.SizeOfStackCommit;
            ntHeader.SizeOfHeapReserve = _properties.SizeOfHeapReserve; 
            ntHeader.SizeOfHeapCommit = _properties.SizeOfHeapCommit;

            ntHeader.SizeOfCode = _textSection.SizeOfRawData;
            ntHeader.SizeOfInitializedData = _rdataSection.SizeOfRawData + _coverSection.SizeOfRawData + _sdataSection.SizeOfRawData + _tlsSection.SizeOfRawData + _resourceSection.SizeOfRawData + _relocSection.SizeOfRawData;
            ntHeader.SizeOfHeaders = BitArithmeticUtilities.Align(ComputeSizeOfPeHeaders(), _properties.FileAlignment);
            ntHeader.SizeOfImage = BitArithmeticUtilities.Align(_relocSection.RelativeVirtualAddress + _relocSection.VirtualSize, 0x2000);
            ntHeader.SizeOfUninitializedData = 0;

            ntHeader.ImportAddressTable = new DirectoryEntry(
                (_properties.RequiresStartupStub) ? textSectionRva : 0,
                _sizeOfImportAddressTable);

            ntHeader.CliHeaderTable = new DirectoryEntry(
                textSectionRva + _sizeOfImportAddressTable,
                size: 72); // TODO: constants

            if (_properties.RequiresStartupStub)
            {
                ntHeader.ImportTable = new DirectoryEntry(
                    textSectionRva + ComputeOffsetToImportTable(metadataSizes),
                    (_is32bit ? 66 : 70) + 13); // TODO: constants
            }

            ntHeader.BaseRelocationTable = new DirectoryEntry(
                (_properties.RequiresStartupStub) ? _relocSection.RelativeVirtualAddress : 0,
                _relocSection.VirtualSize);

            if (EmitPdb)
            {
                // Only the size of the fixed part of the debug table goes here.
                ntHeader.DebugTable = new DirectoryEntry(
                    _textSection.RelativeVirtualAddress + ComputeOffsetToDebugTable(metadataSizes),
                    ImageDebugDirectoryBaseSize);
            }

            if (_resourceSection.SizeOfRawData > 0)
            {
                ntHeader.ResourceTable = new DirectoryEntry(
                    _resourceSection.RelativeVirtualAddress,
                    _resourceSection.VirtualSize);
            }

            if (_tlsSection.SizeOfRawData > 0)
            {
                ntHeader.ThreadLocalStorageTable = new DirectoryEntry(
                   _tlsSection.RelativeVirtualAddress,
                   _tlsSection.SizeOfRawData);
            }
        }