예제 #1
0
 // public constructors...
 /// <summary>
 ///     Initializes a new instance of the <see cref="KeyValue" /> class.
 /// </summary>
 public KeyValue(VKCellRecord vk)
 {
     VKRecord = vk;
     InternalGUID = Guid.NewGuid().ToString();
 }
예제 #2
0
        private List<IRecordBase> ExtractRecordsFromSlack(byte[] remainingData, long relativeoffset)
        {
            var records = new List<IRecordBase>();

            var offsetList2 = new List<int>();

            byte[] raw = null;

            _registryHive._logger.Debug("Looking for cell signatures at absolute offset 0x{0:X}", relativeoffset + 0x1000);

            for (int i = 0; i < remainingData.Length; i++)
            {
                if (remainingData[i] == 0x6b) //6b == k
                {
                    if (remainingData[i - 1] == 0x6e || remainingData[i - 1] == 0x76) //6e = n, 76 = v
                    {
                        //if we are here we have a good signature, nk or vk
                        //check what is before that to see if its 0x00 or 0xFF
                        if (remainingData[i - 2] == 0x00 || remainingData[i - 2] == 0xFF)
                        {
                            //winner! since we initially hit on ZZ, subtract 5 to get to the beginning of the record, XX XX XX XX YY ZZ
                            offsetList2.Add(i - 5); 
                        }
                    }
                }
            }

            //offsetList2 now has offset of every record signature we are interested in
            foreach (var i in offsetList2)
            {
                try
                {
                    var actualStart = i;

                    var size = BitConverter.ToUInt32(remainingData, actualStart);

                    if (size <= 3 || remainingData.Length - actualStart < size)
                    {
                        //if its empty or the size is beyond the data that is left, bail
                        continue;
                    }

                    raw = new ArraySegment<byte>(remainingData, actualStart, Math.Abs((int)size)).ToArray();

                    if (raw.Length<6)
                        continue; // since we need 4 bytes for the size and 2 for sig, if its smaller than 6, go to next one

                    var sig2 = BitConverter.ToInt16(raw, 4);

                    switch (sig2)
                    {
                        case NkSignature:
                            if (raw.Length <= 0x30)
                            {
                                continue;
                            }

                            var nk = new NKCellRecord(raw.Length, relativeoffset + actualStart, _registryHive);
                            if (nk.LastWriteTimestamp.Year > 1900)
                            {
                                _registryHive._logger.Debug("Found nk record in slack at absolute offset 0x{0:X}",
                                    relativeoffset + actualStart + 0x1000);
                                records.Add(nk);
                            }

                            break;
                        case VkSignature:
                            if (raw.Length < 0x18)
                            {
                                //cant have a record shorter than this, even when no name is present
                                continue;
                            }
                            var vk = new VKCellRecord(raw.Length, relativeoffset + actualStart, _minorVersion, _registryHive);
                            _registryHive._logger.Debug("Found vk record in slack at absolute offset 0x{0:X}",
                                relativeoffset + actualStart + 0x1000);
                            records.Add(vk);

                            break;
                    }

                }
                catch (Exception ex)                //ncrunch: no coverage
                {                                   //ncrunch: no coverage
                    // this is a corrupted/unusable record
                    _registryHive._logger.Warn(                       //ncrunch: no coverage
                        ex,$"When recovering from slack at absolute offset 0x{relativeoffset + i + 0x1000:X8}, an error happened! raw Length: 0x{raw.Length:x}");

                    RegistryHive._softParsingErrors += 1;   //ncrunch: no coverage
                }                                   //ncrunch: no coverage
            }


            return records;
        }
예제 #3
0
		private List<KeyValue> GetKeyValues(uint valueListCellIndex, uint valueListCount)
		{
			var values = new List<KeyValue>();

			var offsets = new List<uint>();

			if (valueListCellIndex > 0)
			{
				_logger.Debug("Getting value list offset at relative offset 0x{0:X}. Value count is {1:N0}",
					valueListCellIndex, valueListCount);

				var offsetList = GetDataNodeFromOffset(valueListCellIndex);

				for (var i = 0; i < valueListCount; i++)
				{
					//use i * 4 so we get 4, 8, 12, 16, etc
					var os = BitConverter.ToUInt32(offsetList.Data, i*4);
					_logger.Debug("Got value offset 0x{0:X}", os);
					offsets.Add(os);
				}
			}

			if (offsets.Count != valueListCount)
            { //ncrunch: no coverage
                _logger.Warn("Value count mismatch! ValueListCount is {0:N0} but NKRecord.ValueOffsets.Count is {1:N0}", //ncrunch: no coverage
                    valueListCount, offsets.Count);
            } //ncrunch: no coverage

            foreach (var valueOffset in offsets)
			{
				_logger.Debug("Looking for vk record at relative offset 0x{0:X}", valueOffset);

				var rawVK = GetRawRecord(valueOffset);
				var vk = new VKCellRecord(rawVK.Length, valueOffset, Header.MinorVersion, this);

				_logger.Debug("Found vk record at relative offset 0x{0:X}. Value name: {1}", valueOffset, vk.ValueName);
				var value = new KeyValue(vk);
				values.Add(value);
			}
			
			return values;
		}
예제 #4
0
        public List<IRecordBase> Process()
        {
            var records = new List<IRecordBase>();

            //additional cell data starts 32 bytes (0x20) in
            var offsetInHbin = 0x20;

            _registryHive.TotalBytesRead += 0x20;

            while (offsetInHbin < Size)
            {
                var recordSize = BitConverter.ToUInt32(_rawBytes, offsetInHbin);

                var readSize = (int) recordSize;

                if (!_recoverDeleted && readSize > 0)
                {
                    //since we do not want to get deleted stuff, if the cell size > 0, its free, so skip it
                    offsetInHbin += readSize;
                    continue;
                }

                // if we get a negative number here the record is allocated, but we cant read negative bytes, so get absolute value
                readSize = Math.Abs(readSize);

                var rawRecord = new ArraySegment<byte>(_rawBytes, offsetInHbin, readSize).ToArray();//  new byte[readSize];

                _registryHive.TotalBytesRead += readSize;

                var cellSignature = Encoding.ASCII.GetString(rawRecord, 4, 2);
                var cellSignature2 = BitConverter.ToInt16(rawRecord, 4);

                //ncrunch: no coverage start
                if (_registryHive._logger.IsDebugEnabled)
                {
                    var foundMatch = false;
               
                        foundMatch = Regex.IsMatch(cellSignature, @"\A[a-z]{2}\z");

                    //only process records with 2 letter signatures. this avoids crazy output for data cells
                    if (foundMatch)
                    {
                        _registryHive._logger.Debug("Processing {0} record at hbin relative offset 0x{1:X} (Absolute offset: 0x{2:X})",
                            cellSignature, offsetInHbin, offsetInHbin + RelativeOffset + 0x1000);
                    }
                    else
                    {
                        _registryHive._logger.Debug("Processing data record at hbin relative offset 0x{0:X} (Absolute offset: 0x{1:X})",
                            offsetInHbin, offsetInHbin + RelativeOffset + 0x1000);
                    }  
                }
                //ncrunch: no coverage end

                ICellTemplate cellRecord = null;
                IListTemplate listRecord = null;
                DataNode dataRecord = null;

                try
                {
                    switch (cellSignature2)
                    {
                        case LfSignature:
                        case LhSignature:
                            listRecord = new LxListRecord(rawRecord, offsetInHbin + RelativeOffset);
                            break;

                        case LiSignature:
                            listRecord = new LIListRecord(rawRecord, offsetInHbin + RelativeOffset);

                            break;

                        case RiSignature:
                            listRecord = new RIListRecord(rawRecord, offsetInHbin + RelativeOffset);
                            break;

                        case DbSignature:
                            listRecord = new DBListRecord(rawRecord, offsetInHbin + RelativeOffset);
                            break;

                        case LkSignature:
                            cellRecord = new LKCellRecord(rawRecord, offsetInHbin + RelativeOffset);
                            break; //ncrunch: no coverage

                        case NkSignature:
                            if (rawRecord.Length >= 0x30) // the minimum length for a recoverable record
                            {
                                cellRecord = new NKCellRecord(rawRecord.Length, offsetInHbin + RelativeOffset,
                                    _registryHive);
                            }

                            break;
                        case SkSignature:
                            if (rawRecord.Length >= 0x14)  // the minimum length for a recoverable record
                            {
                                cellRecord = new SKCellRecord(rawRecord, offsetInHbin + RelativeOffset);
                            }
                    
                            break;

                        case VkSignature:
                            if (rawRecord.Length >= 0x18) // the minimum length for a recoverable record
                            {
                                cellRecord = new VKCellRecord(rawRecord.Length, offsetInHbin + RelativeOffset, _minorVersion, _registryHive);
                            }
                            break;

                        default:
                            dataRecord = new DataNode(rawRecord, offsetInHbin + RelativeOffset);
                            break;
                    }
                }
                catch (Exception ex)
                {
                    //check size and see if its free. if so, dont worry about it. too small to be of value, but store it somewhere else?
                

                    var size = BitConverter.ToInt32(rawRecord, 0);

                    if (size < 0)
                    {                                               //ncrunch: no coverage
                        RegistryHive._hardParsingErrors += 1;       //ncrunch: no coverage

                        _registryHive._logger.Error(                             //ncrunch: no coverage     
                            ex,$"Hard error processing record with cell signature {cellSignature} at Absolute Offset: 0x{offsetInHbin + RelativeOffset + 4096:X} with raw data: {BitConverter.ToString(rawRecord)}");

                        //TODO store it somewhere else as a placeholder if its in use. include relative offset and other critical stuff

                    }                                              //ncrunch: no coverage                     
                    else
                    {
                        _registryHive._logger.Warn(
                            ex,$"Soft error processing record with cell signature {cellSignature} at Absolute Offset: 0x{offsetInHbin + RelativeOffset + 4096:X} with raw data: {BitConverter.ToString(rawRecord)}");
                        //This record is marked 'Free' so its not as important of an error
                        RegistryHive._softParsingErrors += 1;
                    }
                }

                List<IRecordBase> carvedRecords = null;

                if (cellRecord != null)
                {
                    if (cellRecord.IsFree)
                    {
                        carvedRecords = ExtractRecordsFromSlack(cellRecord.RawBytes, cellRecord.RelativeOffset);
                    }
                    else
                    {
                        records.Add((IRecordBase) cellRecord);
                    }
                }

                if (listRecord != null)
                {
                    if (_recoverDeleted)
                    {
                        carvedRecords = ExtractRecordsFromSlack(listRecord.RawBytes, listRecord.RelativeOffset);
                    }

                    records.Add((IRecordBase) listRecord);
                }

                if (dataRecord != null && _recoverDeleted)
                {
                    carvedRecords = ExtractRecordsFromSlack(dataRecord.RawBytes, dataRecord.RelativeOffset);
                }

                if (carvedRecords != null)
                {
                    if (carvedRecords.Count > 0)
                    {
                        records.AddRange(carvedRecords);
                    }
                }

                offsetInHbin += readSize;
            }

            _rawBytes = null;
            return records;
        }