Beispiel #1
0
        /// <summary>
        /// Relocate the produced PE file and output the result into a given stream.
        /// </summary>
        /// <param name="peFile">Blob builder representing the complete PE file</param>
        /// <param name="defaultImageBase">Default load address for the image</param>
        /// <param name="corHeaderBuilder">COR header</param>
        /// <param name="corHeaderFileOffset">File position of the COR header</param>
        /// <param name="outputStream">Stream to receive the relocated PE file</param>
        public void RelocateOutputFile(
            BlobBuilder peFile,
            ulong defaultImageBase,
            CorHeaderBuilder corHeaderBuilder,
            int corHeaderFileOffset,
            Stream outputStream)
        {
            RelocationHelper relocationHelper = new RelocationHelper(outputStream, defaultImageBase, peFile);

            if (corHeaderBuilder != null)
            {
                relocationHelper.CopyToFilePosition(corHeaderFileOffset);
                UpdateCorHeader(corHeaderBuilder);
                BlobBuilder corHeaderBlob = new BlobBuilder();
                corHeaderBuilder.WriteTo(corHeaderBlob);
                int writtenSize = corHeaderBlob.Count;
                corHeaderBlob.WriteContentTo(outputStream);
                relocationHelper.AdvanceOutputPos(writtenSize);

                // Just skip the bytes that were emitted by the COR header writer
                byte[] skipBuffer = new byte[writtenSize];
                relocationHelper.CopyBytesToBuffer(skipBuffer, writtenSize);
            }

            // Traverse relocations in all sections in their RVA order
            foreach (Section section in _sections.OrderBy((sec) => sec.RVAWhenPlaced))
            {
                int rvaToFilePosDelta = section.FilePosWhenPlaced - section.RVAWhenPlaced;
                foreach (ObjectDataRelocations objectDataRelocs in section.Relocations)
                {
                    foreach (Relocation relocation in objectDataRelocs.Relocs)
                    {
                        // Process a single relocation
                        int relocationRVA     = section.RVAWhenPlaced + objectDataRelocs.Offset + relocation.Offset;
                        int relocationFilePos = relocationRVA + rvaToFilePosDelta;

                        // Flush parts of PE file before the relocation to the output stream
                        relocationHelper.CopyToFilePosition(relocationFilePos);

                        // Look up relocation target
                        SymbolTarget relocationTarget = _symbolMap[relocation.Target];
                        Section      targetSection    = _sections[relocationTarget.SectionIndex];
                        int          targetRVA        = targetSection.RVAWhenPlaced + relocationTarget.Offset;

                        // Apply the relocation
                        relocationHelper.ProcessRelocation(relocation.RelocType, relocationRVA, targetRVA);
                    }
                }
            }

            // Flush remaining PE file blocks after the last relocation
            relocationHelper.CopyRestOfFile();
        }
Beispiel #2
0
        /// <summary>
        /// Relocate the produced PE file and output the result into a given stream.
        /// </summary>
        /// <param name="peFile">Blob builder representing the complete PE file</param>
        /// <param name="defaultImageBase">Default load address for the image</param>
        /// <param name="corHeaderBuilder">COR header</param>
        /// <param name="corHeaderFileOffset">File position of the COR header</param>
        /// <param name="outputStream">Stream to receive the relocated PE file</param>
        public void RelocateOutputFile(
            BlobBuilder peFile,
            ulong defaultImageBase,
            Stream outputStream)
        {
            RelocationHelper relocationHelper = new RelocationHelper(outputStream, defaultImageBase, peFile);

            // Traverse relocations in all sections in their RVA order
            foreach (Section section in _sections.OrderBy((sec) => sec.RVAWhenPlaced))
            {
                int rvaToFilePosDelta = section.FilePosWhenPlaced - section.RVAWhenPlaced;
                foreach (PlacedObjectData placedObjectData in section.PlacedObjectDataToRelocate)
                {
                    foreach (Relocation relocation in placedObjectData.Relocs)
                    {
                        // Process a single relocation
                        int relocationRVA     = section.RVAWhenPlaced + placedObjectData.Offset + relocation.Offset;
                        int relocationFilePos = relocationRVA + rvaToFilePosDelta;

                        // Flush parts of PE file before the relocation to the output stream
                        relocationHelper.CopyToFilePosition(relocationFilePos);

                        // Look up relocation target
                        SymbolTarget relocationTarget  = _symbolMap[relocation.Target];
                        Section      targetSection     = _sections[relocationTarget.SectionIndex];
                        int          targetRVA         = targetSection.RVAWhenPlaced + relocationTarget.Offset;
                        int          filePosWhenPlaced = targetSection.FilePosWhenPlaced + relocationTarget.Offset;

                        // If relocating to a node's size, switch out the target RVA with data length
                        if (relocation.RelocType == RelocType.IMAGE_REL_SYMBOL_SIZE)
                        {
                            targetRVA = relocationTarget.Size;
                        }

                        // Apply the relocation
                        relocationHelper.ProcessRelocation(relocation.RelocType, relocationRVA, targetRVA, filePosWhenPlaced);
                    }
                }
            }

            // Flush remaining PE file blocks after the last relocation
            relocationHelper.CopyRestOfFile();
        }