Пример #1
0
        private void ReadEntryChildren(ResDirectoryEntry dirEntry, Stream peStream,
                                       long virtualAddress, long baseOffset, ref int nextId)
        {
            // read the child node(s)
            if (dirEntry.entry.DataIsDirectory)
            {
                // note: offset from beginning of section.
                peStream.Seek(baseOffset + dirEntry.entry.OffsetToDirectory, SeekOrigin.Begin);

                dirEntry.child = ReadDirectory(peStream, virtualAddress, baseOffset, dirEntry.id, ref nextId);
            }
            else
            {
                // note: offset from beginning of section.
                peStream.Seek(baseOffset + dirEntry.entry.OffsetToData, SeekOrigin.Begin);

                var dataEntry = peStream.Read <IMAGE_RESOURCE_DATA_ENTRY>();

                // decode the RVA to file offset
                long realDataAddr = baseOffset + dataEntry.OffsetToData - virtualAddress;
                peStream.Seek(realDataAddr, SeekOrigin.Begin);

                var dataBytes = new byte[dataEntry.Size];
                peStream.Read(dataBytes, 0, dataBytes.Length);

                string type, name;
                int    localeId;
                GetResourceInfo(dirEntry, out type, out name, out localeId);

                int dataId = nextId++;
                _data.Add(dataId, new PeResourceData(type, name, localeId, dataBytes));
                dirEntry.child = dataId;
            }
        }
Пример #2
0
        private void GetResourceInfo(ResDirectoryEntry dataEntry, out string type, out string name, out int localeId)
        {
            Debug.Assert(!dataEntry.IsSubdirectory, "attempted to get type/name/locale of resource directory node.");

            localeId = dataEntry.entry.Id;

            ResDirectory localeDir = _directories[dataEntry.ownerDirectory];

            ResDirectoryEntry nameEntry = _entries[localeDir.parentEntry];

            name = nameEntry.name;

            ResDirectory nameDirectory = _directories[nameEntry.ownerDirectory];

            ResDirectoryEntry typeEntry = _entries[nameDirectory.parentEntry];

            type = typeEntry.name;
        }
Пример #3
0
        private int ReadDirectory(Stream peStream, long virtualAddress, long baseOffset, int parentId, ref int nextId)
        {
            int dirId   = nextId++;
            var dirInfo = new ResDirectory();

            dirInfo.id          = dirId;
            dirInfo.parentEntry = parentId;

            _directories.Add(dirId, dirInfo);

            dirInfo.directory = peStream.Read <IMAGE_RESOURCE_DIRECTORY>();

            int nChildren = dirInfo.directory.NumberOfIdEntries + dirInfo.directory.NumberOfNamedEntries;

            dirInfo.childMappings = new int[nChildren];

            // read the directory table rows
            for (int i = 0; i < nChildren; i++)
            {
                int entryId = nextId++;

                var dirEntry = new ResDirectoryEntry();
                dirEntry.id             = entryId;
                dirEntry.ownerDirectory = dirId;

                dirInfo.childMappings[i] = entryId;
                dirEntry.entry           = peStream.Read <IMAGE_RESOURCE_DIRECTORY_ENTRY>();

                _entries.Add(entryId, dirEntry);
            }

            // read the child data.
            for (int i = 0; i < nChildren; i++)
            {
                ResDirectoryEntry dirEntry = _entries[dirInfo.childMappings[i]];

                ReadEntryName(dirEntry, peStream, virtualAddress, baseOffset);

                ReadEntryChildren(dirEntry, peStream, virtualAddress, baseOffset, ref nextId);
            }

            return(dirId);
        }
Пример #4
0
        private IEnumerable <PeResourceData> GetAllChildDatas(ResDirectoryEntry entry)
        {
            if (entry.IsSubdirectory)
            {
                // subdirectory, recursively yield the data
                var dir = _directories[entry.child];

                for (int i = 0; i < dir.NumChildren; i++)
                {
                    var childEntry = _entries[dir.childMappings[i]];

                    foreach (var data in GetAllChildDatas(childEntry))
                    {
                        yield return(data);
                    }
                }
            }
            else
            {
                // leaf node, just yield the data
                yield return(_data[entry.child]);
            }
        }
Пример #5
0
        private void ReadEntryName(ResDirectoryEntry dirEntry, Stream peStream,
                                   long virtualAddress, long baseOffset)
        {
            // read the name
            if (dirEntry.entry.NameIsString)
            {
                // note: offset from beginning of section.
                peStream.Seek(baseOffset + dirEntry.entry.NameOffset, SeekOrigin.Begin);

                int nChars = peStream.Read <short>();

                // names are in "Unicode" (UTF-16LE, wchar_t)
                int nBytes = nChars * 2;

                var nameBytes = new byte[nBytes];
                peStream.Read(nameBytes, 0, nBytes);

                dirEntry.name = Encoding.Unicode.GetString(nameBytes);
            }
            else
            {
                dirEntry.name = dirEntry.entry.Id.ToString();
            }
        }
Пример #6
0
        private int ReadDirectory(Stream peStream, long baseAddress, long virtualAddress, ref int nextId)
        {
            int dirId   = nextId++;
            var dirInfo = new ResDirectory();

            _directories.Add(dirId, dirInfo);

            dirInfo.directory = peStream.Read <IMAGE_RESOURCE_DIRECTORY>();

            int nChildren = dirInfo.directory.NumberOfIdEntries + dirInfo.directory.NumberOfNamedEntries;

            dirInfo.childMappings = new int[nChildren];

            for (int i = 0; i < nChildren; i++)
            {
                int entryId = nextId++;

                var dirEntry = new ResDirectoryEntry();

                _entries.Add(entryId, dirEntry);
                dirInfo.childMappings[i] = entryId;

                dirEntry.entry = peStream.Read <IMAGE_RESOURCE_DIRECTORY_ENTRY>();

                // preserve the current stream position while we read child data
                var curOffset = peStream.Position;

                // read the name
                if (dirEntry.entry.NameIsString)
                {
                    // note: offset from beginning of section.
                    peStream.Seek(baseAddress + dirEntry.entry.NameOffset, SeekOrigin.Begin);

                    int nChars = peStream.Read <short>();

                    // names are in "Unicode"
                    int nBytes = nChars * 2;

                    var nameBytes = new byte[nBytes];
                    peStream.Read(nameBytes, 0, nBytes);

                    dirEntry.name = Encoding.Unicode.GetString(nameBytes);
                }
                else
                {
                    dirEntry.name = dirEntry.entry.Id.ToString();
                }

                // read the child node(s)
                if (dirEntry.entry.DataIsDirectory)
                {
                    // note: offset from beginning of section.
                    peStream.Seek(baseAddress + dirEntry.entry.OffsetToDirectory, SeekOrigin.Begin);

                    dirEntry.child = ReadDirectory(peStream, baseAddress, virtualAddress, ref nextId);
                }
                else
                {
                    // note: offset from beginning of section.
                    peStream.Seek(baseAddress + dirEntry.entry.OffsetToData, SeekOrigin.Begin);

                    var dataEntry = peStream.Read <IMAGE_RESOURCE_DATA_ENTRY>();

                    // decode the RVA...
                    long realDataAddr = baseAddress + dataEntry.OffsetToData - virtualAddress;
                    peStream.Seek(realDataAddr, SeekOrigin.Begin);

                    var dataBytes = new byte[dataEntry.Size];
                    peStream.Read(dataBytes, 0, dataBytes.Length);

                    int dataId = nextId++;
                    _data.Add(dataId, dataBytes);
                    dirEntry.child = dataId;
                }

                peStream.Seek(curOffset, SeekOrigin.Begin);
            }

            return(dirId);
        }