Пример #1
0
        public void ImageImportByNameConstructorWorks_Test()
        {
            var importByName = new ImageImportByName(new BufferFile(RawStructures.RawImportByName), 2);

            Assert.Equal((ushort)0x1100, importByName.Hint);
            Assert.Equal("Hello World", importByName.Name);
        }
Пример #2
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();
        }
    }
Пример #3
0
        protected override ImportFunction[]? ParseTarget()
        {
            if (_importDescriptors == null)
            {
                return(null);
            }

            var impFuncs    = new List <ImportFunction>();
            var sizeOfThunk = (uint)(_is64Bit ? 0x8 : 0x4);  // Size of ImageThunkData
            var ordinalBit  = _is64Bit ? 0x8000000000000000 : 0x80000000;
            var ordinalMask = (ulong)(_is64Bit ? 0x7FFFFFFFFFFFFFFF : 0x7FFFFFFF);
            var iat         = _dataDirectories[(int)DataDirectoryType.IAT];

            foreach (var idesc in _importDescriptors)
            {
                var dllAdr = idesc.Name.RvaToOffset(_sectionHeaders);
                var dll    = PeFile.ReadAsciiString(dllAdr);
                if (IsModuleNameTooLong(dll))
                {
                    continue;
                }
                var tmpAdr = idesc.OriginalFirstThunk != 0 ? idesc.OriginalFirstThunk : idesc.FirstThunk;
                if (tmpAdr == 0)
                {
                    continue;
                }

                var  thunkAdr = tmpAdr.RvaToOffset(_sectionHeaders);
                uint round    = 0;
                while (true)
                {
                    var t         = new ImageThunkData(PeFile, thunkAdr + round * sizeOfThunk, _is64Bit);
                    var iatOffset = idesc.FirstThunk + round * sizeOfThunk - iat.VirtualAddress;

                    if (t.AddressOfData == 0)
                    {
                        break;
                    }

                    // Check if import by name or by ordinal.
                    // If it is an import by ordinal, the most significant bit of "Ordinal" is "1" and the ordinal can
                    // be extracted from the least significant bits.
                    // Else it is an import by name and the link to the ImageImportByName has to be followed

                    if ((t.Ordinal & ordinalBit) == ordinalBit) // Import by ordinal
                    {
                        impFuncs.Add(new ImportFunction(null, dll, (ushort)(t.Ordinal & ordinalMask), iatOffset));
                    }
                    else // Import by name
                    {
                        var ibn = new ImageImportByName(PeFile,
                                                        ((uint)t.AddressOfData).RvaToOffset(_sectionHeaders));
                        impFuncs.Add(new ImportFunction(ibn.Name, dll, ibn.Hint, iatOffset));
                    }

                    round++;
                }
            }


            return(impFuncs.ToArray());
        }