Exemplo n.º 1
0
        /// <summary>
        /// Initializes a new instance of the RegistryHive class.
        /// </summary>
        /// <param name="hive">The stream containing the registry hive</param>
        /// <param name="ownership">Whether the new object assumes object of the stream</param>
        public RegistryHive(Stream hive, Ownership ownership)
        {
            _fileStream          = hive;
            _fileStream.Position = 0;
            _ownsStream          = ownership;

            byte[] buffer = Utilities.ReadFully(_fileStream, HiveHeader.HeaderSize);

            _header = new HiveHeader();
            _header.ReadFrom(buffer, 0);

            _bins = new List <BinHeader>();
            int pos = 0;

            while (pos < _header.Length)
            {
                _fileStream.Position = BinStart + pos;
                byte[]    headerBuffer = Utilities.ReadFully(_fileStream, BinHeader.HeaderSize);
                BinHeader header       = new BinHeader();
                header.ReadFrom(headerBuffer, 0);
                _bins.Add(header);

                pos += header.BinSize;
            }
        }
Exemplo n.º 2
0
        public Bin(RegistryHive hive, Stream stream)
        {
            _hive       = hive;
            _fileStream = stream;
            _streamPos  = stream.Position;

            stream.Position = _streamPos;
            byte[] buffer = Utilities.ReadFully(stream, 0x20);
            _header = new BinHeader();
            _header.ReadFrom(buffer, 0);

            _fileStream.Position = _streamPos;
            _buffer = Utilities.ReadFully(_fileStream, _header.BinSize);

            // Gather list of all free cells.
            _freeCells = new List <Range <int, int> >();
            int pos = 0x20;

            while (pos < _buffer.Length)
            {
                int size = Utilities.ToInt32LittleEndian(_buffer, pos);
                if (size > 0)
                {
                    _freeCells.Add(new Range <int, int>(pos, size));
                }

                pos += Math.Abs(size);
            }
        }
Exemplo n.º 3
0
        private Bin GetBin(int cellIndex)
        {
            BinHeader binHeader = FindBin(cellIndex);

            if (binHeader != null)
            {
                return(LoadBin(binHeader));
            }

            return(null);
        }
Exemplo n.º 4
0
        internal int AllocateRawCell(int capacity)
        {
            int minSize = Utilities.RoundUp(capacity + 4, 8); // Allow for size header and ensure multiple of 8

            // Incredibly inefficient algorithm...
            foreach (var binHeader in _bins)
            {
                Bin bin       = LoadBin(binHeader);
                int cellIndex = bin.AllocateCell(minSize);

                if (cellIndex >= 0)
                {
                    return(cellIndex);
                }
            }

            BinHeader newBinHeader = AllocateBin(minSize);
            Bin       newBin       = LoadBin(newBinHeader);

            return(newBin.AllocateCell(minSize));
        }
Exemplo n.º 5
0
        private BinHeader AllocateBin(int minSize)
        {
            BinHeader lastBin = _bins[_bins.Count - 1];

            BinHeader newBinHeader = new BinHeader();

            newBinHeader.FileOffset = lastBin.FileOffset + lastBin.BinSize;
            newBinHeader.BinSize    = Utilities.RoundUp(minSize + newBinHeader.Size, 4 * (int)Sizes.OneKiB);

            byte[] buffer = new byte[newBinHeader.Size];
            newBinHeader.WriteTo(buffer, 0);
            _fileStream.Position = BinStart + newBinHeader.FileOffset;
            _fileStream.Write(buffer, 0, buffer.Length);

            byte[] cellHeader = new byte[4];
            Utilities.WriteBytesLittleEndian(newBinHeader.BinSize - newBinHeader.Size, cellHeader, 0);
            _fileStream.Write(cellHeader, 0, 4);

            // Update hive with new length
            _header.Length    = newBinHeader.FileOffset + newBinHeader.BinSize;
            _header.Timestamp = DateTime.UtcNow;
            _header.Sequence1++;
            _header.Sequence2++;
            _fileStream.Position = 0;
            byte[] hiveHeader = Utilities.ReadFully(_fileStream, _header.Size);
            _header.WriteTo(hiveHeader, 0);
            _fileStream.Position = 0;
            _fileStream.Write(hiveHeader, 0, hiveHeader.Length);

            // Make sure the file is initialized to desired position
            _fileStream.Position = BinStart + _header.Length - 1;
            _fileStream.WriteByte(0);

            _bins.Add(newBinHeader);
            return(newBinHeader);
        }
Exemplo n.º 6
0
 private Bin LoadBin(BinHeader binHeader)
 {
     _fileStream.Position = BinStart + binHeader.FileOffset;
     return(new Bin(this, _fileStream));
 }
Exemplo n.º 7
0
        /// <summary>
        /// Creates a new (empty) registry hive.
        /// </summary>
        /// <param name="stream">The stream to contain the new hive</param>
        /// <param name="ownership">Whether the returned object owns the stream</param>
        /// <returns>The new hive</returns>
        public static RegistryHive Create(Stream stream, Ownership ownership)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream", "Attempt to create registry hive in null stream");
            }

            // Construct a file with minimal structure - hive header, plus one (empty) bin
            BinHeader binHeader = new BinHeader();

            binHeader.FileOffset = 0;
            binHeader.BinSize    = (int)(4 * Sizes.OneKiB);

            HiveHeader hiveHeader = new HiveHeader();

            hiveHeader.Length = binHeader.BinSize;

            stream.Position = 0;

            byte[] buffer = new byte[hiveHeader.Size];
            hiveHeader.WriteTo(buffer, 0);
            stream.Write(buffer, 0, buffer.Length);

            buffer = new byte[binHeader.Size];
            binHeader.WriteTo(buffer, 0);
            stream.Position = BinStart;
            stream.Write(buffer, 0, buffer.Length);

            buffer = new byte[4];
            Utilities.WriteBytesLittleEndian(binHeader.BinSize - binHeader.Size, buffer, 0);
            stream.Write(buffer, 0, buffer.Length);

            // Make sure the file is initialized out to the end of the firs bin
            stream.Position = BinStart + binHeader.BinSize - 1;
            stream.WriteByte(0);

            // Temporary hive to perform construction of higher-level structures
            RegistryHive newHive  = new RegistryHive(stream);
            KeyNodeCell  rootCell = new KeyNodeCell("root", -1);

            rootCell.Flags = RegistryKeyFlags.Normal | RegistryKeyFlags.Root;
            newHive.UpdateCell(rootCell, true);

            RegistrySecurity sd = new RegistrySecurity();

            sd.SetSecurityDescriptorSddlForm("O:BAG:BAD:PAI(A;;KA;;;SY)(A;CI;KA;;;BA)", AccessControlSections.All);
            SecurityCell secCell = new SecurityCell(sd);

            newHive.UpdateCell(secCell, true);
            secCell.NextIndex     = secCell.Index;
            secCell.PreviousIndex = secCell.Index;
            newHive.UpdateCell(secCell, false);

            rootCell.SecurityIndex = secCell.Index;
            newHive.UpdateCell(rootCell, false);

            // Ref the root cell from the hive header
            hiveHeader.RootCell = rootCell.Index;
            buffer = new byte[hiveHeader.Size];
            hiveHeader.WriteTo(buffer, 0);
            stream.Position = 0;
            stream.Write(buffer, 0, buffer.Length);

            // Finally, return the new hive
            return(new RegistryHive(stream, ownership));
        }