private Task <String> findCurrentComputerName() { return(Task.Run(() => { showMsg("Find Computer Name: Getting list of logical drives...", loadImg); string[] drives = Environment.GetLogicalDrives(); showMsg("Find Computer Name: Searching in offline registries...", loadImg); foreach (string drive in drives) { string rPath = drive + @"Windows\System32\config\SYSTEM"; if (File.Exists(rPath)) { try { Registry.RegistryHiveOnDemand registryHive = new Registry.RegistryHiveOnDemand(rPath); Registry.Abstractions.RegistryKey key = registryHive.GetKey(@"ControlSet001\Control\ComputerName\ComputerName"); foreach (Registry.Abstractions.KeyValue value in key.Values) { if (value.ValueName == "ComputerName") { return value.ValueData; } } } catch (IOException) { } } } showMsg("Find Computer Name: Searching in online registry...", loadImg); Microsoft.Win32.RegistryKey computerName = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SYSTEM\ControlSet001\Control\ComputerName\ComputerName", false); hideMsg(); return (string)computerName.GetValue("ComputerName"); })); }
/// <summary> /// allows iteration over offline registry keys in a foreach loop /// </summary> private IEnumerable <RegistryKeyWrapper> GetOfflineRegistryKeyIterator(string registryFilePath) { int count = 0; OfflineRegistryHive hive; try { hive = new OfflineRegistryHive(registryFilePath); } catch (Exception) { yield break; } foreach (string location in Config.ShellbagRootLocations) { string userOfHive = FindOfflineUsername(hive); foreach (RegistryKeyWrapper keyWrapper in IterateOfflineRegistry(hive.GetKey(location), hive, location, null, "")) { if (userOfHive != string.Empty) { keyWrapper.RegistryUser = userOfHive; } count++; yield return(keyWrapper); } } }
private void AdaptOfflineKey(OfflineRegistryKey registryKey, OfflineRegistryHive hive) { //obtain SID and Username(?) //HKEY USERS registry is UserSID\.... string UserSID = registryKey.KeyPath.Split('\\')[0]; // "_classes" is actually just a user's usrclass.dat, not a seperate user. UserSID = UserSID.ToUpper().Replace("_CLASSES", ""); RegistrySID = UserSID; //if we dont know the username, default to the SID. RegistryUser = RegistrySID; //obtain NodeSlot (Shellbag Path in registry) SlotModifiedDate = DateTime.MinValue; LastRegistryWriteDate = DateTime.MinValue; NodeSlot = null; string nodeSlotPath = null; foreach (OfflineKeyValue kv in registryKey.Values) { if (kv.ValueName.Equals("NodeSlot")) { NodeSlot = int.Parse(kv.ValueData); nodeSlotPath = string.Format("{0}{1}\\{2}", registryKey.KeyPath.Substring(0, registryKey.KeyPath.IndexOf("BagMRU", StringComparison.Ordinal)), "Bags", NodeSlot); break; } } if (nodeSlotPath != null) { SlotModifiedDate = hive.GetKey(nodeSlotPath).LastWriteTime.Value.LocalDateTime; } //obtain the date the registry last wrote this key LastRegistryWriteDate = registryKey.LastWriteTime.Value.UtcDateTime; }
/// <summary> /// Recursively iterates over the a registry key and its subkeys for enumerating all values of the keys and subkeys /// </summary> /// <param name="rk">the root registry key to start iterating over</param> /// <param name="hive">the offline registry hive</param> /// <param name="subKey">the path of the first subkey under the root key</param> /// <param name="indent"></param> /// <param name="path_prefix">the header to the current root key, needed for identification of the registry store</param> /// <returns></returns> private static IEnumerable <RegistryKeyWrapper> IterateOfflineRegistry(OfflineRegistryKey rk, OfflineRegistryHive hive, string subKey, RegistryKeyWrapper parent, string path_prefix) { if (rk == null) { yield break; } foreach (OfflineRegistryKey valueName in rk.SubKeys) { if (valueName.KeyName.ToUpper() == "ASSOCIATIONS") { continue; } string sk = GetSubkeyString(subKey, valueName.KeyName); OfflineRegistryKey rkNext; try { rkNext = hive.GetKey(GetSubkeyString(rk.KeyPath, valueName.KeyName)); } catch (SecurityException) { continue; } string path = path_prefix; RegistryKeyWrapper rkNextWrapper = null; bool isNumeric = int.TryParse(valueName.KeyName, out _); if (isNumeric) { OfflineKeyValue rkValue = null; try { rkValue = rk.Values.First(val => val.ValueName == valueName.KeyName); } catch (InvalidOperationException) { } if (rkValue == null) { continue; } byte[] byteVal = rkValue.ValueDataRaw; yield return(rkNextWrapper = new RegistryKeyWrapper(rkNext, byteVal, hive, parent)); } foreach (var wrapper in IterateOfflineRegistry(rkNext, hive, sk, rkNextWrapper, path)) { yield return(wrapper); } } }
private string FindOfflineUsername(OfflineRegistryHive hive) { string retval = string.Empty; try { //todo refactor Parser.GetUsernameLocations() into key-value pairs for lookup, we have to hardcode key-values otherwise. //todo we know of the Desktop value inside the "Shell Folders" location, so naively try this until a better way is found Dictionary <string, int> likelyUsernames = new Dictionary <string, int>(); foreach (string usernameLocation in Config.UsernameLocations) { if (hive.GetKey(usernameLocation) == null) { continue; } Func <string, string> extractUsername = (string path) => { if (!Path.IsPathFullyQualified(path)) { return(null); } //break string up into it's path string[] pathParts = path.Split('\\'); if (pathParts.Length > 2 && pathParts[1] == "Users") { return(pathParts[2]); //usually in the form of C:\Users\username } return(null); }; //based on the values in '...\Explorer\Shell Folders' the [2] value in the string may not always be the username, but it does appear the most. foreach (OfflineKeyValue value in hive.GetKey(usernameLocation).Values) { var username = extractUsername(value.ValueData); if (username != null) { if (!likelyUsernames.ContainsKey(username)) { likelyUsernames[username] = 1; } else { likelyUsernames[username]++; } } username = extractUsername(value.ValueName); if (username != null) { if (!likelyUsernames.ContainsKey(username)) { likelyUsernames[username] = 1; } else { likelyUsernames[username]++; } } } } //most occurred value is probably the username. if (likelyUsernames.Count >= 1) { retval = likelyUsernames.OrderByDescending(pair => pair.Value).First().Key; } } catch (Exception) { } return(retval); }
/// <summary> /// Adapts a ShellBag RegistryKey to a common standard for retrieval of important information independent of key retrieval methodologies /// </summary> /// <param name="registryKey">A Registry Key associated with a Shellbag, retrieved from a offline registry reader API</param> /// <param name="keyValue">The Value of a Registry key containing Shellbag information. Found in the Parent of the registryKey being inspected</param> /// <param name="parent">The parent of the currently inspected registryKey. Can be null.</param> public RegistryKeyWrapper(OfflineRegistryKey registryKey, byte[] keyValue, OfflineRegistryHive hive, RegistryKeyWrapper parent = null) : this(keyValue) { Parent = parent; RegistryPath = registryKey.KeyPath; AdaptOfflineKey(registryKey, hive); }