Esempio n. 1
0
        bool IBinaryAppender <ImageImportDescriptor, ReaderWithOffsetArgs> .Attach(ref ImageImportDescriptor s, uint size, ReaderWithOffsetArgs arg)
        {
            // check if data not empty:
            if (s.TimeDateStamp == 0 && s.Name == 0)
            {
                return(false);
            }

            // read proper data:
            Name = arg.Source.ReadStringAnsiAt(s.Name - arg.Delta);
            if (s.TimeDateStamp == uint.MaxValue)
            {
                BindDate = DateTime.Now;
                isBinded = true;
            }
            else
            {
                BindDate = new DateTime(1970, 1, 1).AddSeconds(s.TimeDateStamp);
                isBinded = s.TimeDateStamp != 0;
            }

            ForwarderChain    = s.ForwarderChain;
            NextModuleAddress = s.CharacteristicsOrOriginalFirstThunk;
            if (NextModuleAddress == 0)
            {
                NextModuleAddress = s.FirstThunk;
            }
            FirstThunk = s.FirstThunk;

            return(true);
        }
Esempio n. 2
0
        protected override ImageImportDescriptor[]? ParseTarget()
        {
            if (Offset == 0)
            {
                return(null);
            }

            var  idescs    = new List <ImageImportDescriptor>();
            uint idescSize = 20; // Size of ImageImportDescriptor (5 * 4 Byte)
            uint round     = 0;

            while (true)
            {
                var idesc = new ImageImportDescriptor(PeFile, Offset + idescSize * round);

                // Found the last ImageImportDescriptor which is completely null (except TimeDateStamp).
                if (idesc.OriginalFirstThunk == 0
                    //&& idesc.TimeDateStamp == 0
                    && idesc.ForwarderChain == 0 &&
                    idesc.Name == 0 &&
                    idesc.FirstThunk == 0)
                {
                    break;
                }

                idescs.Add(idesc);
                round++;
            }


            return(idescs.ToArray());
        }
Esempio n. 3
0
        internal ImageImportDll(MappedImage mappedImage, ImageImportDescriptor* descriptor)
        {
            _mappedImage = mappedImage;
            _descriptor = descriptor;

            if (_descriptor->OriginalFirstThunk != 0)
                _lookupTable = _mappedImage.RvaToVa(_descriptor->OriginalFirstThunk);
            else
                _lookupTable = _mappedImage.RvaToVa(_descriptor->FirstThunk);

            if (_lookupTable != null)
            {
                int i = 0;

                if (_mappedImage.Magic == Win32.Pe32Magic)
                {
                    while (((int*)_lookupTable)[i] != 0)
                        i++;
                }
                else if (_mappedImage.Magic == Win32.Pe32PlusMagic)
                {
                    while (((long*)_lookupTable)[i] != 0)
                        i++;
                }

                _count = i;
            }
        }
Esempio n. 4
0
        public void ImageImportDescriptorConstructorWorks_Test()
        {
            var importDescriptor = new ImageImportDescriptor(new BufferFile(RawStructures.RawImportDescriptor), 2);

            Assert.Equal((uint)0x33221100, importDescriptor.OriginalFirstThunk);
            Assert.Equal((uint)0x77665544, importDescriptor.TimeDateStamp);
            Assert.Equal(0xbbaa9988, importDescriptor.ForwarderChain);
            Assert.Equal(0xffeeddcc, importDescriptor.Name);
            Assert.Equal((uint)0x44332211, importDescriptor.FirstThunk);
        }
Esempio n. 5
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();
        }
    }
Esempio n. 6
0
        public static IEnumerable <uint> ReadImportLocationTable(this PEStream stream, ImageImportDescriptor descriptor)
        {
            // The thunk processing is the same for PE32 and PE32+, however the size of the thunks differ to support 64-bit addresses
            // when translating the ImportAddressTable (IAT). Luckily only 32-bits of the 64 are actually required in both
            // PE32 and PE32+ for the ImportLookupTable (ILT) so we can just normalize the data into a DWORD and avoid having to create
            // two *almost* identical methods.
            var is32Bit     = stream.OptionalHeader.Magic == H.IMAGE_NT_OPTIONAL_HDR32_MAGIC;
            var thunkSize   = (uint)(is32Bit ? sizeof(uint) : sizeof(ulong));
            var buffer      = new byte[thunkSize];
            var thunkOffset = 0U;
            var thunk       = 0U;

            while (true)
            {
                stream.SeekVirtualAddress(descriptor.OriginalFirstThunk + thunkOffset);
                stream.FullRead(buffer, 0, buffer.Length);

                if (is32Bit)
                {
                    thunk = BitConverter.ToUInt32(buffer, 0);
                }
                else
                {
                    var thunk64 = BitConverter.ToUInt64(buffer, 0);
                    thunk = (uint)((thunk64 & 0x7FFFFFFF) | ((thunk64 >> 32) & 0x80000000));
                }

                if (thunk == 0)
                {
                    break;
                }

                thunkOffset += thunkSize;
                yield return(thunk);
            }
        }