예제 #1
0
        public void RebuildNetPEAddSection()
        {
            const string fileName    = "HelloWorld";
            const string sectionName = ".test";
            var          sectionData = new byte[] { 1, 3, 3, 7 };

            var peFile = PEFile.FromBytes(Properties.Resources.HelloWorld);

            // Add a new section.
            peFile.Sections.Add(new PESection(sectionName, SectionFlags.MemoryRead | SectionFlags.ContentInitializedData)
            {
                Contents = new DataSegment(sectionData)
            });

            // Rebuild and check if file is still runnable.
            _fixture
            .GetRunner <FrameworkPERunner>()
            .RebuildAndRun(peFile, fileName, "Hello World!" + Environment.NewLine);

            // Read the new file.
            var newPEFile = PEFile.FromFile(_fixture
                                            .GetRunner <FrameworkPERunner>()
                                            .GetTestExecutablePath(nameof(PEFileTest), nameof(RebuildNetPEAddSection), fileName));

            // Verify the section and its data is present:
            var newSection = newPEFile.Sections.First(s => s.Name == sectionName);
            var newData    = new byte[sectionData.Length];

            Assert.Equal(sectionData.Length, newSection
                         .CreateReader()
                         .ReadBytes(newData, 0, newData.Length));
            Assert.Equal(sectionData, newData);
        }
예제 #2
0
        public void PreserveMetadataNoChange()
        {
            var peFile   = PEFile.FromBytes(Properties.Resources.HelloWorld);
            var peImage  = PEImage.FromFile(peFile);
            var metadata = peImage.DotNetDirectory.Metadata;

            using var tempStream = new MemoryStream();
            metadata.Write(new BinaryStreamWriter(tempStream));

            var newMetadata = new SerializedMetadata(new PEReaderContext(peFile), new ByteArrayReader(tempStream.ToArray()));

            Assert.Equal(metadata.MajorVersion, newMetadata.MajorVersion);
            Assert.Equal(metadata.MinorVersion, newMetadata.MinorVersion);
            Assert.Equal(metadata.Reserved, newMetadata.Reserved);
            Assert.Equal(metadata.VersionString, newMetadata.VersionString);
            Assert.Equal(metadata.Flags, newMetadata.Flags);

            Assert.Equal(metadata.Streams.Count, newMetadata.Streams.Count);
            for (int i = 0; i < metadata.Streams.Count; i++)
            {
                var oldStream = metadata.Streams[i];
                var newStream = newMetadata.Streams[i];

                Assert.Equal(oldStream.Name, newStream.Name);
                var oldData = oldStream.CreateReader().ReadToEnd();
                var newData = newStream.CreateReader().ReadToEnd();
                Assert.Equal(oldData, newData);
            }
        }
예제 #3
0
        public void PreserveTableStreamNoChange()
        {
            var peFile       = PEFile.FromBytes(Properties.Resources.HelloWorld);
            var peImage      = PEImage.FromFile(peFile);
            var tablesStream = peImage.DotNetDirectory.Metadata.GetStream <TablesStream>();

            using var tempStream = new MemoryStream();
            tablesStream.Write(new BinaryStreamWriter(tempStream));

            var newTablesStream = new SerializedTableStream(tablesStream.Name, tempStream.ToArray(), peFile);

            Assert.Equal(tablesStream.Reserved, newTablesStream.Reserved);
            Assert.Equal(tablesStream.MajorVersion, newTablesStream.MajorVersion);
            Assert.Equal(tablesStream.MinorVersion, newTablesStream.MinorVersion);
            Assert.Equal(tablesStream.Flags, newTablesStream.Flags);
            Assert.Equal(tablesStream.Log2LargestRid, newTablesStream.Log2LargestRid);
            Assert.Equal(tablesStream.ExtraData, newTablesStream.ExtraData);

            for (TableIndex i = 0; i <= TableIndex.GenericParamConstraint; i++)
            {
                var oldTable = tablesStream.GetTable(i);
                var newTable = newTablesStream.GetTable(i);

                Assert.Equal(oldTable.Count, newTable.Count);
                for (int j = 0; j < oldTable.Count; j++)
                {
                    Assert.Equal(oldTable[j], newTable[j]);
                }
            }
        }
예제 #4
0
        public void RebuildNetPENoChange()
        {
            var peFile = PEFile.FromBytes(Properties.Resources.HelloWorld);

            _fixture
            .GetRunner <FrameworkPERunner>()
            .RebuildAndRun(peFile, "HelloWorld", "Hello World!" + Environment.NewLine);
        }
예제 #5
0
        public void RemoveSectionShouldPersistOtherSectionContents()
        {
            var peFile = PEFile.FromBytes(Properties.Resources.HelloWorld);

            var section = peFile.Sections[1];

            byte[] contents = ((IReadableSegment)section.Contents).ToArray();

            peFile.Sections.RemoveAt(0);

            peFile.UpdateHeaders();

            byte[] contents2 = ((IReadableSegment)section.Contents).ToArray();
            Assert.Equal(contents, contents2);
        }
예제 #6
0
        public void InsertSectionShouldPersistOtherSectionContents()
        {
            var peFile = PEFile.FromBytes(Properties.Resources.HelloWorld);

            var section = peFile.Sections[0];

            byte[] contents = ((IReadableSegment)section.Contents).ToArray();

            peFile.Sections.Insert(0, new PESection(".test",
                                                    SectionFlags.MemoryRead | SectionFlags.MemoryWrite | SectionFlags.ContentInitializedData,
                                                    new DataSegment(new byte[] { 1, 2, 3, 4 })));

            peFile.UpdateHeaders();

            byte[] contents2 = ((IReadableSegment)section.Contents).ToArray();
            Assert.Equal(contents, contents2);
        }
예제 #7
0
        public void RoundTripPE()
        {
            // This test validates that a PE can be loaded, copied, and written, without altering the data

            var originalBytes = Properties.Resources.NativeMemoryDemos;
            var peFile        = PEFile.FromBytes(originalBytes);

            var msOutput = new MemoryStream();
            var output   = new PEFile(peFile.DosHeader, peFile.FileHeader, peFile.OptionalHeader);

            foreach (var section in peFile.Sections)
            {
                var newSection = new PESection(section);
                output.Sections.Add(newSection);
            }
            output.Write(new BinaryStreamWriter(msOutput));
            Assert.Equal(originalBytes, msOutput.ToArray());
        }
예제 #8
0
        /// <summary>
        /// Finalizes a delay-signed PE image.
        /// </summary>
        /// <param name="imageStream">The stream containing the image to sign.</param>
        /// <param name="hashAlgorithm">The hashing algorithm to use.</param>
        /// <exception cref="BadImageFormatException">Occurs when the image does not contain a valid .NET image.</exception>
        /// <exception cref="ArgumentException">Occurs when the image does not contain a strong name directory of the right size.</exception>
        public void SignImage(Stream imageStream, AssemblyHashAlgorithm hashAlgorithm)
        {
            imageStream.Position = 0;
            using var streamCopy = new MemoryStream();
            imageStream.CopyTo(streamCopy);
            streamCopy.Position = 0;

            var file  = PEFile.FromBytes(streamCopy.ToArray());
            var image = PEImage.FromFile(file);

            // Check existence of .NET metadata.
            if (image.DotNetDirectory is null)
            {
                throw new BadImageFormatException("Input image is not a .NET assembly.");
            }

            // Check existence of a valid sn directory.
            var strongNameDirectory = image.DotNetDirectory.StrongName;

            if (strongNameDirectory is null)
            {
                throw new ArgumentException("Cannot sign an image without a strong name directory.");
            }

            if (PrivateKey.Modulus.Length != strongNameDirectory.GetPhysicalSize())
            {
                throw new ArgumentException(
                          "The strong name signature directory size does not match the size of the strong signature.");
            }

            // Compute hash of pseudo PE file.
            var hash = GetHashToSign(streamCopy, file, image, hashAlgorithm);

            // Compute strong name signature.
            var signature = ComputeSignature(hashAlgorithm, hash);

            // Copy strong name signature into target PE.
            imageStream.Position = (long)strongNameDirectory.Offset;
            imageStream.Write(signature, 0, signature.Length);
        }
예제 #9
0
        public void SectionsInMappedBinaryShouldUseVirtualAddressesAsOffset()
        {
            var physicalFile = PEFile.FromBytes(Properties.Resources.HelloWorld);
            var memoryFile   = PEFile.FromDataSource(
                new ByteArrayDataSource(Properties.Resources.HelloWorldDump),
                PEMappingMode.Mapped);

            Assert.Equal(physicalFile.Sections.Count, memoryFile.Sections.Count);
            for (int i = 0; i < physicalFile.Sections.Count; i++)
            {
                var physicalSection = physicalFile.Sections[i];
                var memorySection   = memoryFile.Sections[i];

                Assert.NotEqual(physicalSection.Offset, memorySection.Offset);
                Assert.Equal(physicalSection.Rva, memorySection.Rva);

                byte[] expected = new byte[20];
                physicalSection.CreateReader().ReadBytes(expected, 0, expected.Length);
                byte[] actual = new byte[20];
                memorySection.CreateReader().ReadBytes(actual, 0, actual.Length);
                Assert.Equal(expected, actual);
            }
        }
 /// <summary>
 /// Opens a PE image from a buffer.
 /// </summary>
 /// <param name="bytes">The bytes to interpret.</param>
 /// <param name="readParameters">The parameters to use while reading the PE image.</param>
 /// <returns>The PE image that was opened.</returns>
 /// <exception cref="BadImageFormatException">Occurs when the file does not follow the PE file format.</exception>
 public static IPEImage FromBytes(byte[] bytes, PEReadParameters readParameters) =>
 FromFile(PEFile.FromBytes(bytes), readParameters);
 /// <summary>
 /// Opens a PE image from a buffer.
 /// </summary>
 /// <param name="bytes">The bytes to interpret.</param>
 /// <returns>The PE image that was opened.</returns>
 /// <exception cref="BadImageFormatException">Occurs when the file does not follow the PE file format.</exception>
 public static IPEImage FromBytes(byte[] bytes) => FromFile(PEFile.FromBytes(bytes));
예제 #12
0
        public void InvalidFileOffsetToRva()
        {
            var peFile = PEFile.FromBytes(Properties.Resources.HelloWorld);

            Assert.Throws <ArgumentOutOfRangeException>(() => peFile.FileOffsetToRva(0x2000));
        }
예제 #13
0
        public void ValidFileOffsetToRva()
        {
            var peFile = PEFile.FromBytes(Properties.Resources.HelloWorld);

            Assert.Equal(0x0000268Eu, peFile.FileOffsetToRva(0x0000088Eu));
        }