示例#1
0
        /// <summary>
        /// Locate the <see cref="IMAGE_SECTION_HEADER"/> that corresponds to the given RVA
        /// </summary>
        /// <param name="rva">The address to map to a header.</param>
        /// <returns></returns>
        public IMAGE_SECTION_HEADER GetSectionFromRva(uint rva)
        {
            IMAGE_SECTION_HEADER section = new IMAGE_SECTION_HEADER();

            var sections = ImageSectionHeaders.ToArray();

            int i = 0;

            while (i < FileHeader.NumberOfSections)
            {
                if (rva < sections[i].VirtualAddress + AlignTo(sections[i].VirtualSize, SectionAlignment))
                {
                    if (rva < sections[i].VirtualAddress)
                    {
                        return(section);
                    }
                    else
                    {
                        return(sections[i]);
                    }
                }
                i++;
            }
            return(section);
        }
示例#2
0
        public PeHeaderReader(RemoteProcess process, IntPtr moduleBase) : base(process, moduleBase)
        {
            DosHeader = new ImageDosHeader(process, moduleBase);
            NtHeader  = new ImageNtHeader(process, moduleBase + (int)DosHeader.e_lfanew, Is64Bit);

            var numSections    = (int)NtHeader.FileHeader.NumberOfSections;
            var secHeaderStart = DosHeader.e_lfanew + NtHeader.FileHeader.SizeOfOptionalHeader + 0x18;

            SectionHeaders = new ImageSectionHeaders(process, moduleBase + (int)secHeaderStart, numSections);

            var exportDirVa = NtHeader.OptionalHeader.DataDirectory[0].VirtualAddress;

            if (exportDirVa != 0)
            {
                ExportDirectory = new ImageExportDirectory(process, moduleBase + (int)exportDirVa);
            }
        }
示例#3
0
        /// <summary>
        /// Add imports to the PE file.
        /// </summary>
        /// <param name="additionalImports">List with additional imports.</param>
        public void AddImports(List <AdditionalImport> additionalImports)
        {
            if (ImageNtHeaders is null || ImageSectionHeaders is null || _dataDirectoryParsers is null)
            {
                throw new Exception("NT Headers, Section Headers and Data Directory must not be null.");
            }

            const int sizeOfImpDesc   = 0x14;
            var       sizeOfThunkData = Is32Bit ? 4 : 8;
            var       numAddImpDescs  = additionalImports.Count;
            var       importRva       = ImageNtHeaders.OptionalHeader.DataDirectory[(int)DataDirectoryType.Import].VirtualAddress;
            var       importSize      = ImageNtHeaders.OptionalHeader.DataDirectory[(int)DataDirectoryType.Import].Size;

            ImageSectionHeader GetImportSection()
            => ImageSectionHeaders.First(sh => sh.VirtualAddress + sh.VirtualSize >= importRva);

            int EstimateAdditionalNeededSpace()
            => additionalImports.Select(ai => ai.Functions).Count() * 64;

            var impSection             = GetImportSection();
            var newUnalignedRawSecSize = EstimateAdditionalNeededSpace();

            // First copy the current import descriptor array to the start of the new section to have enough space to
            // add additional import descriptors.
            AddSection(".addImp", (int)(impSection !.SizeOfRawData + newUnalignedRawSecSize), (ScnCharacteristicsType)0xC0000000);
            var newImpSec       = ImageSectionHeaders.First(sh => sh.Name == ".addImp");
            var oldImpDescBytes = RawFile.AsSpan(importRva.RvaToOffset(ImageSectionHeaders), importSize);

            RawFile.WriteBytes(newImpSec.PointerToRawData, oldImpDescBytes);

            // Set the import data directory to the new import section and adjust the size
            ImageNtHeaders.OptionalHeader.DataDirectory[(int)DataDirectoryType.Import].VirtualAddress = newImpSec.VirtualAddress;
            ImageNtHeaders.OptionalHeader.DataDirectory[(int)DataDirectoryType.Import].Size           = (uint)(importSize + (sizeOfImpDesc * numAddImpDescs));
            var newImportRva  = ImageNtHeaders.OptionalHeader.DataDirectory[(int)DataDirectoryType.Import].VirtualAddress;
            var newImportSize = ImageNtHeaders.OptionalHeader.DataDirectory[(int)DataDirectoryType.Import].Size;

            var paAdditionalSpace = newImpSec.PointerToRawData + newImportSize;

            // Update import descriptors and imported functions to reflect the new
            // position in the new section.
            _dataDirectoryParsers.ReparseImportDescriptors(ImageSectionHeaders);
            _dataDirectoryParsers.ReparseImportedFunctions();

            uint AddModName(ref uint offset, string module)
            {
                var tmp   = Encoding.ASCII.GetBytes(module);
                var mName = new byte[tmp.Length + 1];

                Array.Copy(tmp, mName, tmp.Length);

                var paName = offset;

                RawFile.WriteBytes(offset, mName);

                offset = (uint)(offset + mName.Length);
                return(paName);
            }

            List <uint> AddImpByNames(ref uint offset, List <string> funcs)
            {
                var adrList = new List <uint>();

                foreach (var f in funcs)
                {
                    var ibn = new ImageImportByName(RawFile, offset)
                    {
                        Hint = 0,
                        Name = f
                    };

                    adrList.Add(offset);

                    offset += (uint)ibn.Name.Length + 2;
                }

                // Add zero DWORD to end array
                RawFile.WriteUInt(offset + 1, 0);
                offset += 5;

                return(adrList);
            }

            uint AddThunkDatas(ref uint offset, List <uint> adrList)
            {
                var paThunkStart = offset;

                foreach (var adr in adrList)
                {
                    _ = new ImageThunkData(RawFile, offset, Is64Bit)
                    {
                        AddressOfData = adr.OffsetToRva(ImageSectionHeaders !)
                    };

                    offset += (uint)sizeOfThunkData;
                }

                // End array with empty thunk data
                _ = new ImageThunkData(RawFile, offset, Is64Bit)
                {
                    AddressOfData = 0
                };

                offset += (uint)sizeOfThunkData;

                return(paThunkStart);
            }

            void AddImportWithNewImpDesc(ref uint tmpOffset, ref long paIdesc, AdditionalImport ai)
            {
                var paName    = AddModName(ref tmpOffset, ai.Module);
                var funcAdrs  = AddImpByNames(ref tmpOffset, ai.Functions);
                var thunkAdrs = AddThunkDatas(ref tmpOffset, funcAdrs);

                _ = new ImageImportDescriptor(RawFile, paIdesc)
                {
                    Name = paName.OffsetToRva(ImageSectionHeaders),
                    OriginalFirstThunk = 0,
                    FirstThunk         = thunkAdrs.OffsetToRva(ImageSectionHeaders),
                    ForwarderChain     = 0,
                    TimeDateStamp      = 0
                };
                paIdesc += (uint)sizeOfImpDesc;
            }

            var paIdesc   = newImportRva.RvaToOffset(ImageSectionHeaders) + ImageImportDescriptors !.Length * sizeOfImpDesc;
            var tmpOffset = paAdditionalSpace;

            // Add new imports
            foreach (var ai in additionalImports)
            {
                AddImportWithNewImpDesc(ref tmpOffset, ref paIdesc, ai);
            }

            // End with zero filled idesc
            _ = new ImageImportDescriptor(RawFile, paIdesc)
            {
                Name = 0,
                OriginalFirstThunk = 0,
                FirstThunk         = 0,
                ForwarderChain     = 0,
                TimeDateStamp      = 0
            };


            // Reparse imports
            _dataDirectoryParsers.ReparseImportDescriptors(ImageSectionHeaders);
            _dataDirectoryParsers.ReparseImportedFunctions();
        }
    }
示例#4
0
        /// <summary>
        /// Remove a section from the PE file.
        /// </summary>
        /// <param name="name">Name of the section to remove.</param>
        /// <param name="removeContent">Flag if the content should be removed or only the section header entry.</param>
        public void RemoveSection(string name, bool removeContent = true)
        {
            var sectionToRemove = ImageSectionHeaders.First(s => s.Name == name);

            // Remove section from list of sections
            var newSections = ImageSectionHeaders.Where(s => s.Name != name).ToArray();

            // Change number of sections in the file header
            ImageNtHeaders !.FileHeader.NumberOfSections--;

            if (removeContent)
            {
                // Reloc the physical address of all sections
                foreach (var s in newSections)
                {
                    if (s.PointerToRawData > sectionToRemove.PointerToRawData)
                    {
                        s.PointerToRawData -= sectionToRemove.SizeOfRawData;
                    }
                }

                // Remove section content
                RawFile.RemoveRange(sectionToRemove.PointerToRawData, sectionToRemove.SizeOfRawData);
            }

            // Fix virtual size
            for (var i = 1; i < newSections.Count(); i++)
            {
                if (newSections[i - 1].VirtualAddress < sectionToRemove.VirtualAddress)
                {
                    newSections[i - 1].VirtualSize = newSections[i].VirtualAddress - newSections[i - 1].VirtualAddress;
                }
            }

            // Replace old section headers with new section headers
            var sectionHeaderOffset = ImageDosHeader !.E_lfanew + ImageNtHeaders !.FileHeader.SizeOfOptionalHeader + 0x18;
            var sizeOfSection       = 0x28;
            var newRawSections      = new byte[newSections.Count() * sizeOfSection];

            for (var i = 0; i < newSections.Count(); i++)
            {
                Array.Copy(newSections[i].ToArray(), 0, newRawSections, i * sizeOfSection, sizeOfSection);
            }

            // Null the data directory entry if any available
            var de = ImageNtHeaders
                     .OptionalHeader
                     .DataDirectory
                     .FirstOrDefault(d => d.VirtualAddress == sectionToRemove.VirtualAddress &&
                                     d.Size == sectionToRemove.VirtualSize);

            if (de != null)
            {
                de.Size           = 0;
                de.VirtualAddress = 0;
            }

            // Null the old section headers
            RawFile.WriteBytes(sectionHeaderOffset, new byte[ImageSectionHeaders.Count() * sizeOfSection]);

            // Write the new sections headers
            RawFile.WriteBytes(sectionHeaderOffset, newRawSections);

            // Reparse section header
            _nativeStructureParsers.ReparseSectionHeaders();
        }
示例#5
0
        /// <summary>
        /// Add a new section to the PE file.
        /// </summary>
        /// <param name="name">Name of the section to add. At max. 8 characters.</param>
        /// <param name="size">Size in bytes of the new section.</param>
        /// <param name="characteristics">Section characteristics.</param>
        public void AddSection(string name, int size, ScnCharacteristicsType characteristics)
        {
            if (ImageNtHeaders is null)
            {
                throw new Exception("IMAGE_NT_HEADERS must not be null.");
            }
            if (ImageDosHeader is null)
            {
                throw new Exception("IMAGE_DOS_HEADER must not be null");
            }

            uint getNewSizeOfImage()
            {
                var factor         = size / (double)ImageNtHeaders.OptionalHeader.SectionAlignment;
                var additionalSize = (uint)Math.Ceiling(factor) * ImageNtHeaders !.OptionalHeader.SectionAlignment;

                return(ImageNtHeaders.OptionalHeader.SizeOfImage + additionalSize);
            }

            uint getNewSecHeaderOffset()
            {
                var sizeOfSection        = 0x28;
                var x                    = (uint)ImageNtHeaders !.FileHeader.SizeOfOptionalHeader + 0x18;
                var startOfSectionHeader = ImageDosHeader.E_lfanew + x;

                return((uint)(startOfSectionHeader + (ImageNtHeaders.FileHeader.NumberOfSections * sizeOfSection)));
            }

            uint getNewSecVA()
            {
                var lastSec      = ImageSectionHeaders.OrderByDescending(sh => sh.VirtualAddress).First();
                var vaLastSecEnd = lastSec.VirtualAddress + lastSec.VirtualSize;
                var factor       = vaLastSecEnd / (double)ImageNtHeaders.OptionalHeader.SectionAlignment;

                return((uint)(Math.Ceiling(factor) * ImageNtHeaders.OptionalHeader.SectionAlignment));
            }

            // Append new section to end of file
            var paNewSec = RawFile.AppendBytes(new Byte[size]);

            // Add new entry in section table
            var newSection = new ImageSectionHeader(RawFile, getNewSecHeaderOffset(), ImageNtHeaders.OptionalHeader.ImageBase)
            {
                Name                 = name,
                VirtualSize          = (uint)size,
                VirtualAddress       = getNewSecVA(),
                SizeOfRawData        = (uint)size,
                PointerToRawData     = (uint)paNewSec,
                PointerToRelocations = 0,
                PointerToLinenumbers = 0,
                NumberOfRelocations  = 0,
                NumberOfLinenumbers  = 0,
                Characteristics      = characteristics
            };

            // Increase number of sections
            ImageNtHeaders.FileHeader.NumberOfSections = (ushort)(ImageNtHeaders.FileHeader.NumberOfSections + 1);

            // Adjust image size by image alignment
            ImageNtHeaders.OptionalHeader.SizeOfImage = getNewSizeOfImage();

            // Reparse section headers
            _nativeStructureParsers.ReparseSectionHeaders();
        }