Ejemplo n.º 1
0
        /// <summary>
        /// Updates the physical location of all sections, and updates the amount of initialized data
        /// </summary>
        public void UpdatePhysicalLayout()
        {
            uint fileAlignment, filePosition;

            switch (optionalStandard.Magic)
            {
            case IMAGE_OPTIONAL_HEADER_STANDARD.MAGIC_PE32:
                fileAlignment = optionalHeader32.FileAlignment;
                filePosition  = optionalHeader32.SizeOfHeaders;
                break;

            case IMAGE_OPTIONAL_HEADER_STANDARD.MAGIC_ROM:
                throw new NotSupportedException();

            case IMAGE_OPTIONAL_HEADER_STANDARD.MAGIC_PE32PLUS:
                fileAlignment = optionalHeader32plus.FileAlignment;
                filePosition  = optionalHeader32plus.SizeOfHeaders;
                break;

            default:
                throw new ArgumentException();
            }

            uint initializedDataSize = 0;

            /* Layout the sections in physical order */
            foreach (var s in sections)
            {
                if (s.ContributesToFileSize)
                {
                    //TODO use null coalecing operator somehow
                    if (s.Data != null)
                    {
                        s.RawSize = PEUtility.AlignUp((uint)s.Data.Length, fileAlignment);
                    }
                    else
                    {
                        s.RawSize = PEUtility.AlignUp(s.RawSize, fileAlignment);
                    }
                    s.PhysicalAddress = filePosition;

                    filePosition        += s.RawSize;
                    initializedDataSize += s.RawSize;
                }
            }

            optionalStandard.SizeOfInitializedData = initializedDataSize;
        }
Ejemplo n.º 2
0
        public void UpdateVirtualLayout(uint initialVirtualAddress = StartingVirtualAddress)
        {
            uint virtualAlignment;

            switch (optionalStandard.Magic)
            {
            case IMAGE_OPTIONAL_HEADER_STANDARD.MAGIC_PE32:
                virtualAlignment = optionalHeader32.SectionAlignment;
                break;

            case IMAGE_OPTIONAL_HEADER_STANDARD.MAGIC_ROM:
                throw new NotSupportedException();

            case IMAGE_OPTIONAL_HEADER_STANDARD.MAGIC_PE32PLUS:
                virtualAlignment = optionalHeader32plus.SectionAlignment;
                break;

            default:
                throw new ArgumentException();
            }

            /*
             * Fix up virtual addresses of the sections.
             * We start at 0x1000 (seems to be the convention)
             * Text should come first, then followed by data, then reloc
             * As we encounter certain sections, we need to update
             * special fields (data directory entries etc.).
             */
            uint virtualPosition        = initialVirtualAddress;
            bool dataSectionEncountered = false;

            foreach (var s in sections)
            {
                //update optional header
                switch (s.Name)
                {
                case TEXT:
                    optionalStandard.BaseOfCode = virtualPosition;
                    break;

                case RDATA:
                case DATA:
                    //PE32 headers want to know where the data starts
                    if (optionalStandard.Magic == IMAGE_OPTIONAL_HEADER_STANDARD.MAGIC_PE32 && !dataSectionEncountered)
                    {
                        dataSectionEncountered      = true;
                        optionalHeader32.BaseOfData = virtualPosition;
                    }
                    break;
                }

                //update virtual address
                if (s.VirtualAddress != virtualPosition)
                {
                    switch (s.Name)
                    {
                    case RSRC:
                        ResourceTable res;
                        using (var ms = new MemoryStream(s.Data))
                        {
                            //need to give it the original RVA 'cause that's important
                            res = new ResourceTable(ms, s.VirtualAddress);
                        }
                        res.UpdateVirtualAddress(virtualPosition);
                        //this is only safe because all I've done is changed the virtual address and reserialized the data
                        //this means the data size can only go DOWN (because of alignment not being included)
                        //do not repeat this anywhere else where the data gets changed
                        s.Data = res.ToArray();
                        goto default;

                    default:
                        s.VirtualAddress = virtualPosition;
                        break;
                    }
                }

                //update size
                if (s.HasUninitializedData)
                {
                    // Leave uninitialized data sizes untouched, their raw size is 0
                }
                else if (s.HasInitializedData && s.HasCode)
                {
                    //TODO really not sure why this is here...
                    // It is possible for the virtual size to be greater than the size of raw data
                    // Leave the virtual size untouched if this is the case
                    if (s.VirtualSize <= s.RawSize)
                    {
                        s.VirtualSize = (uint)s.Data.Length;
                    }
                }

                virtualPosition += PEUtility.AlignUp(s.VirtualSize, virtualAlignment);
            }

            /* Total virtual size is the final virtual address, which includes the initial virtual offset. */
            if (optionalStandard.Magic == IMAGE_OPTIONAL_HEADER_STANDARD.MAGIC_PE32)
            {
                optionalHeader32.SizeOfImage = virtualPosition;
            }
            else
            {
                optionalHeader32plus.SizeOfImage = virtualPosition;
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Layout contents of PE file, updating headers and order sections.
        /// </summary>
        /// <returns>Returns bool describing if layout succeeded.</returns>
        public bool Layout()
        {
            uint virtualAlignment    = optionalHeader.SectionAlignment;
            uint fileAlignment       = optionalHeader.FileAlignment;
            uint totalSize           = 0;
            uint initializedDataSize = 0;

            totalSize += optionalHeader.SizeOfHeaders;
            /* Calculate total physical size required */
            foreach (PESection s in sections)
            {
                totalSize += PEUtility.AlignUp((uint)s.Data.Length, fileAlignment);
            }

            /* Layout the sections in physical order */
            uint filePosition = optionalHeader.SizeOfHeaders;

            sections.Sort(new SectionPhysicalComparer());
            foreach (PESection s in sections)
            {
                if (s.ContributesToFileSize())
                {
                    s.RawSize         = PEUtility.AlignUp((uint)s.Data.Length, fileAlignment);
                    s.PhysicalAddress = filePosition;

                    filePosition        += s.RawSize;
                    initializedDataSize += PEUtility.AlignUp((uint)s.Data.Length, fileAlignment);
                }
                break;
            }

            optionalHeader.SizeOfInitializedData = initializedDataSize;

            /*
             * Fix up virtual addresses of the sections.
             * We start at 0x1000 (seems to be the convention)
             * Text should come first, then followed by data, then reloc
             * As we encounter certain sections, we need to update
             * special fields (data directory entries etc.).
             */
            uint virtAddr = 0x1000;
            bool dataSectionEncountered = false;

            sections.Sort(new SectionVirtualComparer());
            foreach (PESection s in sections)
            {
                if (s.Name == ".text")
                {
                    optionalHeader.BaseOfCode = virtAddr;
                }

                if (!dataSectionEncountered &&
                    ((s.Name == ".data") || (s.Name == ".rdata")))
                {
                    dataSectionEncountered    = true;
                    optionalHeader.BaseOfData = virtAddr;
                }

                if (s.Name == ".rdata")
                {
                    dataDirectories.debug.VirtualAddress = virtAddr;
                }

                if (s.Name == ".reloc")
                {
                    dataDirectories.baseReloc.VirtualAddress = virtAddr;
                }

                s.VirtualAddress = virtAddr;

                if (s.HasUninitializedData)
                {
                    // Leave uninitialized data sizes untouched, their raw size is 0
                    virtAddr += PEUtility.AlignUp(s.VirtualSize, virtualAlignment);
                }
                else if (s.HasInitializedData && s.HasCode)
                {
                    // It is possible for the virtual size to be greater than the size of raw data
                    // Leave the virtual size untouched if this is the case
                    if (s.VirtualSize > s.RawSize)
                    {
                        virtAddr += PEUtility.AlignUp(s.VirtualSize, virtualAlignment);
                    }
                    else
                    {
                        s.VirtualSize = (uint)s.Data.Length;
                        virtAddr     += PEUtility.AlignUp((uint)s.Data.Length, virtualAlignment);
                    }
                }

                break;
            }

            /* Total virtual size is the final virtual address, which includes the initial virtual offset. */
            optionalHeader.SizeOfImage = virtAddr;

            /* Serialize and write the header contents */
            Serialize(totalSize);

            return(true);
        }