Example #1
0
        private (RawDirectoryEntry, IEnumerable <StreamRange>) GetHashableRanges(
            PEHeaders headers
            )
        {
            var snDir = headers.CorHeader.StrongNameSignatureDirectory;
            RawDirectoryEntry rawSNDir;

            return(snDir.Size > 0 && headers.TryGetDirectoryOffset(snDir, out var snOffset) ?
                   (rawSNDir = new RawDirectoryEntry(snOffset, snDir.Size), this.CalculateRangesWithValidSNDir(headers, rawSNDir)) :
Example #2
0
 public static void Write(Stream output, RawDirectoryEntry instance, Endian endian)
 {
     output.WriteValueS32(instance.DirectoryCount, endian);
     output.WriteValueS32(instance.DirectoryIndex, endian);
     output.WriteValueS32(instance.FileCount, endian);
     output.WriteValueS32(instance.FileIndex, endian);
     output.WriteValueU32(instance.Unknown10, endian);
     output.WriteValueU32(instance.Unknown14, endian);
     output.WriteValueU32(instance.Unknown18, endian);
     output.WriteValueU32(instance.Unknown1C, endian);
 }
Example #3
0
        public void Deserialize(Stream input)
        {
            var basePosition = input.Position;

            var magic = input.ReadValueU32(Endian.Big);

            if (magic != Signature)
            {
                throw new FormatException("bad header magic");
            }

            var version = input.ReadValueU8();

            if (version != 2)
            {
                throw new FormatException("bad header version");
            }

            var endianness = input.ReadValueU8();

            if (endianness != 0 && endianness != 1)
            {
                throw new FormatException("bad header endianness");
            }
            var endian = endianness == 0 ? Endian.Little : Endian.Big;

            var headerSizeHi = input.ReadValueU8();

            var unknown07 = input.ReadValueU8();

            if (unknown07 != 0)
            {
                throw new FormatException("bad header unknown07");
            }

            var unknown08 = input.ReadValueU32(endian);

            if (unknown08 != 0x00020001u)
            {
                throw new FormatException("bad header unknown08");
            }

            var headerSizeLo         = input.ReadValueU32(endian);
            var directoryCount       = input.ReadValueU32(endian);
            var directoryTableOffset = input.ReadValueU32(endian);
            var fileCount            = input.ReadValueU32(endian);
            var fileTableOffset      = input.ReadValueU32(endian);

            var actualHeaderSize = 32L;

            actualHeaderSize += 64 * (directoryCount + fileCount);
            actualHeaderSize += 32 * directoryCount;
            actualHeaderSize += 32 * fileCount;

            var headerSize = (headerSizeHi << 32) | headerSizeLo;

            if (headerSize != 0)
            {
                if (headerSize != actualHeaderSize.Align(Alignment))
                {
                    throw new FormatException("bad header size");
                }
            }

            if (input.Length < basePosition + actualHeaderSize)
            {
                throw new EndOfStreamException("stream too small for all header data");
            }

            var directoryNames = new string[directoryCount];

            for (uint i = 0; i < directoryCount; i++)
            {
                directoryNames[i] = input.ReadString(64, true, _Encoding);
            }

            var fileNames = new string[fileCount];

            for (uint i = 0; i < fileCount; i++)
            {
                fileNames[i] = input.ReadString(64, true, _Encoding);
            }

            var rawDirectoryEntries = new RawDirectoryEntry[directoryCount];

            if (directoryCount > 0)
            {
                input.Position = basePosition + directoryTableOffset;
                for (uint i = 0; i < directoryCount; i++)
                {
                    var directoryEntry = rawDirectoryEntries[i] = RawDirectoryEntry.Read(input, endian);

                    if (directoryEntry.Unknown14 != 0)
                    {
                        throw new FormatException("bad directory unknown14");
                    }

                    if (directoryEntry.Unknown18 != 0)
                    {
                        throw new FormatException("bad directory unknown18");
                    }

                    if (directoryEntry.Unknown1C != 0)
                    {
                        throw new FormatException("bad directory unknown1C");
                    }
                }
            }

            var rawFileEntries = new RawFileEntry[fileCount];

            if (fileCount > 0)
            {
                input.Position = basePosition + fileTableOffset;
                for (uint i = 0; i < fileCount; i++)
                {
                    var fileEntry = rawFileEntries[i] = RawFileEntry.Read(input, endian);

                    if ((fileEntry.CompressionFlags & 0x7FFFFFFFu) != 0)
                    {
                        throw new FormatException("bad file compression flags");
                    }

                    if (fileEntry.Unknown14 != 0)
                    {
                        throw new FormatException("bad file unknown14");
                    }

                    if (fileEntry.Unknown18 != 0)
                    {
                        throw new FormatException("bad file unknown18");
                    }
                }
            }

            var fileEntries = new List <FileEntry>();

            if (directoryCount > 0)
            {
                var queue = new Queue <KeyValuePair <int, string> >();
                queue.Enqueue(new KeyValuePair <int, string>(0, null));

                while (queue.Count > 0)
                {
                    var directoryInfo     = queue.Dequeue();
                    var directoryIndex    = directoryInfo.Key;
                    var rawDirectoryEntry = rawDirectoryEntries[directoryIndex];
                    var directoryName     = directoryNames[directoryIndex];
                    var isRootDirectory   = directoryIndex == 0 && directoryName == ".";
                    var directoryBasePath = directoryInfo.Value;
                    var directoryPath     = directoryBasePath == null
                                            ? isRootDirectory == true
                                                  ? null
                                                  : directoryName
                                            : isRootDirectory == true
                                                  ? directoryBasePath
                                                  : Path.Combine(directoryBasePath, directoryName);

                    for (int i = 0, o = rawDirectoryEntry.DirectoryIndex;
                         i < rawDirectoryEntry.DirectoryCount;
                         i++, o++)
                    {
                        queue.Enqueue(new KeyValuePair <int, string>(o, directoryPath));
                    }

                    for (int i = 0, o = rawDirectoryEntry.FileIndex; i < rawDirectoryEntry.FileCount; i++, o++)
                    {
                        var       rawFileEntry = rawFileEntries[o];
                        FileEntry fileEntry;
                        fileEntry.Path = directoryPath == null
                                             ? fileNames[o]
                                             : Path.Combine(directoryPath, fileNames[o]);
                        fileEntry.IsCompressed = ((FileFlags)rawFileEntry.CompressionFlags & FileFlags.IsCompressed) !=
                                                 0;
                        fileEntry.DataUncompressedSize = rawFileEntry.DataUncompressedSize;
                        fileEntry.DataCompressedSize   = rawFileEntry.DataCompressedSize;
                        fileEntry.DataOffset           =
                            (long)(rawFileEntry.DataOffsetLo) << 0 |
                                (long)(rawFileEntry.DataOffsetHi) << 32;
                        fileEntries.Add(fileEntry);
                    }
                }
            }
            else
            {
                // no directories but there's a file?
                if (fileCount > 0)
                {
                    throw new FormatException("bad directory count");
                }
            }

            this._Endian = endian;
            this._Entries.Clear();
            this._Entries.AddRange(fileEntries);
        }
Example #4
0
        private void ReadHeader()
        {
            _stream.Seek(0, SeekOrigin.Begin);

            var magic = _reader.ReadUInt32();

            if (magic != Signature)
            {
                throw new FormatException("Bad header magic");
            }

            var version = _reader.ReadByte();

            if (version != 2)
            {
                throw new FormatException("Unsupported version");
            }

            var endianness = _reader.ReadByte();

            _reader.Endianness = endianness == 0 ? Endianness.Little : Endianness.Big;

            var headerSizeHi = _reader.ReadByte();
            var unknown07    = _reader.ReadByte();   // 0
            var unknown08    = _reader.ReadUInt32(); // 0x00020001u

            var headerSizeLo         = _reader.ReadUInt32();
            var directoryCount       = _reader.ReadUInt32();
            var directoryTableOffset = _reader.ReadUInt32();
            var fileCount            = _reader.ReadUInt32();
            var fileTableOffset      = _reader.ReadUInt32();

            var actualHeaderSize = 32L;

            actualHeaderSize += 64 * (directoryCount + fileCount);
            actualHeaderSize += 32 * directoryCount;
            actualHeaderSize += 32 * fileCount;

            var headerSize     = (headerSizeHi << 32) | headerSizeLo;
            var directoryNames = new string[directoryCount];

            for (uint i = 0; i < directoryCount; i++)
            {
                directoryNames[i] = _reader.ReadString(64, _Encoding);
            }

            var fileNames = new string[fileCount];

            for (uint i = 0; i < fileCount; i++)
            {
                fileNames[i] = _reader.ReadString(64, _Encoding);
            }

            var rawDirectoryEntries = new RawDirectoryEntry[directoryCount];

            if (directoryCount > 0)
            {
                _stream.Position = directoryTableOffset;
                for (uint i = 0; i < directoryCount; i++)
                {
                    var directoryEntry = rawDirectoryEntries[i] = RawDirectoryEntry.Read(_reader);

                    if (directoryEntry.Unknown14 != 0)
                    {
                        throw new FormatException("bad directory unknown14");
                    }

                    if (directoryEntry.Unknown18 != 0)
                    {
                        throw new FormatException("bad directory unknown18");
                    }

                    if (directoryEntry.Unknown1C != 0)
                    {
                        throw new FormatException("bad directory unknown1C");
                    }
                }
            }

            var rawFileEntries = new RawFileEntry[fileCount];

            if (fileCount > 0)
            {
                _stream.Position = fileTableOffset;
                for (uint i = 0; i < fileCount; i++)
                {
                    var fileEntry = rawFileEntries[i] = RawFileEntry.Read(_reader);

                    if ((fileEntry.CompressionFlags & 0x7FFFFFFFu) != 0)
                    {
                        throw new FormatException("bad file compression flags");
                    }

                    if (fileEntry.Unknown14 != 0)
                    {
                        throw new FormatException("bad file unknown14");
                    }

                    if (fileEntry.Unknown18 != 0)
                    {
                        throw new FormatException("bad file unknown18");
                    }
                }
            }

            Queue <(int Index, string BasePath)> queue = new Queue <(int Index, string BasePath)>();

            queue.Enqueue((0, null));

            while (queue.Count > 0)
            {
                var(index, basePath) = queue.Dequeue();
                var rawDirectory    = rawDirectoryEntries[index];
                var directoryName   = directoryNames[index];
                var isRootDirectory = index == 0 && directoryName == ".";
                var directoryPath   = basePath == null
                    ? isRootDirectory
                        ? null
                        : directoryName
                    : isRootDirectory
                        ? basePath
                        : Path.Combine(basePath, directoryName);

                for (int i = 0; i < rawDirectory.DirectoryCount; i++)
                {
                    queue.Enqueue((i + rawDirectory.DirectoryOffset, directoryPath));
                }


                for (int i = 0; i < rawDirectory.FileCount; i++)
                {
                    var       fileIndex    = i + rawDirectory.FileOffset;
                    var       rawFileEntry = rawFileEntries[fileIndex];
                    FileEntry fileEntry;
                    fileEntry.Path = directoryPath == null
                        ? fileNames[fileIndex]
                        : Path.Combine(directoryPath, fileNames[fileIndex]);
                    fileEntry.IsCompressed         = ((FileFlags)rawFileEntry.CompressionFlags & FileFlags.IsCompressed) != 0;
                    fileEntry.DataUncompressedSize = rawFileEntry.DataUncompressedSize;
                    fileEntry.DataCompressedSize   = rawFileEntry.DataCompressedSize;
                    fileEntry.DataOffset           = (long)(rawFileEntry.DataOffsetLo) << 0 | (long)(rawFileEntry.DataOffsetHi) << 32;
                    fileEntry.Unknown10            = rawFileEntry.HeaderSize;
                    fileEntry.Unknown14            = rawFileEntry.Unknown14;
                    fileEntry.Unknown18            = rawFileEntry.Unknown18;
                    fileEntry.Unknown1C            = rawFileEntry.Unknown1C;

                    _entries.Add(fileEntry);
                }
            }

            // _entries = _entries.OrderBy(e => e.DataOffset).ToList();
            // int counter = 0;
            // for (int i = 1; i < _entries.Count; i++)
            // {
            //     var prev = _entries[i - 1];
            //     var file = _entries[i];
            //
            //     // Console.WriteLine($"[{file.DataOffset % Alignment}] {file.DataOffset - (prev.DataOffset + (prev.IsCompressed ? prev.DataCompressedSize : prev.DataUncompressedSize))}");
            //     if (file.DataOffset % Alignment != 0)
            //     {
            //         // var sameBlock = (file.DataOffset / Alignment) == ((prev.DataOffset + prev.Size) / Alignment);
            //         // counter++;
            //         // Console.WriteLine(sameBlock);
            //     }
            //     else
            //     {
            //         var sameBlock = (file.DataOffset / Alignment) == ((prev.DataOffset + prev.Size) / Alignment);
            //         counter++;
            //         Console.WriteLine(sameBlock);
            //     }
            // }

            // Console.WriteLine("Total: " + counter);
        }
Example #5
0
        public void Deserialize(Stream input)
        {
            var basePosition = input.Position;

            var magic = input.ReadValueU32(Endian.Big);
            if (magic != Signature)
            {
                throw new FormatException();
            }

            var version = input.ReadValueU8();
            if (version != 2)
            {
                throw new FormatException();
            }

            var endianness = input.ReadValueU8();
            if (endianness != 0 && endianness != 1)
            {
                throw new FormatException();
            }
            var endian = endianness == 0 ? Endian.Little : Endian.Big;

            var unknown06 = input.ReadValueU8();
            var unknown07 = input.ReadValueU8();
            if (unknown06 != 0 || unknown07 != 0)
            {
                throw new FormatException();
            }

            var unknown08 = input.ReadValueU32(endian);
            if (unknown08 != 0x00020001u)
            {
                throw new FormatException();
            }

            var unknown0C = input.ReadValueU32(endian);
            if (unknown0C != 0)
            {
                throw new FormatException();
            }

            var directoryCount = input.ReadValueU32(endian);
            var directoryTableOffset = input.ReadValueU32(endian);
            var fileCount = input.ReadValueU32(endian);
            var fileTableOffset = input.ReadValueU32(endian);

            var directoryNames = new string[directoryCount];
            for (uint i = 0; i < directoryCount; i++)
            {
                directoryNames[i] = input.ReadString(64, true, Encoding.ASCII);
            }

            var fileNames = new string[fileCount];
            for (uint i = 0; i < fileCount; i++)
            {
                fileNames[i] = input.ReadString(64, true, Encoding.ASCII);
            }

            var rawDirectoryEntries = new RawDirectoryEntry[directoryCount];
            if (directoryCount > 0)
            {
                input.Position = basePosition + directoryTableOffset;
                for (uint i = 0; i < directoryCount; i++)
                {
                    var directoryEntry = rawDirectoryEntries[i] = RawDirectoryEntry.Read(input, endian);
                    if (directoryEntry.Unknown14 != 0 || directoryEntry.Unknown18 != 0 || directoryEntry.Unknown1C != 0)
                    {
                        throw new FormatException();
                    }
                }
            }

            var rawFileEntries = new RawFileEntry[fileCount];
            if (fileCount > 0)
            {
                input.Position = basePosition + fileTableOffset;
                for (uint i = 0; i < fileCount; i++)
                {
                    var fileEntry = rawFileEntries[i] = RawFileEntry.Read(input, endian);
                    if ((fileEntry.CompressionFlags & 0x7FFFFFFFu) != 0)
                    {
                        throw new FormatException();
                    }
                    if (fileEntry.Unknown14 != 0 || fileEntry.Unknown18 != 0)
                    {
                        throw new FormatException();
                    }
                }
            }

            var fileEntries = new List<FileEntry>();

            if (directoryCount > 0)
            {
                var queue = new Queue<KeyValuePair<int, string>>();
                queue.Enqueue(new KeyValuePair<int, string>(0, null));

                while (queue.Count > 0)
                {
                    var directoryInfo = queue.Dequeue();
                    var directoryIndex = directoryInfo.Key;
                    var rawDirectoryEntry = rawDirectoryEntries[directoryIndex];
                    var directoryName = directoryNames[directoryIndex];
                    var isRootDirectory = directoryIndex == 0 && directoryName == ".";
                    var directoryBasePath = directoryInfo.Value;
                    var directoryPath = directoryBasePath == null
                                            ? isRootDirectory == true
                                                  ? null
                                                  : directoryName
                                            : isRootDirectory == true
                                                  ? directoryBasePath
                                                  : Path.Combine(directoryBasePath, directoryName);

                    for (int i = 0, o = rawDirectoryEntry.DirectoryIndex;
                        i < rawDirectoryEntry.DirectoryCount;
                        i++, o++)
                    {
                        queue.Enqueue(new KeyValuePair<int, string>(o, directoryPath));
                    }

                    for (int i = 0, o = rawDirectoryEntry.FileIndex; i < rawDirectoryEntry.FileCount; i++, o++)
                    {
                        var rawFileEntry = rawFileEntries[o];
                        FileEntry fileEntry;
                        fileEntry.Path = directoryPath == null
                                             ? fileNames[o]
                                             : Path.Combine(directoryPath, fileNames[o]);
                        fileEntry.IsCompressed = ((FileFlags)rawFileEntry.CompressionFlags & FileFlags.IsCompressed) !=
                                                 0;
                        fileEntry.DataUncompressedSize = rawFileEntry.DataUncompressedSize;
                        fileEntry.DataCompressedSize = rawFileEntry.DataCompressedSize;
                        fileEntry.DataOffset =
                            (long)(rawFileEntry.DataOffsetLo) << 0 |
                            (long)(rawFileEntry.DataOffsetHi) << 32;
                        fileEntries.Add(fileEntry);
                    }
                }
            }
            else
            {
                // no directories but there's a file?
                if (fileCount > 0)
                {
                    throw new FormatException();
                }
            }

            this._Endian = endian;
            this._Entries.Clear();
            this._Entries.AddRange(fileEntries);
        }