public void ProcessValues(RegistryKey key)
        {
            _values.Clear();
            Errors.Clear();

            try
            {
                var arcHist = key.Values.SingleOrDefault(t => t.ValueName == "ArcHistory");

                if (arcHist != null)
                {
                    var arcs = Encoding.Unicode.GetString(arcHist.ValueDataRaw).Split('\0');

                    foreach (var arc in arcs)
                    {
                        if (arc.Trim().Length == 0)
                        {
                            continue;
                        }
                        var v = new ValuesOut(arc);
                        Values.Add(v);
                    }
                }
            }
            catch (Exception ex)
            {
                Errors.Add($"Error processing 7-Zip archive history: {ex.Message}");
            }

            if (Errors.Count > 0)
            {
                AlertMessage = "Errors detected. See Errors information in lower right corner of plugin window";
            }
        }
Beispiel #2
0
        // write entries information under subkey of specified key
        private static void WriteSubKeyData(RegistryKey key, CsvWriter csv, string computerName, string hiveName)
        {
            if (key.SubKeys.Count > 0)
            {
                foreach (var sk in key.SubKeys)
                {
                    if (sk.Values.Count > 0)
                    {
                        WriteValueData(sk, csv, computerName, hiveName);
                    }
                    else // wirte only key and timestamp if no entries exist
                    {
                        var ce = new CacheEntry();

                        ce.ComputerName = computerName;
                        ce.HiveName     = hiveName;
                        ce.Key          = Helpers.StripRootKeyNameFromKeyPath(key.KeyPath);
                        ce.Name         = "";
                        ce.Value        = "";
                        ce.LastModified = key.LastWriteTime.Value.LocalDateTime.ToString("yyyy/MM/dd HH:mm:ss.fff");
                        ce.TimeZone     = key.LastWriteTime.Value.LocalDateTime.ToString("zzz");

                        csv.WriteRecord(ce);
                    }
                }
            }
        }
        public void ProcessValues(RegistryKey key)
        {
            _values.Clear();
            Errors.Clear();

            foreach (var keyValue in key.Values)
            {
                try
                {
                    var unrot = Helpers.Rot13Transform(keyValue.ValueName);
                    var run = 0;

                    string guid = null;
                    try
                    {
                        guid =
                            Regex.Match(unrot, @"\b[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}\b",
                                RegexOptions.IgnoreCase).Value;

                        var foldername = Utils.GetFolderNameFromGuid(guid);

                        unrot = unrot.Replace(guid, foldername);
                    }
                    catch (ArgumentException ex)
                    {
                        // Syntax error in the regular expression
                    }

                    DateTimeOffset? lastRun = null;

                    if (keyValue.ValueDataRaw.Length >= 16)
                    {
                        run = BitConverter.ToInt32(keyValue.ValueDataRaw, 4);

                        lastRun = DateTimeOffset.FromFileTime(BitConverter.ToInt64(keyValue.ValueDataRaw, 8));

                        if (keyValue.ValueDataRaw.Length >= 68)
                        {
                            lastRun = DateTimeOffset.FromFileTime(BitConverter.ToInt64(keyValue.ValueDataRaw, 60));
                        }
                    }

                    if (lastRun?.Year < 1970)
                    {
                        lastRun = null;
                    }

                    var vo = new ValuesOut(keyValue.ValueName, unrot, run, lastRun);

                    _values.Add(vo);
                }
                catch (Exception ex)
                {
                    Errors.Add($"Value name: {keyValue.ValueName}, message: {ex.Message}");
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Generic registry helper to enumerate all registry values
        /// </summary>
        /// <param name="regKey"></param>
        /// <param name="path"></param>
        /// <param name="type"></param>
        /// <param name="info"></param>
        /// <param name="sourceFile"></param>
        private void EnumerateValues(Registry.Abstractions.RegistryKey regKey, string path, string type, string info, string sourceFile)
        {
            DateTimeOffset?modified = regKey.LastWriteTime;

            foreach (Registry.Abstractions.KeyValue regValue in regKey.Values)
            {
                ProcessEntry(regValue.ValueData.ToString(), path, type, info, sourceFile, modified);
            }
        }
        public void ProcessValues(RegistryKey key)
        {
            _values.Clear();
            Errors.Clear();

            foreach (var rd in ProcessKey(key))
            {
                _values.Add(rd);
            }
        }
Beispiel #6
0
        // public constructors...
        public RegistryKey(NKCellRecord nk, RegistryKey parent)
        {
            NKRecord = nk;

            Parent = parent;

            InternalGUID = Guid.NewGuid().ToString();

            SubKeys = new List<RegistryKey>();
            Values = new List<KeyValue>();

            ClassName = string.Empty;
        }
        public void ProcessValues(RegistryKey key)
        {
            _values.Clear();
            Errors.Clear();

            var appcompatValue = key.Values.Single(t => t.ValueName == ValueName);

            var ctl = key.KeyPath.Split('\\').SingleOrDefault(t => t.Contains("ControlSet"));

            var num = -1;

            if (ctl != null)
            {
                num = ctl.ToCharArray().Last();
            }

            try
            {
                var cache = new acc(appcompatValue.ValueDataRaw, num);

                foreach (var c in cache.Caches)
                {
                    foreach (var cacheEntry in c.Entries)
                    {
                        try
                        {
                            var vo = new ValuesOut(cacheEntry.CacheEntryPosition, cacheEntry.Path,
                                cacheEntry.LastModifiedTimeUTC);

                            _values.Add(vo);
                        }
                        catch (Exception ex)
                        {
                            Errors.Add($"Value name: {cacheEntry.CacheEntryPosition}, message: {ex.Message}");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Errors.Add($"Error processing AppCompatCache: {ex.Message}");
            }

            if (Errors.Count > 0)
            {
                AlertMessage = "Errors detected. See Errors information in lower right corner of plugin window";
            }
        }
Beispiel #8
0
        // write entries information recursively under specified key
        private static void WriteSpecificKeyInfo(RegistryKey key, CsvWriter csv, string filepath)
        {
            string computerName = ExtractComputerName(filepath);
            string hiveName     = Path.GetFileName(filepath);

            // processing if entries exist under specified key
            if (key.Values.Count > 0)
            {
                WriteValueData(key, csv, computerName, hiveName);
            }
            // loop processing if entries exist under specified key
            if (key.SubKeys.Count > 0)
            {
                foreach (var sk in key.SubKeys)
                {
                    WriteSubKeyData(sk, csv, computerName, hiveName);
                }
            }
        }
        public void ProcessValues(RegistryKey key)
        {
            _values.Clear();
            Errors.Clear();

            var currVal = string.Empty;

            try
            {
                foreach (var keyValue in key.Values)
                {
                    var vData = string.Empty;

                    currVal = keyValue.ValueName;

                    switch (keyValue.ValueDataRaw[0])
                    {
                        case 0x5f:
                            vData = Encoding.Unicode.GetString(keyValue.ValueDataRaw);
                            break;
                        default:
                            throw new Exception("fix me");
                    }

                    var v1 = new ValuesOut(keyValue.ValueName, vData);

                    Values.Add(v1);
                }
            }
            catch (Exception ex)
            {
                Errors.Add($"Error processing MountedDevices value {currVal}: {ex.Message}");
            }

            if (Errors.Count > 0)
            {
                AlertMessage = "Errors detected. See Errors information in lower right corner of plugin window";
            }
        }
Beispiel #10
0
        // write entries information under specified key
        private static void WriteValueData(RegistryKey key, CsvWriter csv, string computerName, string hiveName)
        {
            foreach (var keyValue in key.Values)
            {
                var ce = new CacheEntry();

                ce.ComputerName = computerName;
                ce.HiveName     = hiveName;
                ce.Key          = Helpers.StripRootKeyNameFromKeyPath(key.KeyPath);
                ce.Name         = keyValue.ValueName;
                if (keyValue.ValueData.Length > 256)
                {
                    ce.Value = $"(Large Data: {keyValue.ValueDataRaw.Length} bytes";
                }
                else
                {
                    ce.Value = keyValue.ValueData;
                }
                ce.LastModified = key.LastWriteTime.Value.LocalDateTime.ToString("yyyy/MM/dd HH:mm:ss.fff");
                ce.TimeZone     = key.LastWriteTime.Value.LocalDateTime.ToString("zzz");

                csv.WriteRecord(ce);
            }
        }
        public void ProcessValues(RegistryKey key)
        {
            _values.Clear();
            Errors.Clear();

            var vn = string.Empty;

            try
            {
                foreach (var keyValue in key.Values)
                {
                    vn = keyValue.ValueName;

                    switch (keyValue.ValueName)
                    {
                        case "Bias":
                            var b0 = BitConverter.ToInt32(keyValue.ValueDataRaw, 0);

                            _values.Add(new ValuesOut(keyValue.ValueName, b0.ToString(), keyValue.ValueData));

                            break;
                        case "StandardName":

                            _values.Add(new ValuesOut(keyValue.ValueName, keyValue.ValueData, keyValue.ValueData));

                            break;
                        case "StandardBias":

                            var b1 = BitConverter.ToInt32(keyValue.ValueDataRaw, 0);

                            _values.Add(new ValuesOut(keyValue.ValueName, b1.ToString(), keyValue.ValueData));

                            break;
                        case "StandardStart":
                            //santiago utc - 4
                            //
                            //start			00 00 0A 00 02 00 17 00 3B 00 3B 00 E7 03 06 00
                            //hour			24
                            //day of week		6
                            //week of month		2
                            //month			10
                            //
                            //			00 00
                            //			0A == 10	Month
                            //			00
                            //			02 		week of month
                            //			00
                            //			17 == 23	hour
                            //			00
                            //			3B == 59	minute
                            //			00
                            //			3B == 59	second
                            //			00
                            //			E7 03 == 999	millisecond?
                            //			06 00		day of week

                            var month0 = keyValue.ValueDataRaw[2];
                            var weekOfMonth0 = keyValue.ValueDataRaw[4];
                            var hour0 = keyValue.ValueDataRaw[6];
                            var minute0 = keyValue.ValueDataRaw[8];
                            var second0 = keyValue.ValueDataRaw[10];
                            var millisecond0 = BitConverter.ToInt16(keyValue.ValueDataRaw, 12);
                            var dayOfWeek0 = keyValue.ValueDataRaw[14];

                            var ss =
                                $"Month {month0}, week of month {weekOfMonth0}, day of week {dayOfWeek0}, Hours:Minutes:Seconds:Milliseconds {hour0}:{minute0}:{second0}:{millisecond0}";

                            _values.Add(new ValuesOut(keyValue.ValueName, ss, keyValue.ValueData));

                            break;
                        case "DaylightName":
                            _values.Add(new ValuesOut(keyValue.ValueName, keyValue.ValueData, keyValue.ValueData));

                            break;
                        case "DaylightBias":
                            var b2 = BitConverter.ToInt32(keyValue.ValueDataRaw, 0);

                            _values.Add(new ValuesOut(keyValue.ValueName, b2.ToString(), keyValue.ValueData));

                            break;
                        case "DaylightStart":

                            var month1 = keyValue.ValueDataRaw[2];
                            var weekOfMonth1 = keyValue.ValueDataRaw[4];
                            var hour1 = keyValue.ValueDataRaw[6];
                            var minute1 = keyValue.ValueDataRaw[8];
                            var second1 = keyValue.ValueDataRaw[10];
                            var millisecond1 = BitConverter.ToInt16(keyValue.ValueDataRaw, 12);
                            var dayOfWeek1 = keyValue.ValueDataRaw[14];

                            var ss1 =
                                $"Month {month1}, week of month {weekOfMonth1}, day of week {dayOfWeek1}, Hours:Minutes:Seconds:Milliseconds {hour1}:{minute1}:{second1}:{millisecond1}";

                            _values.Add(new ValuesOut(keyValue.ValueName, ss1, keyValue.ValueData));

                            break;
                        case "ActiveTimeBias":

                            var b3 = BitConverter.ToInt32(keyValue.ValueDataRaw, 0);

                            _values.Add(new ValuesOut(keyValue.ValueName, b3.ToString(), keyValue.ValueData));

                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                Errors.Add($"Error processing TimeZoneInformation value '{vn}': {ex.Message}");
            }

            if (Errors.Count > 0)
            {
                AlertMessage = "Errors detected. See Errors information in lower right corner of plugin window";
            }
        }
Beispiel #12
0
        public bool ParseHive()
        {
            if (_parsed)
            {
                throw new Exception("ParseHive already called");
            }
            TotalBytesRead = 0;

            TotalBytesRead += 4096;

            _softParsingErrors = 0;
            _hardParsingErrors = 0;

            ////Look at first hbin, get its size, then read that many bytes to create hbin record
            long offsetInHive = 4096;

            var hiveLength = Header.Length + 0x1000;

            //keep reading the file until we reach the end
            while (offsetInHive < hiveLength)
            {
                var hbinSize = BitConverter.ToUInt32(ReadBytesFromHive(offsetInHive + 8, 4), 0);

                if (hbinSize == 0)
                {
                    _logger.Info("Found hbin with size 0 at absolute offset 0x{0:X}", offsetInHive);
                    // Go to end if we find a 0 size block (padding?)
                    offsetInHive = HiveLength();
                    continue;
                }

                var hbinSig = BitConverter.ToInt32(ReadBytesFromHive(offsetInHive, 4), 0);

                if (hbinSig != HbinSignature)
                {
                    _logger.Error("hbin header incorrect at absolute offset 0x{0:X}!!! Percent done: {1:P}",
                        offsetInHive,
                        (double) offsetInHive/hiveLength);

//                    if (RecoverDeleted) //TODO ? always or only if recoverdeleted
//                    {
//                        //TODO need to try to recover records from the bad chunk
//                    }

                    break;
                }

                Check.That(hbinSig).IsEqualTo(HbinSignature);

                _logger.Debug(
                    "Processing hbin at absolute offset 0x{0:X} with size 0x{1:X} Percent done: {2:P}",
                    offsetInHive, hbinSize,
                    (double) offsetInHive/hiveLength);

                var rawhbin = ReadBytesFromHive(offsetInHive, (int) hbinSize);

                try
                {
                    var h = new HBinRecord(rawhbin, offsetInHive - 0x1000, Header.MinorVersion, RecoverDeleted, this);

                    _logger.Trace("hbin info: {0}", h.ToString());

                    _logger.Debug("Getting records from hbin at absolute offset 0x{0:X}", offsetInHive);

                    var records = h.Process();

                    _logger.Debug("Found {0:N0} records from hbin at absolute offset 0x{1:X}", records.Count,
                        offsetInHive);

                    foreach (var record in records)
                    {
                        //TODO change this to compare against constants?
                        switch (record.Signature)
                        {
                            case "nk":
                            case "sk":
                            case "lk":
                            case "vk":
                                _logger.Debug("Adding cell record with signature {0} at absolute offset 0x{1:X}",
                                    record.Signature, record.AbsoluteOffset);

                                CellRecords.Add(record.AbsoluteOffset - 4096, (ICellTemplate) record);
                                break;

                            case "db":
                            case "li":
                            case "ri":
                            case "lh":
                            case "lf":
                                _logger.Debug("Adding list record with signature {0} at absolute offset 0x{1:X}",
                                    record.Signature, record.AbsoluteOffset);

                                ListRecords.Add(record.AbsoluteOffset - 4096, (IListTemplate) record);
                                break;
                        }
                    }

                    HBinRecordCount += 1;
                    HBinRecordTotalSize += hbinSize;
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, $"Error processing hbin at absolute offset 0x{offsetInHive:X}.");
                }

                offsetInHive += hbinSize;
            }

            _logger.Info("Initial processing complete. Building tree...");

            //The root node can be found by either looking at Header.RootCellOffset or looking for an nk record with HiveEntryRootKey flag set.
            //here we are looking for the flag
            var rootNode =
                CellRecords.Values.OfType<NKCellRecord>()
                    .SingleOrDefault(
                        (f =>
                            (f.Flags & NKCellRecord.FlagEnum.HiveEntryRootKey) == NKCellRecord.FlagEnum.HiveEntryRootKey));

            if (rootNode == null)
            {
                throw new KeyNotFoundException("Root nk record not found!");
            }

            //validate what we found above via the flag method
            Check.That((long) Header.RootCellOffset).IsEqualTo(rootNode.RelativeOffset);

            rootNode.IsReferenced = true;

            _logger.Info("Found root node! Getting subkeys...");

            Root = new RegistryKey(rootNode, null);
            _logger.Debug("Created root node object. Getting subkeys.");


            var keys = GetSubKeysAndValues(Root);

            Root.SubKeys.AddRange(keys);

            _logger.Info("Hive processing complete!");

            //All processing is complete, so we do some tests to see if we really saw everything
            if (RecoverDeleted && HiveLength() != TotalBytesRead)
            {
                var remainingHive = ReadBytesFromHive(TotalBytesRead, (int) (HiveLength() - TotalBytesRead));

                //Sometimes the remainder of the file is all zeros, which is useless, so check for that
                if (!Array.TrueForAll(remainingHive, a => a == 0))
                {
                    _logger.Warn(
                        "Extra, non-zero data found beyond hive length! Check for erroneous data starting at 0x{0:x}!",
                        TotalBytesRead);
                }

                //as a second check, compare Header length with what we read (taking the header into account as Header.Length is only for hbin records)

                if (Header.Length != TotalBytesRead - 0x1000)
                {
//ncrunch: no coverage
                    _logger.Warn( //ncrunch: no coverage
                        "Hive length (0x{0:x}) does not equal bytes read (0x{1:x})!! Check the end of the hive for erroneous data",
                        HiveLength(), TotalBytesRead);
                } //ncrunch: no coverage
            }

            if (RecoverDeleted)
            {
                BuildDeletedRegistryKeys();
            }

            if (FlushRecordListsAfterParse)
            {
                _logger.Info("Flushing record lists...");
                ListRecords.Clear();

                var toRemove = CellRecords.Where(pair => pair.Value is NKCellRecord || pair.Value is VKCellRecord)
                    .Select(pair => pair.Key)
                    .ToList();

                foreach (var key in toRemove)
                {
                    CellRecords.Remove(key);
                }
            }
            _parsed = true;
            return true;
        }
        public void ProcessValues(RegistryKey key)
        {
            _values.Clear();
            Errors.Clear();

            var namesKey = key.SubKeys.SingleOrDefault(t => t.KeyName == "Names");

            var nameMap = new Dictionary<int, DateTimeOffset>();

            if (namesKey == null)
            {
                return;
            }

            foreach (var registryKey in namesKey.SubKeys)
            {
                if (nameMap.ContainsKey((int) registryKey.Values.First().VKRecord.DataTypeRaw))
                {
                    continue;
                }
                nameMap.Add((int) registryKey.Values.First().VKRecord.DataTypeRaw, registryKey.LastWriteTime.Value);
            }

            foreach (var key1 in key.SubKeys)
            {
                if (key1.KeyName == "Names")
                {
                    continue;
                }

                try
                {
                    var fVal = key1.Values.SingleOrDefault(t => t.ValueName == "F");

                    var userId = 0;
                    var invalidLogins = 0;
                    var totalLogins = 0;
                    DateTimeOffset? lastLoginTime = null;
                    DateTimeOffset? lastPwChangeTime = null;
                    DateTimeOffset? acctExpiresTime = null;
                    DateTimeOffset? lastIncorrectPwTime = null;

                    if (fVal != null)
                    {
                        userId = BitConverter.ToInt32(fVal.ValueDataRaw, 0x30);
                        invalidLogins = BitConverter.ToInt16(fVal.ValueDataRaw, 0x40);
                        totalLogins = BitConverter.ToInt16(fVal.ValueDataRaw, 0x42);

                        var tempTime = DateTimeOffset.FromFileTime(BitConverter.ToInt64(fVal.ValueDataRaw, 0x8));
                        if (tempTime.Year > 1700)
                        {
                            lastLoginTime = tempTime.ToUniversalTime();
                        }

                        tempTime = DateTimeOffset.FromFileTime(BitConverter.ToInt64(fVal.ValueDataRaw, 0x18));
                        if (tempTime.Year > 1700)
                        {
                            lastPwChangeTime = tempTime.ToUniversalTime();
                        }

                        tempTime = DateTimeOffset.MinValue;

                        try
                        {
                            tempTime = DateTimeOffset.FromFileTime(BitConverter.ToInt64(fVal.ValueDataRaw, 0x20));
                        }
                        catch (Exception)
                        {
                        }

                        if (tempTime.Year > 1700)
                        {
                            acctExpiresTime = tempTime.ToUniversalTime();
                        }

                        tempTime = DateTimeOffset.FromFileTime(BitConverter.ToInt64(fVal.ValueDataRaw, 0x28));
                        if (tempTime.Year > 1700)
                        {
                            lastIncorrectPwTime = tempTime.ToUniversalTime();
                        }
                    }

                    var vVal = key1.Values.SingleOrDefault(t => t.ValueName == "V");

                    var offToName = BitConverter.ToInt32(vVal.ValueDataRaw, 0xc) + 0xCC;
                    var nameLen = BitConverter.ToInt32(vVal.ValueDataRaw, 0xc + 4);
                    var name1 = Encoding.Unicode.GetString(vVal.ValueDataRaw, offToName, nameLen);

                    var offToFull = BitConverter.ToInt32(vVal.ValueDataRaw, 0x18) + 0xCC;
                    var fullLen = BitConverter.ToInt32(vVal.ValueDataRaw, 0x18 + 4);
                    var full1 = Encoding.Unicode.GetString(vVal.ValueDataRaw, offToFull, fullLen);

                    var offToComment = BitConverter.ToInt32(vVal.ValueDataRaw, 0x24) + 0xCC;
                    var commentLen = BitConverter.ToInt32(vVal.ValueDataRaw, 0x24 + 4);
                    var comment = Encoding.Unicode.GetString(vVal.ValueDataRaw, offToComment, commentLen);

                    var offToUserComment = BitConverter.ToInt32(vVal.ValueDataRaw, 0x30) + 0xCC;
                    var userCommentLen = BitConverter.ToInt32(vVal.ValueDataRaw, 0x30 + 4);
                    var userComment = Encoding.Unicode.GetString(vVal.ValueDataRaw, offToUserComment, userCommentLen);

                    var offHomeDir = BitConverter.ToInt32(vVal.ValueDataRaw, 0x48) + 0xCC;
                    var homeDirLen = BitConverter.ToInt32(vVal.ValueDataRaw, 0x48 + 4);
                    var homeDir = Encoding.Unicode.GetString(vVal.ValueDataRaw, offHomeDir, homeDirLen);

                    var createdOn = nameMap[userId];

                    var u = new UserOut(userId, invalidLogins, totalLogins, lastLoginTime, lastPwChangeTime,
                        lastIncorrectPwTime, acctExpiresTime, name1, full1, comment, userComment, homeDir, createdOn);

                    _values.Add(u);
                }
                catch (Exception ex)
                {
                    Errors.Add($"Error processing user account: {ex.Message}");
                }

                if (Errors.Count > 0)
                {
                    AlertMessage = "Errors detected. See Errors information in lower right corner of plugin window";
                }
            }
        }
Beispiel #14
0
        public void ProcessValues(RegistryKey key)
        {
            _values.Clear();
            Errors.Clear();

            var valuesList = new List<ValuesOut>();

            var currentKey = string.Empty;

            try
            {
                currentKey = key.KeyName;

                //get MRU key and read it in

                var mruVal = key.Values.SingleOrDefault(t => t.ValueName == "MRUList");

                var mruListOrder = new ArrayList();

                if (mruVal != null)
                {
                    foreach (var c in mruVal.ValueData.ToCharArray())
                    {
                        mruListOrder.Add(c.ToString());
                    }
                }

                foreach (var keyValue in key.Values)
                {
                    if (keyValue.ValueName == "MRUList")
                    {
                        continue;
                    }

                    var mru = mruListOrder.IndexOf(keyValue.ValueName);

                    DateTimeOffset? openedOn = null;

                    if (mru == 0)
                    {
                        openedOn = key.LastWriteTime;
                    }

                    var vd = keyValue.ValueData;

                    if (vd.EndsWith(@"\1"))
                    {
                        vd = keyValue.ValueData.Substring(0, keyValue.ValueData.Length - 2);
                    }

                    var v = new ValuesOut(keyValue.ValueName, vd, mru, openedOn);

                    valuesList.Add(v);
                }
            }
            catch (Exception ex)
            {
                Errors.Add($"Error processing RunMRU subkey {currentKey}: {ex.Message}");
            }

            if (Errors.Count > 0)
            {
                AlertMessage = "Errors detected. See Errors information in lower right corner of plugin window";
            }

            var v1 = valuesList.OrderBy(t => t.MruPosition);

            foreach (var source in v1.ToList())
            {
                _values.Add(source);
            }
        }
Beispiel #15
0
        private void DumpKeyCommonFormat(RegistryKey key, StreamWriter sw, ref int keyCount,
            ref int valueCount)
        {
            if (((key.KeyFlags & RegistryKey.KeyFlagsEnum.HasActiveParent) == RegistryKey.KeyFlagsEnum.HasActiveParent) &&
                ((key.KeyFlags & RegistryKey.KeyFlagsEnum.Deleted) == RegistryKey.KeyFlagsEnum.Deleted))
            {
                return;
            }

            foreach (var subkey in key.SubKeys)
            {
                if (((subkey.KeyFlags & RegistryKey.KeyFlagsEnum.HasActiveParent) ==
                     RegistryKey.KeyFlagsEnum.HasActiveParent) &&
                    ((subkey.KeyFlags & RegistryKey.KeyFlagsEnum.Deleted) == RegistryKey.KeyFlagsEnum.Deleted))
                {
                    return;
                }

                keyCount += 1;

                sw.WriteLine("key|{0}|{1}|{2}|{3}", subkey.NKRecord.IsFree ? "U" : "A",
                    subkey.NKRecord.AbsoluteOffset, subkey.KeyPath,
                    subkey.LastWriteTime.Value.UtcDateTime.ToString("o"));

                foreach (var val in subkey.Values)
                {
                    valueCount += 1;

                    sw.WriteLine(@"value|{0}|{1}|{2}|{3}|{4}|{5}", val.VKRecord.IsFree ? "U" : "A",
                        val.VKRecord.AbsoluteOffset, subkey.KeyName, val.ValueName, (int) val.VKRecord.DataType,
                        BitConverter.ToString(val.VKRecord.ValueDataRaw).Replace("-", " "));
                }

                DumpKeyCommonFormat(subkey, sw, ref keyCount, ref valueCount);
            }
        }
        public void ProcessValues(RegistryKey key)
        {
            _values.Clear();
            Errors.Clear();

            try
            {
                foreach (var keyValue in key.Values)
                {
                    //[F00000000][T01D005C5B44B6300][O00000000]*C:\Users\eric\Desktop\aa\Out\Deduplicated.tsv

                    var segs = keyValue.ValueData.Split('*');
                    var fName = segs.Last();

                    var segs2 = segs.First().Split('[');
                    //"T01D005C5B44B6300]"

                    var rawTime = segs2[2];
                    rawTime = rawTime.Substring(1);
                    rawTime = rawTime.Substring(0, rawTime.Length - 1);
                    var time = Convert.ToInt64(rawTime, 16);

                    var firstOpen = DateTimeOffset.FromFileTime(time);

                    //  @"Software\Microsoft\Office\15.0\Word\User MRU\*\File MRU", //Software\Microsoft\Office\15.0\Word\Reading Locations
                    //Software\Microsoft\Office\15.0\Word\Reading Locations
                    //Value Name	Value Type	Data
                    //File Path   RegSz C:\ProjectWorkingFolder\GOON2\GOON2\GOON2Manual.docx

                    //jump up a few levels and check for Reading Locations
                    var readingLocKey =
                        key.Parent.Parent.Parent.SubKeys.SingleOrDefault(t => t.KeyName == "Reading Locations");

                    DateTimeOffset? lastOpen = null;

                    if (readingLocKey != null)
                    {
                        foreach (var registryKey in readingLocKey.SubKeys)
                        {
                            var readingLocVal = registryKey.Values.SingleOrDefault(t => t.ValueName == "File Path");

                            if (readingLocVal != null)
                            {
                                if (readingLocVal.ValueData == fName)
                                {
                                    lastOpen = registryKey.LastWriteTime;
                                    break;
                                }
                            }
                        }
                    }

                    var v = new ValuesOut(keyValue.ValueName, firstOpen, lastOpen, fName);

                    _values.Add(v);
                }
            }
            catch (Exception ex)
            {
                Errors.Add($"Error processing MRU key: {ex.Message}");
            }

            if (Errors.Count > 0)
            {
                AlertMessage = "Errors detected. See Errors information in lower right corner of plugin window";
            }
        }
Beispiel #17
0
 public ValueBySizeInfo(RegistryKey key, KeyValue value)
 {
     Key = key;
       Value = value;
 }
        private IEnumerable<RecentDoc> ProcessRecentKey(RegistryKey key)
        {
            var l = new List<RecentDoc>();

            try
            {
                var mruList = key.Values.Single(t => t.ValueName == "MRUListEx");

                var mruPositions = new Dictionary<uint, int>();

                var i = 0;

                var index = 0;

                var mruPos = BitConverter.ToUInt32(mruList.ValueDataRaw, index);
                index += 4;

                while (mruPos != 0xFFFFFFFF)
                {
                    mruPositions.Add(mruPos, i);
                    i++;
                    mruPos = BitConverter.ToUInt32(mruList.ValueDataRaw, index);
                    index += 4;
                }

                //mruPositions now contains a map of positions (the key) to the order it was opened (the value)

                foreach (var keyValue in key.Values)
                {
                    if (keyValue.ValueName == "MRUListEx" || keyValue.ValueName == "ViewStream")
                    {
                        continue;
                    }

                    var mru = mruPositions[uint.Parse(keyValue.ValueName)];

                    var targetName = Encoding.Unicode.GetString(keyValue.ValueDataRaw).Split('\0')[0];

                    var offsetToRemainingData = targetName.Length*2 + 2;

                    //TODO do not use Skip. use Buffer.BlockCopy as its faster

                    var remainingData = keyValue.ValueDataRaw.Skip(offsetToRemainingData).ToArray();

                    index = 0;

                    var chunkLen = BitConverter.ToUInt16(remainingData, index);

                    var chunks = new List<byte[]>();

                    while (remainingData.Length > index)
                    {
                        var chunk = remainingData.Skip(index).Take(chunkLen).ToArray();

                        chunks.Add(chunk);

                        index += chunkLen;

                        chunkLen = BitConverter.ToUInt16(remainingData, index);

                        if (chunkLen == 0)
                        {
                            break;
                        }
                    }

                    index = 2; //skip chunk length
                    var lnkNameType = chunks[0][index]; // if 32, its unicode, if 36, ascii
                    index += 12; //skip type that always seems to be [32|36]-00-00-00-00-00-00-00-00-00-00-00-

                    var lnkName = "";

                    if (lnkNameType == 36)
                    {
                        lnkName = Encoding.Unicode.GetString(chunks[0].Skip(index).ToArray()).Split('\0')[0];
                        index += lnkName.Length*2;
                    }
                    else
                    {
                        lnkName = Encoding.GetEncoding(1252).GetString(chunks[0].Skip(index).ToArray()).Split('\0')[0];
                        index += lnkName.Length;
                    }

                    while (chunks[0][index] != 4)
                    {
                        index += 1; //move until our signature
                    }

                    index -= 4; //jump back to start of extension block

                    var beefBytes = chunks[0].Skip(index).ToArray();

                    var sig = BitConverter.ToUInt32(beefBytes, 4);
                    var beef = (Beef0004) Utils.GetExtensionBlockFromBytes(sig, beefBytes);

                    DateTimeOffset? openedOn = null;

                    if (mru == 0)
                    {
                        openedOn = key.LastWriteTime;
                    }

                    DateTimeOffset? extLastOpened = null;

                    var ext = Path.GetExtension(targetName).ToLowerInvariant();

                    var targetName1 = string.Empty;

                    if (ext.Length == 0)
                    {
                        //folder
                        var sk1 = key.SubKeys.SingleOrDefault(t => t.KeyName == "Folder");
                        var skmru = sk1?.Values.SingleOrDefault(t => t.ValueName == "MRUListEx");

                        if (skmru != null)
                        {
                            //get last accessed folder value name
                            var mruPosf = BitConverter.ToInt32(skmru.ValueDataRaw, 0);

                            //pull folder name from the value
                            var val1 = sk1.Values.SingleOrDefault(t => t.ValueName == mruPosf.ToString());

                            targetName1 = Encoding.Unicode.GetString(val1.ValueDataRaw).Split('\0')[0];
                        }

                        if (sk1 != null && targetName1 == targetName)
                        {
                            extLastOpened = sk1.LastWriteTime;
                        }
                    }
                    else
                    {
                        var sk2 = key.SubKeys.SingleOrDefault(t => t.KeyName.ToLowerInvariant() == ext);
                        var skmruf = sk2?.Values.SingleOrDefault(t => t.ValueName == "MRUListEx");

                        if (skmruf != null)
                        {
                            //get last accessed folder value name
                            var mruPosff = BitConverter.ToInt32(skmruf.ValueDataRaw, 0);

                            //pull folder name from the value
                            var val1 = sk2.Values.SingleOrDefault(t => t.ValueName == mruPosff.ToString());

                            targetName1 = Encoding.Unicode.GetString(val1.ValueDataRaw).Split('\0')[0];
                        }

                        if (sk2 != null && targetName1 == targetName)
                        {
                            extLastOpened = sk2.LastWriteTime;
                        }
                    }

                    var rd = new RecentDoc(mru, keyValue.ValueName, targetName, beef.MFTInformation.MFTEntryNumber,
                        beef.MFTInformation.MFTSequenceNumber, beef.MFTInformation.Note, beef.CreatedOnTime,
                        beef.LastAccessTime, beef.LongName, key.KeyName, openedOn, extLastOpened);
                    l.Add(rd);
                }
            }
            catch (Exception ex)
            {
                Errors.Add($"Error processing recent key ({key.KeyPath}): {ex.Message}");
            }

            foreach (var registryKey in key.SubKeys)
            {
                var subItems = ProcessRecentKey(registryKey);

                l.AddRange(subItems);
            }

            if (Errors.Count > 0)
            {
                AlertMessage = "Errors detected. See Errors information in lower right corner of plugin window";
            }

            l = l.OrderByDescending(t => t.Extension).ThenBy(t => t.MruPosition).ToList();

            return l;
        }
Beispiel #19
0
        //TODO this needs refactored to remove duplicated code
        private List<RegistryKey> GetSubKeysAndValues(RegistryKey key)
        {
            RelativeOffsetKeyMap.Add(key.NKRecord.RelativeOffset, key);

            KeyPathKeyMap.Add(key.KeyPath.ToLowerInvariant(), key);

            _logger.Debug("Getting subkeys for {0}", key.KeyPath);

            key.KeyFlags = RegistryKey.KeyFlagsEnum.HasActiveParent;

            var keys = new List<RegistryKey>();

            if (key.NKRecord.ClassCellIndex > 0)
            {
                _logger.Debug("Getting Class cell information at relative offset 0x{0:X}", key.NKRecord.ClassCellIndex);
                var d = GetDataNodeFromOffset(key.NKRecord.ClassCellIndex);
                d.IsReferenced = true;
                var clsName = Encoding.Unicode.GetString(d.Data, 0, key.NKRecord.ClassLength);
                key.ClassName = clsName;
                _logger.Debug("Class name found {0}", clsName);
            }

            //Build ValueOffsets for this NKRecord
            if (key.NKRecord.ValueListCellIndex > 0)
            {
                //there are values for this key, so get the offsets so we can pull them next

                _logger.Debug("Getting value list offset at relative offset 0x{0:X}. Value count is {1:N0}",
                    key.NKRecord.ValueListCellIndex, key.NKRecord.ValueListCount);

                var offsetList = GetDataNodeFromOffset(key.NKRecord.ValueListCellIndex);

                offsetList.IsReferenced = true;

                for (var i = 0; i < key.NKRecord.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);
                    key.NKRecord.ValueOffsets.Add(os);
                }
            }

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

            // look for values in this key 
            foreach (var valueOffset in key.NKRecord.ValueOffsets)
            {
                _logger.Debug("Looking for vk record at relative offset 0x{0:X}", valueOffset);
                var vc = CellRecords[(long) valueOffset];

                var vk = vc as VKCellRecord;

                _logger.Debug("Found vk record at relative offset 0x{0:X}. Value name: {1}", valueOffset, vk.ValueName);

                vk.IsReferenced = true;

                var value = new KeyValue(vk);

                key.Values.Add(value);
            }

            _logger.Debug("Looking for sk record at relative offset 0x{0:X}", key.NKRecord.SecurityCellIndex);

            var sk = CellRecords[key.NKRecord.SecurityCellIndex] as SKCellRecord;
            sk.IsReferenced = true;

            //TODO THIS SHOULD ALSO CHECK THE # OF SUBKEYS == 0
            if (ListRecords.ContainsKey(key.NKRecord.SubkeyListsStableCellIndex) == false)
            {
                return keys;
            }

            _logger.Debug("Looking for list record at relative offset 0x{0:X}", key.NKRecord.SubkeyListsStableCellIndex);
            var l = ListRecords[key.NKRecord.SubkeyListsStableCellIndex];

            var sig = BitConverter.ToInt16(l.RawBytes, 4);

            switch (sig)
            {
                case LfSignature:
                case LhSignature:
                    var lxRecord = l as LxListRecord;
                    lxRecord.IsReferenced = true;

                    foreach (var offset in lxRecord.Offsets)
                    {
                        _logger.Debug("In lf or lh, looking for nk record at relative offset 0x{0:X}", offset.Key);
                        var cell = CellRecords[offset.Key];

                        var nk = cell as NKCellRecord;
                        nk.IsReferenced = true;

                        _logger.Debug("In lf or lh, found nk record at relative offset 0x{0:X}. Name: {1}", offset.Key,
                            nk.Name);

                        var tempKey = new RegistryKey(nk, key);

                        var sks = GetSubKeysAndValues(tempKey);
                        tempKey.SubKeys.AddRange(sks);

                        keys.Add(tempKey);
                    }
                    break;

                case RiSignature:
                    var riRecord = l as RIListRecord;
                    riRecord.IsReferenced = true;

                    foreach (var offset in riRecord.Offsets)
                    {
                        _logger.Debug("In ri, looking for list record at relative offset 0x{0:X}", offset);
                        var tempList = ListRecords[offset];

                        //templist is now an li or lh list 

                        if (tempList.Signature == "li")
                        {
                            var sk3 = tempList as LIListRecord;

                            foreach (var offset1 in sk3.Offsets)
                            {
                                _logger.Debug("In ri/li, looking for nk record at relative offset 0x{0:X}", offset1);
                                var cell = CellRecords[offset1];

                                var nk = cell as NKCellRecord;
                                nk.IsReferenced = true;

                                var tempKey = new RegistryKey(nk, key);

                                var sks = GetSubKeysAndValues(tempKey);
                                tempKey.SubKeys.AddRange(sks);

                                keys.Add(tempKey);
                            }
                        }
                        else
                        {
                            var lxRecord_ = tempList as LxListRecord;
                            lxRecord_.IsReferenced = true;

                            foreach (var offset3 in lxRecord_.Offsets)
                            {
                                _logger.Debug("In ri/li, looking for nk record at relative offset 0x{0:X}", offset3.Key);
                                var cell = CellRecords[offset3.Key];

                                var nk = cell as NKCellRecord;
                                nk.IsReferenced = true;

                                var tempKey = new RegistryKey(nk, key);

                                var sks = GetSubKeysAndValues(tempKey);
                                tempKey.SubKeys.AddRange(sks);

                                keys.Add(tempKey);
                            }
                        }
                    }

                    break;

                case LiSignature:
                    var liRecord = l as LIListRecord;
                    liRecord.IsReferenced = true;

                    foreach (var offset in liRecord.Offsets)
                    {
                        _logger.Debug("In li, looking for nk record at relative offset 0x{0:X}", offset);
                        var cell = CellRecords[offset];

                        var nk = cell as NKCellRecord;
                        nk.IsReferenced = true;

                        var tempKey = new RegistryKey(nk, key);

                        var sks = GetSubKeysAndValues(tempKey);
                        tempKey.SubKeys.AddRange(sks);

                        keys.Add(tempKey);
                    }

                    break;
                default:
                    throw new Exception($"Unknown subkey list type {l.Signature}!");
            }

            return keys;
        }
        public void ProcessValues(RegistryKey key)
        {
            _values.Clear();
            Errors.Clear();

            var valuesList = new List<ValuesOut>();

            var currentKey = string.Empty;

            try
            {
                //this key has folders stored in the root as well

                var mruVal1 = key.Values.SingleOrDefault(t => t.ValueName == "MRUList");

                var mruListOrder1 = new ArrayList();

                if (mruVal1 != null)
                {
                    foreach (var c in mruVal1.ValueData.ToCharArray())
                    {
                        mruListOrder1.Add(c.ToString());
                    }
                }

                foreach (var keyValue in key.Values)
                {
                    if (keyValue.ValueName == "MRUList")
                    {
                        continue;
                    }
                    var mru1 = mruListOrder1.IndexOf(keyValue.ValueName);

                    DateTimeOffset? openedOn1 = null;

                    if (mru1 == 0)
                    {
                        openedOn1 = key.LastWriteTime;
                    }

                    var v1 = new ValuesOut("OpenSaveMRU", keyValue.ValueData, keyValue.ValueName, mru1, openedOn1);

                    valuesList.Add(v1);
                }

                foreach (var registryKey in key.SubKeys)
                {
                    currentKey = registryKey.KeyName;

                    //get MRU key and read it in

                    var mruVal = registryKey.Values.SingleOrDefault(t => t.ValueName == "MRUList");

                    var mruListOrder = new ArrayList();

                    if (mruVal != null)
                    {
                        foreach (var c in mruVal.ValueData.ToCharArray())
                        {
                            mruListOrder.Add(c.ToString());
                        }
                    }

                    foreach (var keyValue in registryKey.Values)
                    {
                        if (keyValue.ValueName == "MRUList")
                        {
                            continue;
                        }

                        var mru = mruListOrder.IndexOf(keyValue.ValueName);

                        DateTimeOffset? openedOn = null;

                        if (mru == 0)
                        {
                            openedOn = registryKey.LastWriteTime;
                        }

                        var v = new ValuesOut(registryKey.KeyName, keyValue.ValueData, keyValue.ValueName, mru, openedOn);

                        valuesList.Add(v);
                    }
                }
            }
            catch (Exception ex)
            {
                Errors.Add($"Error processing OpenSaveMRU subkey {currentKey}: {ex.Message}");
            }

            if (Errors.Count > 0)
            {
                AlertMessage = "Errors detected. See Errors information in lower right corner of plugin window";
            }

            var v2 = valuesList.OrderBy(t => t.MruPosition);

            foreach (var source in v2.ToList())
            {
                _values.Add(source);
            }
        }
Beispiel #21
0
        private void UpdateChildPaths(RegistryKey key)
        {
            _logger.Trace("Updating child paths or key {0}", key.KeyPath);
            foreach (var sk in key.SubKeys)
            {
                sk.KeyPath = $@"{key.KeyPath}\{sk.KeyName}";

                RelativeOffsetKeyMap.Add(sk.NKRecord.RelativeOffset, sk);

                if (KeyPathKeyMap.ContainsKey(sk.KeyPath.ToLowerInvariant()) == false)
                {
                    KeyPathKeyMap.Add(sk.KeyPath.ToLowerInvariant(), sk);
                }

                UpdateChildPaths(sk);
            }
        }
        public void ProcessValues(RegistryKey key)
        {
            _values.Clear();
            Errors.Clear();

            var currentKey = string.Empty;

            try
            {
                foreach (var registryKey in key.SubKeys) // subkeys of FileExts
                {
                    currentKey = registryKey.KeyName;

                    var oe = new List<string>();
                    var op = new List<string>();
                    var uc = "(UserChoice key not present)";

                    if (registryKey.SubKeys.Count == 0)
                    {
                        var progId = registryKey.Values.SingleOrDefault(t => t.ValueName == "Progid");
                        if (progId != null)
                        {
                            op.Add(progId.ValueData);
                        }
                        var vo1 = new ValuesOut(registryKey.KeyName, string.Join(", ", oe), string.Join(", ", op), uc);

                        _values.Add(vo1);
                        continue;
                    }

                    foreach (var subKey in registryKey.SubKeys) // subkey's subkeys
                    {
                        switch (subKey.KeyName)
                        {
                            case "OpenWithList":
                                // contains values with name == char and value data of an executable name
                                //there is an MRUList that contains the order the executables were selected

                                var mruList = subKey.Values.SingleOrDefault(t => t.ValueName == "MRUList");

                                if (mruList != null)
                                {
                                    //foreach slot in MRU, get the value and append it to our oe variable

                                    foreach (var mruPos in mruList.ValueData.ToCharArray())
                                    {
                                        var exeName =
                                            subKey.Values.SingleOrDefault(t => t.ValueName == mruPos.ToString());

                                        if (exeName != null)
                                        {
                                            oe.Add(exeName.ValueData);
                                        }
                                        else
                                        {
                                            oe.Add($"(Executable name for MRU slot '{mruPos}' not found!)");
                                        }
                                    }
                                }

                                break;
                            case "OpenWithProgids":
                                foreach (var proIdValue in subKey.Values)
                                {
                                    op.Add(proIdValue.ValueName);
                                }
                                break;
                            case "UserChoice":
                                var progId = subKey.Values.SingleOrDefault(t => t.ValueName == "ProgId");
                                if (progId != null)
                                {
                                    uc = progId.ValueData;
                                }
                                break;
                        }
                    }

                    //we have enough to add an entry

                    var vo = new ValuesOut(registryKey.KeyName, string.Join(", ", oe), string.Join(", ", op), uc);

                    _values.Add(vo);
                }
            }
            catch (Exception ex)
            {
                Errors.Add($"Error processing FileExts subkey {currentKey}: {ex.Message}");
            }

            if (Errors.Count > 0)
            {
                AlertMessage = "Errors detected. See Errors information in lower right corner of plugin window";
            }
        }
		public RegistryKey GetKey(string keyPath)
		{
			var rawRoot = GetRawRecord(Header.RootCellOffset);

			var rootNk = new NKCellRecord(rawRoot.Length, Header.RootCellOffset, this);

		    var newPath = keyPath.ToLowerInvariant();

            // when getting child keys, the name may start with the root key name. if so, strip it
            if (newPath.StartsWith(rootNk.Name.ToLowerInvariant()))
		    {
		        var segs = keyPath.Split('\\');
                newPath = string.Join("\\", segs.Skip(1));
		    }

			var rootKey = new RegistryKey(rootNk, null);

			var keyNames = newPath.Split(new[] {'\\'}, StringSplitOptions.RemoveEmptyEntries);

			rootKey.SubKeys.AddRange(GetSubkeys(rootKey.NKRecord.SubkeyListsStableCellIndex, rootKey));

			var finalKey = rootKey;
			
			for (var i = 0; i < keyNames.Length; i++)
			{
				finalKey = finalKey.SubKeys.SingleOrDefault(r => r.KeyName.ToLowerInvariant() == keyNames[i].ToLowerInvariant());

				if (finalKey == null)
				{
					return null;
				}

				if (finalKey.NKRecord.SubkeyListsStableCellIndex > 0)
				{
					finalKey.SubKeys.AddRange(GetSubkeys(finalKey.NKRecord.SubkeyListsStableCellIndex, finalKey));
				}
			}

			finalKey.Values.AddRange(GetKeyValues(finalKey.NKRecord.ValueListCellIndex, finalKey.NKRecord.ValueListCount));

            if (finalKey.NKRecord.ClassCellIndex > 0)
            {
                _logger.Debug("Getting Class cell information at relative offset 0x{0:X}", finalKey.NKRecord.ClassCellIndex);
                var d = GetDataNodeFromOffset(finalKey.NKRecord.ClassCellIndex);
                d.IsReferenced = true;
                var clsName = Encoding.Unicode.GetString(d.Data, 0, finalKey.NKRecord.ClassLength);
                finalKey.ClassName = clsName;
                _logger.Debug("Class name found {0}", clsName);
            }

            return finalKey;
		}
Beispiel #24
0
        /// <summary>
        ///     Associates vk records with NK records and builds a hierarchy of nk records
        ///     <remarks>Results of this method will be available in DeletedRegistryKeys</remarks>
        /// </summary>
        private void BuildDeletedRegistryKeys()
        {
            _logger.Info("Associating deleted keys and values...");

            var unreferencedNKCells = CellRecords.Where(t => t.Value.IsReferenced == false && t.Value is NKCellRecord);

            var associatedVKRecordOffsets = new List<long>();

            var _deletedRegistryKeys = new Dictionary<long, RegistryKey>();

            //Phase one is to associate any value records with key records
            foreach (var unreferencedNkCell in unreferencedNKCells)
            {
                try
                {
                    var nk = unreferencedNkCell.Value as NKCellRecord;

                    _logger.Debug("Processing deleted nk record at absolute offset 0x{0:X}", nk.AbsoluteOffset);

                    nk.IsDeleted = true;

                    var regKey = new RegistryKey(nk, null)
                    {
                        KeyFlags = RegistryKey.KeyFlagsEnum.Deleted
                    };

                    //some sanity checking on things
                    if (regKey.NKRecord.Size < 0x50 + regKey.NKRecord.NameLength)
                    {
                        continue;
                    }

                    //Build ValueOffsets for this NKRecord
                    if (regKey.NKRecord.ValueListCellIndex > 0)
                    {
                        //there are values for this key, so get the offsets so we can pull them next

                        _logger.Debug("Processing deleted nk record values for nk at absolute offset 0x{0:X}",
                            nk.AbsoluteOffset);

                        DataNode offsetList = null;

                        var size = ReadBytesFromHive(regKey.NKRecord.ValueListCellIndex + 4096, 4);

                        var sizeNum = Math.Abs(BitConverter.ToUInt32(size, 0));

                        if (sizeNum > regKey.NKRecord.ValueListCount*4 + 4)
                        {
                            //ValueListCount is the number of offsets we should be looking for. they are 4 bytes long
                            //If the size of the data record at regKey.NKRecord.ValueListCellIndex exceeds the total number of bytes plus the size (another 4 bytes), reset it to a more sane value to avoid crazy long reads
                            sizeNum = regKey.NKRecord.ValueListCount*4 + 4;
                        }

                        try
                        {
                            var rawData = ReadBytesFromHive(regKey.NKRecord.ValueListCellIndex + 4096,
                                (int) sizeNum);

                            var dr = new DataNode(rawData, regKey.NKRecord.ValueListCellIndex);

                            offsetList = dr;
                        }
                        catch (Exception) //ncrunch: no coverage
                        {
//ncrunch: no coverage
                            //sometimes the data node doesn't have enough data to even do this, or its wrong data
                            _logger.Warn( //ncrunch: no coverage
                                "When getting values for nk record at absolute offset 0x{0:X}, not enough/invalid data was found at offset 0x{1:X}to look for value offsets. Value recovery is not possible",
                                nk.AbsoluteOffset, regKey.NKRecord.ValueListCellIndex);
                        } //ncrunch: no coverage

                        if (offsetList != null)
                        {
                            _logger.Debug("Found offset list for nk at absolute offset 0x{0:X}. Processing.",
                                nk.AbsoluteOffset);
                            try
                            {
                                for (var i = 0; i < regKey.NKRecord.ValueListCount; i++)
                                {
                                    //use i * 4 so we get 4, 8, 12, 16, etc
                                    var os = BitConverter.ToUInt32(offsetList.Data, i*4);

                                    regKey.NKRecord.ValueOffsets.Add(os);
                                }
                            }
                            catch (Exception) //ncrunch: no coverage
                            {
//ncrunch: no coverage
                                _logger.Warn( //ncrunch: no coverage
                                    "When getting value offsets for nk record at absolute offset 0x{0:X}, not enough data was found at offset 0x{1:X} to look for all value offsets. Only partial value recovery possible",
                                    nk.AbsoluteOffset, regKey.NKRecord.ValueListCellIndex);
                            } //ncrunch: no coverage
                        }
                    }

                    _logger.Debug("Looking for vk records for nk record at absolute offset 0x{0:X}", nk.AbsoluteOffset);

                    //For each value offset, get the vk record if it exists, create a KeyValue, and assign it to the current RegistryKey
                    foreach (var valueOffset in nk.ValueOffsets)
                    {
                        if (CellRecords.ContainsKey((long) valueOffset))
                        {
                            _logger.Debug(
                                "Found vk record at relative offset 0x{0:X} for nk record at absolute offset 0x{1:X}",
                                valueOffset, nk.AbsoluteOffset);

                            var val = CellRecords[(long) valueOffset] as VKCellRecord;
                            //we have a value for this key

                            if (val != null)
                            {
                                //if its an in use record AND referenced, warn
                                if (val.IsFree == false && val.IsReferenced)
                                {
                                    _logger.Warn(
                                        "When getting values for nk record at absolute offset 0x{0:X}, VK record at relative offset 0x{1:X} isn't free and is referenced by another nk record. Skipping!",
                                        nk.AbsoluteOffset, valueOffset);
                                }
                                else
                                {
                                    associatedVKRecordOffsets.Add(val.RelativeOffset);

                                    var kv = new KeyValue(val);

                                    regKey.Values.Add(kv);
                                    _logger.Debug(
                                        "Added vk record at relative offset 0x{0:X} for nk record at absolute offset 0x{1:X}",
                                        valueOffset, nk.AbsoluteOffset);
                                }
                            }
                        }
                        else
                        {
                            _logger.Debug(
                                "vk record at relative offset 0x{0:X} not found for nk record at absolute offset 0x{1:X}",
                                valueOffset, nk.AbsoluteOffset);
                        }
                    }

                    _logger.Debug(
                        "Associated {0:N0} value(s) out of {1:N0} possible values for nk record at absolute offset 0x{2:X}",
                        regKey.Values.Count, nk.ValueListCount, nk.AbsoluteOffset);


                    _deletedRegistryKeys.Add(nk.RelativeOffset, regKey);
                }
                catch (Exception ex) //ncrunch: no coverage
                {
//ncrunch: no coverage
                    _logger.Error( //ncrunch: no coverage
                        ex,
                        $"Error while processing deleted nk record at absolute offset 0x{unreferencedNkCell.Value.AbsoluteOffset:X}");
                } //ncrunch: no coverage
            }

            _logger.Debug("Building tree of key/subkeys for deleted keys");

            //DeletedRegistryKeys now contains all deleted nk records and their associated values.
            //Phase 2 is to build a tree of key/subkeys
            var matchFound = true;
            while (matchFound)
            {
                var keysToRemove = new List<long>();
                matchFound = false;

                foreach (var deletedRegistryKey in _deletedRegistryKeys)
                {
                    if (_deletedRegistryKeys.ContainsKey(deletedRegistryKey.Value.NKRecord.ParentCellIndex))
                    {
                        //deletedRegistryKey is a child of RegistryKey with relative offset ParentCellIndex

                        //add the key as as subkey of its parent
                        var parent = _deletedRegistryKeys[deletedRegistryKey.Value.NKRecord.ParentCellIndex];

                        _logger.Debug(
                            "Found subkey at absolute offset 0x{0:X} for parent key at absolute offset 0x{1:X}",
                            deletedRegistryKey.Value.NKRecord.AbsoluteOffset, parent.NKRecord.AbsoluteOffset);

                        deletedRegistryKey.Value.KeyPath = $@"{parent.KeyPath}\{deletedRegistryKey.Value.KeyName}";

                        parent.SubKeys.Add(deletedRegistryKey.Value);

                        //mark the subkey for deletion so we do not blow up the collection while iterating it
                        keysToRemove.Add(deletedRegistryKey.Value.NKRecord.RelativeOffset);

                        //reset this so the loop continutes
                        matchFound = true;
                    }
                }

                foreach (var l in keysToRemove)
                {
                    //take out the key from main collection since we copied it above to its parent's subkey list
                    _deletedRegistryKeys.Remove(l);
                }
            }

            _logger.Debug("Associating top level deleted keys to active Registry keys");

            //Phase 3 is looking at top level keys from Phase 2 and seeing if any of those can be assigned to non-deleted keys in the main tree
            foreach (var deletedRegistryKey in _deletedRegistryKeys)
            {
                if (CellRecords.ContainsKey(deletedRegistryKey.Value.NKRecord.ParentCellIndex))
                {
                    //an parent key has been located, so get it
                    var parentNk = CellRecords[deletedRegistryKey.Value.NKRecord.ParentCellIndex] as NKCellRecord;

                    _logger.Debug(
                        "Found possible parent key at absolute offset 0x{0:X} for deleted key at absolute offset 0x{1:X}",
                        deletedRegistryKey.Value.NKRecord.ParentCellIndex + 0x1000,
                        deletedRegistryKey.Value.NKRecord.AbsoluteOffset);

                    if (parentNk == null)
                    {
                        //the data at that index is not an nkrecord
                        continue;
                    }

                    if (parentNk.IsReferenced && parentNk.IsFree == false)
                    {
                        //parent exists in our primary tree, so get that key
                        var pk = GetKey(deletedRegistryKey.Value.NKRecord.ParentCellIndex);

                        _logger.Debug(
                            "Copying subkey at absolute offset 0x{0:X} for parent key at absolute offset 0x{1:X}",
                            deletedRegistryKey.Value.NKRecord.AbsoluteOffset, pk.NKRecord.AbsoluteOffset);

                        deletedRegistryKey.Value.KeyPath = $@"{pk.KeyPath}\{deletedRegistryKey.Value.KeyName}";

                        deletedRegistryKey.Value.KeyFlags |= RegistryKey.KeyFlagsEnum.HasActiveParent;

                        UpdateChildPaths(deletedRegistryKey.Value);

                        //add a copy of deletedRegistryKey under its original parent
                        pk.SubKeys.Add(deletedRegistryKey.Value);

                        RelativeOffsetKeyMap.Add(deletedRegistryKey.Value.NKRecord.RelativeOffset,
                            deletedRegistryKey.Value);

                        if (KeyPathKeyMap.ContainsKey(deletedRegistryKey.Value.KeyPath.ToLowerInvariant()) == false)
                        {
                            KeyPathKeyMap.Add(deletedRegistryKey.Value.KeyPath.ToLowerInvariant(),
                                deletedRegistryKey.Value);
                        }

                        _logger.Debug(
                            "Associated deleted key at absolute offset 0x{0:X} to active parent key at absolute offset 0x{1:X}",
                            deletedRegistryKey.Value.NKRecord.AbsoluteOffset, pk.NKRecord.AbsoluteOffset);
                    }
                }
            }

            DeletedRegistryKeys = _deletedRegistryKeys.Values.ToList();

            var unreferencedVk = CellRecords.Where(t => t.Value.IsReferenced == false && t.Value is VKCellRecord);

            foreach (var keyValuePair in unreferencedVk)
            {
                if (associatedVKRecordOffsets.Contains(keyValuePair.Key) == false)
                {
                    var vk = keyValuePair.Value as VKCellRecord;
                    var val = new KeyValue(vk);

                    UnassociatedRegistryValues.Add(val);
                }
            }
        }
        public void ProcessValues(RegistryKey key)
        {
            _values.Clear();
            Errors.Clear();

            var valuesList = new List<ValuesOut>();

            var currentKey = string.Empty;

            try
            {
                foreach (var registryKey in key.SubKeys)
                {
                    currentKey = registryKey.KeyName;

                    //get MRU key and read it in

                    var mruVal = registryKey.Values.SingleOrDefault(t => t.ValueName == "MRUListEx");

                    var mruListOrder = new ArrayList();

                    if (mruVal != null)
                    {
                        var index = 0;
                        var mruPos = 0;

                        while (index < mruVal.ValueDataRaw.Length)
                        {
                            mruPos = BitConverter.ToInt32(mruVal.ValueDataRaw, index);
                            index += 4;

                            if (mruPos != -1)
                            {
                                mruListOrder.Add(mruPos);
                            }
                        }
                    }

                    foreach (var keyValue in registryKey.Values)
                    {
                        if (keyValue.ValueName == "MRUListEx")
                        {
                            continue;
                        }

                        bags = new List<ShellBag>();

                        var shellItemsRaw = new List<byte[]>();

                        var mru = (int) mruListOrder[int.Parse(keyValue.ValueName)];
                        DateTimeOffset? openedOn = null;

                        if (mru == 0)
                        {
                            openedOn = registryKey.LastWriteTime;
                        }

                        try
                        {
                            var det = new StringBuilder();

                            var index = 0;
                            while (index < keyValue.ValueDataRaw.Length)
                            {
                                var size = BitConverter.ToInt16(keyValue.ValueDataRaw, index);

                                if (size == 0)
                                {
                                    break;
                                }

                                var shellRaw = new byte[size];
                                Buffer.BlockCopy(keyValue.ValueDataRaw, index, shellRaw, 0, size);

                                shellItemsRaw.Add(shellRaw);

                                index += size;
                            }

                            ShellBag bag = null;

                            foreach (var bytese in shellItemsRaw)
                            {
                                switch (bytese[2])
                                {
                                    case 0x00:
                                        bag = new ShellBag0X00(bytese);

                                        break;
                                    case 0x1f:
                                        bag = new ShellBag0X1F(bytese);

                                        break;
                                    case 0x2f:
                                        bag = new ShellBag0X2F(bytese);

                                        break;
                                    case 0x2e:
                                        bag = new ShellBag0X2E(bytese);

                                        break;
                                    case 0xb1:
                                    case 0x31:
                                        bag = new ShellBag0X31(bytese);

                                        break;
                                    case 0x32:
                                        bag = new ShellBag0X32(bytese);

                                        break;
                                    case 0x71:
                                        bag = new ShellBag0X71(bytese);

                                        break;
                                    case 0x74:
                                        bag = new ShellBag0X74(bytese);

                                        break;
                                    case 0x40:
                                        bag = new ShellBag0X40(bytese);

                                        break;
                                    case 0x61:
                                        bag = new ShellBag0X61(bytese);

                                        break;
                                    case 0xc3:
                                        bag = new ShellBag0Xc3(bytese);

                                        break;
                                    default:
                                        det.AppendLine(
                                            $"Key: {registryKey.KeyName}, Value name: {keyValue.ValueName}, Message: **** Unsupported ShellID: 0x{bytese[2]:x2}. Send this ID to [email protected] so support can be added!! ****");

                                        Errors.Add(
                                            $"Key: {registryKey.KeyName}, Value name: {keyValue.ValueName}, Message: **** Unsupported ShellID: 0x{bytese[2]:x2}. Send this ID to [email protected] so support can be added!! ****");
                                        break;
                                }

                                if (bag != null)
                                {
                                    det.AppendLine(bag.ToString());
                                    bags.Add(bag);
                                }
                            }

                            var v = new ValuesOut(registryKey.KeyName,
                                $"{GetAbsolutePathFromTargetIDs(bags)}", det.ToString(), keyValue.ValueName, mru,
                                openedOn);
                            valuesList.Add(v);
                        }
                        catch (Exception ex)
                        {
                            Errors.Add(
                                $"Key: {registryKey.KeyName}, Value name: {keyValue.ValueName}, message: {ex.Message}");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Errors.Add($"Error processing OpenSavePidlMRU subkey {currentKey}: {ex.Message}");
            }

            if (Errors.Count > 0)
            {
                AlertMessage = "Errors detected. See Errors information in lower right corner of plugin window";
            }

            var v1 = valuesList.OrderBy(t => t.MruPosition);

            foreach (var source in v1.ToList())
            {
                _values.Add(source);
            }
        }
Beispiel #26
0
        // 指定キー内のName/Valueを書き出す
        private static void WriteValueData(RegistryKey key, StreamWriter sw, string filepath)
        {
            foreach (var keyValue in key.Values)
            {
//                var slack = "";
//                if (keyValue.ValueSlack.Length > 0)
//                    slack = keyValue.ValueSlack;

                if(keyValue.ValueData.Length > 1024)
                    sw.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}", filepath, Helpers.StripRootKeyNameFromKeyPath(key.KeyPath), keyValue.ValueName, $"(Large Data: {keyValue.ValueDataRaw.Length} bytes", key.LastWriteTime.Value.LocalDateTime, key.LastWriteTime.Value.UtcDateTime);
                else
                    sw.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}", filepath, Helpers.StripRootKeyNameFromKeyPath(key.KeyPath), keyValue.ValueName, keyValue.ValueData, key.LastWriteTime.Value.LocalDateTime, key.LastWriteTime.Value.UtcDateTime);

            }
        }
        private List<RegistryKey> GetSubkeys(uint subkeyListsStableCellIndex, RegistryKey parent)
		{
			var keys = new List<RegistryKey>();

			_logger.Debug("Looking for list record at relative offset 0x{0:X}", subkeyListsStableCellIndex);

			var rawList = GetRawRecord(subkeyListsStableCellIndex);

			var l = GetListFromRawBytes(rawList, subkeyListsStableCellIndex);

            var sig = BitConverter.ToInt16(l.RawBytes, 4);

            switch (sig)
			{
				case LfSignature:
				case LhSignature:
					var lxRecord = l as LxListRecord;

					foreach (var offset in lxRecord.Offsets)
					{
						_logger.Debug("In lf or lh, looking for nk record at relative offset 0x{0:X}", offset);
						var rawCell = GetRawRecord(offset.Key);
						var nk = new NKCellRecord(rawCell.Length, offset.Key, this);
						
						_logger.Debug("In lf or lh, found nk record at relative offset 0x{0:X}. Name: {1}", offset,
							nk.Name);

						var tempKey = new RegistryKey(nk, parent);

						keys.Add(tempKey);
					}
					break;

				case RiSignature:
					var riRecord = l as RIListRecord;

					foreach (var offset in riRecord.Offsets)
					{
						_logger.Debug("In ri, looking for list record at relative offset 0x{0:X}", offset);
						rawList = GetRawRecord(offset);

						var tempList = GetListFromRawBytes(rawList, offset);

						//templist is now an li or lh list 

						if (tempList.Signature == "li")
						{
							var sk3 = tempList as LIListRecord;

							foreach (var offset1 in sk3.Offsets)
							{
								_logger.Debug("In ri/li, looking for nk record at relative offset 0x{0:X}", offset1);
								var rawCell = GetRawRecord(offset1);
								var nk = new NKCellRecord(rawCell.Length, offset1, this);
								
								var tempKey = new RegistryKey(nk, parent);

								keys.Add(tempKey);
							}
						}
						else
						{
							var lxRecord_ = tempList as LxListRecord;

							foreach (var offset3 in lxRecord_.Offsets)
							{
								_logger.Debug("In ri/li, looking for nk record at relative offset 0x{0:X}", offset3);
								var rawCell = GetRawRecord(offset3.Key);
								var nk = new NKCellRecord(rawCell.Length, offset3.Key, this);

								var tempKey = new RegistryKey(nk, parent);

								keys.Add(tempKey);
							}
						}
					}
					
					break;

                //this is a safety net, but li's are typically only seen in RI lists. as such, don't use it in metrics
             
                case LiSignature:
					var liRecord = l as LIListRecord;
					
					foreach (var offset in liRecord.Offsets)
					{
						_logger.Debug("In li, looking for nk record at relative offset 0x{0:X}", offset);
						var rawCell = GetRawRecord(offset);
						var nk = new NKCellRecord(rawCell.Length, offset, this);

						var tempKey = new RegistryKey(nk, parent);
						keys.Add(tempKey);
					}
					
					break;
				default:
					throw new Exception($"Unknown subkey list type {l.Signature}!");
            }

            return keys;
		}
        private IEnumerable<FolderInfo> ProcessKey(RegistryKey key)
        {
            var l = new List<FolderInfo>();

            try
            {
                var mruList = key.Values.Single(t => t.ValueName == "MRUListEx");

                var mruPositions = new Dictionary<uint, int>();

                var i = 0;

                var index = 0;

                var mruPos = BitConverter.ToUInt32(mruList.ValueDataRaw, index);
                index += 4;

                while (mruPos != 0xFFFFFFFF)
                {
                    mruPositions.Add(mruPos, i);
                    i++;
                    mruPos = BitConverter.ToUInt32(mruList.ValueDataRaw, index);
                    index += 4;
                }

                //mruPositions now contains a map of positions (the key) to the order it was opened (the value)

                foreach (var keyValue in key.Values)
                {
                    if (keyValue.ValueName == "MRUListEx")
                    {
                        continue;
                    }

                    var mru = mruPositions[uint.Parse(keyValue.ValueName)];

                    var chunks = Encoding.Unicode.GetString(keyValue.ValueDataRaw).Split('\0');

                    var exeName = chunks[0];

                    var folder = string.Empty;

                    if (chunks.Length > 1)
                    {
                        folder = chunks[1];
                    }

                    DateTimeOffset? openedOn = null;

                    if (mru == 0)
                    {
                        openedOn = key.LastWriteTime;
                    }

                    var ff = new FolderInfo(exeName, folder, mru, openedOn);

                    l.Add(ff);
                }
            }
            catch (Exception ex)
            {
                Errors.Add($"Error processing FirstFolder key: {ex.Message}");
            }

            if (Errors.Count > 0)
            {
                AlertMessage = "Errors detected. See Errors information in lower right corner of plugin window";
            }

            return l.OrderBy(t => t.MRUPosition);
        }
Beispiel #29
0
        public void ProcessValues(RegistryKey key)
        {
            _values.Clear();
            Errors.Clear();

            try
            {
                var networkDHTID = key.Values.SingleOrDefault(t => t.ValueName == "Network.DHTID");
                if (networkDHTID != null)
                {
                    var dh = networkDHTID.ValueData.Replace("-", "");

                    var v = new ValuesOut($"Ares Network DHTID", dh);

                    _values.Add(v);
                }

                var dlFolderVal = key.Values.SingleOrDefault(t => t.ValueName == "Download.Folder");
                if (dlFolderVal != null)
                {
                    var dlf = DecodeHexToAscii(dlFolderVal.ValueData);

                    var v = new ValuesOut($"Download folder", dlf);

                    _values.Add(v);
                }

                var customMshVal = key.Values.SingleOrDefault(t => t.ValueName == "Personal.CustomMessage");
                if (customMshVal != null)
                {
                    var customMsg = customMshVal.ValueData;

                    var v = new ValuesOut($"Custom message", customMsg);

                    _values.Add(v);
                }

                var nickVal = key.Values.SingleOrDefault(t => t.ValueName == "Personal.Nickname");
                if (nickVal != null)
                {
                    var customMsg = DecodeHexToAscii(nickVal.ValueData);

                    var v = new ValuesOut($"User nickname", customMsg);

                    _values.Add(v);
                }

                var awayMsgVal = key.Values.SingleOrDefault(t => t.ValueName == "PrivateMessage.AwayMessage");
                if (awayMsgVal != null)
                {
                    if (
                        awayMsgVal.ValueData.Equals(
                            "5468697320697320616E206175746F6D617469632061776179206D6573736167652067656E65726174656420627920417265732070726F6772616D2C20757365722069736E27742068657265206E6F772E") ==
                        false)
                    {
                        //user has changed default

                        var customMsg = DecodeHexToAscii(awayMsgVal.ValueData);

                        var v = new ValuesOut($"Away message", customMsg);

                        _values.Add(v);
                    }
                }

                var lastConnectedVal = key.Values.SingleOrDefault(t => t.ValueName == "Stats.LstConnect");
                if (lastConnectedVal != null)
                {
                    var lastConnect = DateTimeOffset.FromUnixTimeSeconds(int.Parse(lastConnectedVal.ValueData));

                    var v = new ValuesOut($"Last connection time", lastConnect.ToUniversalTime().ToString());

                    _values.Add(v);
                }

                var portVal = key.Values.SingleOrDefault(t => t.ValueName == "Transfer.ServerPort");

                if (portVal != null)
                {
                    var portNum = int.Parse(portVal.ValueData);

                    if (portNum > 0)
                    {
                        var v = new ValuesOut($"Port number", portNum.ToString());

                        _values.Add(v);
                    }
                }

                var guidVal = key.Values.SingleOrDefault(t => t.ValueName == "Personal.GUID");

                if (guidVal != null)
                {
                    var v = new ValuesOut($"Personal GUID", guidVal.ValueData);

                    _values.Add(v);
                }

                var searchKey = key.SubKeys.SingleOrDefault(t => t.KeyName == "Search.History");

                if (searchKey != null)
                {
                    foreach (var registryKey in searchKey.SubKeys)
                    {
                        if (registryKey.Values.Count == 0)
                        {
                            continue;
                        }

                        var terms = new List<string>();

                        foreach (var keyValue in registryKey.Values)
                        {
                            try
                            {
                                var st = DecodeHexToAscii(keyValue.ValueName);

                                terms.Add(st);
                            }
                            catch (Exception ex)
                            {
                                Errors.Add(
                                    $"Key: {registryKey.KeyName}, Value name: {keyValue.ValueName}, message: {ex.Message}");
                            }
                        }

                        var searchType = registryKey.KeyName.Substring(0, registryKey.KeyName.Length - 4);
                        if (searchType == "gen")
                        {
                            searchType = "all";
                        }

                        var v = new ValuesOut($"Search history for '{searchType}'", string.Join(", ", terms));

                        _values.Add(v);
                    }
                }
            }
            catch (Exception ex)
            {
                Errors.Add($"Error processing Ares search history: {ex.Message}");
            }

            if (Errors.Count > 0)
            {
                AlertMessage = "Errors detected. See Errors information in lower right corner of plugin window";
            }
        }
Beispiel #30
0
        private static void DumpKey(RegistryKey key, bool recursive)
        {
            if (recursive)
            {
                _logger.Info(key);
            }
            else
            {
                _logger.Info($"Key: {Helpers.StripRootKeyNameFromKeyPath(key.KeyPath)}");
                _logger.Info($"Last write time: {key.LastWriteTime}");
                _logger.Info($"Number of Values: {key.Values.Count:N0}");
                _logger.Info($"Number of Subkeys: {key.SubKeys.Count:N0}");
                _logger.Info("");

                var i = 0;

                foreach (var sk in key.SubKeys)
                {
                    _logger.Info($"------------ Subkey #{i:N0} ------------");
                    _logger.Info($"Name: {sk.KeyName} (Last write: {sk.LastWriteTime})");
                    i += 1;
                }

                i = 0;
                _logger.Info("");

                foreach (var keyValue in key.Values)
                {
                    _logger.Info($"------------ Value #{i:N0} ------------");
                    _logger.Info($"Name: {keyValue.ValueName} ({keyValue.ValueType})");

                    var slack = "";

                    if (keyValue.ValueSlack.Length > 0)
                    {
                        slack = $"(Slack: {keyValue.ValueSlack})";
                    }
                    _logger.Info($"Data: {keyValue.ValueData} {slack}");

                    i += 1;
                }
            }
        }
Beispiel #31
0
 // 指定キーのサブキーに対してName/Valueを書き出す
 private static void WriteSubKeyData(RegistryKey key, StreamWriter sw, string filepath)
 {
     if (key.SubKeys.Count > 0)
     {
         foreach (var sk in key.SubKeys)
         {
             if (sk.Values.Count > 0)
                 WriteValueData(sk, sw, filepath);
             else // サブキー配下にエントリが1つもない場合はキーとタイムスタンプのみ書き出す
                 sw.WriteLine("{0}\t{1}\t\t\t{2}\t{3}", filepath, Helpers.StripRootKeyNameFromKeyPath(key.KeyPath), sk.LastWriteTime.Value.LocalDateTime, sk.LastWriteTime.Value.UtcDateTime);
         }
     }
 }
Beispiel #32
0
        /// <summary>
        ///     Exports contents of Registry to text format.
        /// </summary>
        /// <remarks>Be sure to set FlushRecordListsAfterParse to FALSE if you want deleted records included</remarks>
        /// <param name="outfile">The outfile.</param>
        /// <param name="deletedOnly">if set to <c>true</c> [deleted only].</param>
        public void ExportDataToCommonFormat(string outfile, bool deletedOnly)
        {
            var KeyCount = 0; //root key
            var ValueCount = 0;
            var KeyCountDeleted = 0;
            var ValueCountDeleted = 0;

            var header = new StringBuilder();
            header.AppendLine("## Registry common export format");
            header.AppendLine("## Key format");
            header.AppendLine(
                "## key|Is Free (A for in use, U for unused)|Absolute offset in decimal|KeyPath|LastWriteTime in UTC");
            header.AppendLine("## Value format");
            header.AppendLine(
                "## value|Is Free (A for in use, U for unused)|Absolute offset in decimal|KeyPath|Value name|Data type (as decimal integer)|Value data as bytes separated by a singe space");
            header.AppendLine("##");
            header.AppendLine(
                "## Comparison of deleted keys/values is done to compare recovery of vk and nk records, not the algorithm used to associate deleted keys to other keys and their values.");
            header.AppendLine(
                "## When including deleted keys, only the recovered key name should be included, not the full path to the deleted key.");
            header.AppendLine("## When including deleted values, do not include the parent key information.");
            header.AppendLine("##");
            header.AppendLine("## The following totals should also be included");
            header.AppendLine("##");
            header.AppendLine("## total_keys|total in use key count");
            header.AppendLine("## total_values|total in use value count");
            header.AppendLine("## total_deleted_keys|total recovered free key count");
            header.AppendLine("## total_deleted_values|total recovered free value count");
            header.AppendLine("##");
            header.AppendLine(
                "## Before comparison with other common export implementations, the files should be sorted");
            header.AppendLine("##");

            using (var sw = new StreamWriter(outfile, false))
            {
                sw.AutoFlush = true;

                sw.Write(header.ToString());

                if (deletedOnly == false)
                {
                    //dump active stuff
                    if (Root.LastWriteTime != null)
                    {
                        KeyCount = 1;
                        sw.WriteLine("key|{0}|{1}|{2}|{3}", Root.NKRecord.IsFree ? "U" : "A",
                            Root.NKRecord.AbsoluteOffset,
                            Root.KeyPath, Root.LastWriteTime.Value.UtcDateTime.ToString("o"));
                    }

                    foreach (var val in Root.Values)
                    {
                        ValueCount += 1;
                        sw.WriteLine(@"value|{0}|{1}|{2}|{3}|{4}|{5}", val.VKRecord.IsFree ? "U" : "A",
                            val.VKRecord.AbsoluteOffset, Root.KeyPath, val.ValueName, (int) val.VKRecord.DataType,
                            BitConverter.ToString(val.VKRecord.ValueDataRaw).Replace("-", " "));
                    }

                    DumpKeyCommonFormat(Root, sw, ref KeyCount, ref ValueCount);
                }

                var theRest = CellRecords.Where(a => a.Value.IsReferenced == false);
                //may not need to if we do not care about orphaned values

                foreach (var keyValuePair in theRest)
                {
                    try
                    {
                        if (keyValuePair.Value.Signature == "vk")
                        {
                            ValueCountDeleted += 1;
                            var val = keyValuePair.Value as VKCellRecord;

                            sw.WriteLine(@"value|{0}|{1}|{2}|{3}|{4}|{5}", val.IsFree ? "U" : "A", val.AbsoluteOffset,
                                "",
                                val.ValueName, (int) val.DataType,
                                BitConverter.ToString(val.ValueDataRaw).Replace("-", " "));
                        }

                        if (keyValuePair.Value.Signature == "nk")
                        {
                            //this should never be once we re-enable deleted key rebuilding

                            KeyCountDeleted += 1;
                            var nk = keyValuePair.Value as NKCellRecord;
                            var key = new RegistryKey(nk, null);

                            sw.WriteLine("key|{0}|{1}|{2}|{3}", key.NKRecord.IsFree ? "U" : "A",
                                key.NKRecord.AbsoluteOffset, key.KeyName,
                                key.LastWriteTime.Value.UtcDateTime.ToString("o"));

                            DumpKeyCommonFormat(key, sw, ref KeyCountDeleted, ref ValueCountDeleted);
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.Warn("There was an error exporting free record at offset 0x{0:X}. Error: {1}",
                            keyValuePair.Value.AbsoluteOffset, ex.Message);
                    }
                }

                sw.WriteLine("total_keys|{0}", KeyCount);
                sw.WriteLine("total_values|{0}", ValueCount);
                sw.WriteLine("total_deleted_keys|{0}", KeyCountDeleted);
                sw.WriteLine("total_deleted_values|{0}", ValueCountDeleted);
            }
        }
Beispiel #33
0
 // 指定キーのサブキーに対して再帰的にName/Valueを書き出す
 private static void WriteSpecificKeyInfo(RegistryKey key, StreamWriter sw, string filepath)
 {
     // 指定キー配下にエントリがある場合はそのエントリ分の処理をする
     if (key.Values.Count > 0)
         WriteValueData(key, sw, filepath);
     // 指定キー配下にサブキーがある場合は再帰的に処理をする
     if (key.SubKeys.Count > 0)
     {
         foreach (var sk in key.SubKeys)
             WriteSubKeyData(sk, sw, filepath);
     }
 }
Beispiel #34
0
 public SearchHit(RegistryKey key, KeyValue value, string hitstring)
 {
     Key = key;
        Value = value;
        HitString = hitstring;
 }