public void OneOff() { var log1 = $"C:\\Users\\eric\\Desktop\\RegistryExplorer - Failed to Load Hives\\Stack\\NTUSER.DAT.LOG1"; var log2 = $"C:\\Users\\eric\\Desktop\\RegistryExplorer - Failed to Load Hives\\Stack\\NTUSER.DAT.LOG2"; var hive = $"C:\\Users\\eric\\Desktop\\RegistryExplorer - Failed to Load Hives\\Stack\\NTUSER.DAT"; var logs = new List <string>(); logs.Add(log1); logs.Add(log2); var hive1 = new RegistryHive(hive); if (hive1.Header.PrimarySequenceNumber != hive1.Header.SecondarySequenceNumber) { Debug.WriteLine(""); Debug.WriteLine( $"File: {hive} Valid checksum: {hive1.Header.ValidateCheckSum()} Primary: 0x{hive1.Header.PrimarySequenceNumber:X} Secondary: 0x{hive1.Header.SecondarySequenceNumber:X}"); var newb = hive1.ProcessTransactionLogs(logs, true); var newName = hive + "_NONDIRTY"; File.WriteAllBytes(newName, newb); } }
public void HiveTests() { var dir = @"C:\Temp\hives"; var files = Directory.GetFiles(dir); foreach (var file in files) { if (file.Contains("LOG") || file.EndsWith("_NONDIRTY")) { continue; } var log1 = $"{file}.LOG1"; var log2 = $"{file}.LOG2"; var hive1 = new RegistryHive(file); var logs = new List <string>(); logs.Add(log1); logs.Add(log2); if (hive1.Header.PrimarySequenceNumber != hive1.Header.SecondarySequenceNumber) { Debug.WriteLine(""); Debug.WriteLine( $"File: {file} Valid checksum: {hive1.Header.ValidateCheckSum()} Primary: 0x{hive1.Header.PrimarySequenceNumber:X} Secondary: 0x{hive1.Header.SecondarySequenceNumber:X}"); var newb = hive1.ProcessTransactionLogs(logs); var newName = file + "_NONDIRTY"; File.WriteAllBytes(newName, newb); } } }
public void MRU2() { var r = new OfficeMRU(); var reg = new RegistryHive(@"C:\Temp\tout\G\Users\fredr\NTUSER.DAT"); var l = new List <string>(); l.Add(@"C:\Temp\tout\G\Users\fredr\ntuser.dat.LOG1"); l.Add(@"C:\Temp\tout\G\Users\fredr\ntuser.dat.LOG2"); reg.ProcessTransactionLogs(l, true); reg.ParseHive(); var key = reg.GetKey(@"SOFTWARE\Microsoft\Office\16.0\Word\User MRU\ADAL_71509F4C9F29E24E25306165B32FE79B68FD54A88446B7C792A3A9D5AB6BB5AE\File MRU"); Check.That(key).IsNotNull(); Check.That(r.Values.Count).IsEqualTo(0); r.ProcessValues(key); Debug.WriteLine(r.Values.Count); }
public static bool IsNewFormat(string file, bool noLog) { RegistryKey fileKey = null; try { var reg = new RegistryHive(file) { RecoverDeleted = true }; LogManager.DisableLogging(); if (reg.Header.PrimarySequenceNumber != reg.Header.SecondarySequenceNumber) { var hiveBase = Path.GetFileName(file); var dirname = Path.GetDirectoryName(file); if (string.IsNullOrEmpty(dirname)) { dirname = "."; } var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?"); if (logFiles.Length == 0) { var log = LogManager.GetCurrentClassLogger(); if (noLog == false) { log.Warn("Registry hive is dirty and no transaction logs were found in the same directory! LOGs should have same base name as the hive. Aborting!!"); throw new Exception("Sequence numbers do not match and transaction logs were not found in the same directory as the hive. Aborting"); } log.Warn("Registry hive is dirty and no transaction logs were found in the same directory. Data may be missing! Continuing anyways..."); } else { reg.ProcessTransactionLogs(logFiles.ToList(), true); } } reg.ParseHive(); fileKey = reg.GetKey(@"Root\InventoryApplicationFile"); LogManager.EnableLogging(); } catch (Exception) { LogManager.EnableLogging(); } return(fileKey != null); }
static void Run(Options opts) { var logger = Logger.GetInstance(); logger.SetLevel(opts.Verbose ? Logger.Level.Verbose : Logger.Level.Info); logger.Info(String.Format("Number of transactions logs: {0}", opts.TransactionFilenames.Count())); foreach (var trans in opts.TransactionFilenames) { logger.Verbose(String.Format("Transaction file: {0}", trans)); } /* Online: commitRegistry */ // TODO /* Offline */ RegistryHive registryHive = null; try { registryHive = new RegistryHive(opts.DirtyHiveFilename); } catch (Exception exception) { logger.Error(String.Format("Impossible to parse hive: {0}", exception.Message)); Environment.Exit(1); } byte[] mergedHive = null; try { mergedHive = registryHive.ProcessTransactionLogs(opts.TransactionFilenames.ToList()); } catch (Exception exception) { logger.Error(String.Format("An exception occured while processing transaction logs: {0}", exception.Message)); Environment.Exit(1); } logger.Info(String.Format("Merged {0} bytes", mergedHive.Length)); logger.Info(String.Format("Writing to {0}", opts.OutputFilename)); using (var fs = new FileStream(opts.OutputFilename, FileMode.Create)) { using (var bw = new BinaryWriter(fs)) { bw.Write(mergedHive); } } logger.Info("Done"); }
public void HiveTestAmcache() { var config = new LoggingConfiguration(); var loglevel = LogLevel.Trace; const string layout = @"${message}"; var consoleTarget = new ColoredConsoleTarget(); config.AddTarget("console", consoleTarget); consoleTarget.Layout = layout; var rule1 = new LoggingRule("Console", loglevel, consoleTarget); config.LoggingRules.Add(rule1); LogManager.Configuration = config; var hive = @"D:\SynologyDrive\Registry\amcache\aa\Amcache.hve"; var hive1 = new RegistryHive(hive); var log1 = $"{hive}.LOG1"; var log2 = $"{hive}.LOG2"; var logs = new List <string>(); logs.Add(log1); logs.Add(log2); var newb = hive1.ProcessTransactionLogs(logs); var newName = hive + "_NONDIRTY"; File.WriteAllBytes(newName, newb); }
public void OneOff2() { var config = new LoggingConfiguration(); var loglevel = LogLevel.Info; var layout = @"${message}"; var consoleTarget = new ColoredConsoleTarget(); config.AddTarget("console", consoleTarget); consoleTarget.Layout = layout; var rule1 = new LoggingRule("*", loglevel, consoleTarget); config.LoggingRules.Add(rule1); LogManager.Configuration = config; var r = new RegistryHive(@"D:\OneDrive\Desktop\a\SOFTWARE"); r.RecoverDeleted = true; var l1 = new List <string>(); l1.Add(@"D:\OneDrive\Desktop\a\SOFTWARE.log1"); l1.Add(@"D:\OneDrive\Desktop\a\SOFTWARE.log2"); r.ProcessTransactionLogs(l1, true); r.ParseHive(); var l = LogManager.GetCurrentClassLogger(); // var foo = r.FindInValueDataSlack("info.exe", false, false); // // foreach (var searchHit in foo) // { // l.Info(searchHit); // } }
public static bool IsNewFormat(string file, bool noLog) { RegistryKey fileKey = null; RegistryHive reg; var dirname = Path.GetDirectoryName(file); var hiveBase = Path.GetFileName(file); List <RawCopy.RawCopyReturn> rawFiles = null; try { try { reg = new RegistryHive(file) { RecoverDeleted = true }; } catch (IOException) { //file is in use if (RawCopy.Helper.IsAdministrator() == false) { throw new UnauthorizedAccessException("Administrator privileges not found!"); } var files = new List <string>(); files.Add(file); var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?"); foreach (var logFile in logFiles) { files.Add(logFile); } rawFiles = RawCopy.Helper.GetFiles(files); var b = new byte[rawFiles.First().FileStream.Length]; rawFiles.First().FileStream.Read(b, 0, (int)rawFiles.First().FileStream.Length); reg = new RegistryHive(b, rawFiles.First().InputFilename); } LogManager.DisableLogging(); if (reg.Header.PrimarySequenceNumber != reg.Header.SecondarySequenceNumber) { if (string.IsNullOrEmpty(dirname)) { dirname = "."; } var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?"); if (logFiles.Length == 0 || noLog) { var log = LogManager.GetCurrentClassLogger(); if (noLog == false) { log.Warn("Registry hive is dirty and no transaction logs were found in the same directory! LOGs should have same base name as the hive. Aborting!!"); throw new Exception("Sequence numbers do not match and transaction logs were not found in the same directory as the hive. Aborting"); } log.Warn("Registry hive is dirty and no transaction logs were found in the same directory. Data may be missing! Continuing anyways..."); } else { if (rawFiles != null) { var lt = new List <TransactionLogFileInfo>(); foreach (var rawCopyReturn in rawFiles.Skip(1).ToList()) { var b = new byte[rawCopyReturn.FileStream.Length]; rawCopyReturn.FileStream.Read(b, 0, (int)rawCopyReturn.FileStream.Length); var tt = new TransactionLogFileInfo(rawCopyReturn.InputFilename, b); lt.Add(tt); } reg.ProcessTransactionLogs(lt, true); } else { reg.ProcessTransactionLogs(logFiles.ToList(), true); } } } reg.ParseHive(); fileKey = reg.GetKey(@"Root\InventoryApplicationFile"); LogManager.EnableLogging(); } catch (Exception) { LogManager.EnableLogging(); } return(fileKey != null); }
public AmcacheNew(string hive, bool recoverDeleted, bool noLogs) { _logger = LogManager.GetCurrentClassLogger(); RegistryHive reg; var dirname = Path.GetDirectoryName(hive); var hiveBase = Path.GetFileName(hive); List <RawCopyReturn> rawFiles = null; try { reg = new RegistryHive(hive) { RecoverDeleted = true }; } catch (IOException) { //file is in use if (RawCopy.Helper.IsAdministrator() == false) { throw new UnauthorizedAccessException("Administrator privileges not found!"); } _logger.Warn($"'{hive}' is in use. Rerouting...\r\n"); var files = new List <string>(); files.Add(hive); var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?"); foreach (var logFile in logFiles) { files.Add(logFile); } rawFiles = RawCopy.Helper.GetFiles(files); var b = new byte[rawFiles.First().FileStream.Length]; rawFiles.First().FileStream.Read(b, 0, (int)rawFiles.First().FileStream.Length); reg = new RegistryHive(b, rawFiles.First().InputFilename); } if (reg.Header.PrimarySequenceNumber != reg.Header.SecondarySequenceNumber) { if (string.IsNullOrEmpty(dirname)) { dirname = "."; } var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?"); var log = LogManager.GetCurrentClassLogger(); if (logFiles.Length == 0) { if (noLogs == false) { log.Warn( "Registry hive is dirty and no transaction logs were found in the same directory! LOGs should have same base name as the hive. Aborting!!"); throw new Exception( "Sequence numbers do not match and transaction logs were not found in the same directory as the hive. Aborting"); } log.Warn( "Registry hive is dirty and no transaction logs were found in the same directory. Data may be missing! Continuing anyways..."); } else { if (noLogs == false) { if (rawFiles != null) { var lt = new List <TransactionLogFileInfo>(); foreach (var rawCopyReturn in rawFiles.Skip(1).ToList()) { var b = new byte[rawCopyReturn.FileStream.Length]; rawCopyReturn.FileStream.Read(b, 0, (int)rawCopyReturn.FileStream.Length); var tt = new TransactionLogFileInfo(rawCopyReturn.InputFilename, b); lt.Add(tt); } reg.ProcessTransactionLogs(lt, true); } else { reg.ProcessTransactionLogs(logFiles.ToList(), true); } } else { log.Warn( "Registry hive is dirty and transaction logs were found in the same directory, but --nl was provided. Data may be missing! Continuing anyways..."); } } } reg.ParseHive(); var fileKey = reg.GetKey(@"Root\InventoryApplicationFile"); var programsKey = reg.GetKey(@"Root\InventoryApplication"); UnassociatedFileEntries = new List <FileEntryNew>(); ProgramsEntries = new List <ProgramsEntryNew>(); DeviceContainers = new List <DeviceContainer>(); DevicePnps = new List <DevicePnp>(); DriveBinaries = new List <DriverBinary>(); DriverPackages = new List <DriverPackage>(); ShortCuts = new List <Shortcut>(); _logger.Debug("Getting Programs data"); if (programsKey != null) { foreach (var registryKey in programsKey.SubKeys) { var bundleManifestPath = string.Empty; var hiddenArp = false; var inboxModernApp = false; DateTimeOffset?installDate = null; var language = 0; var manifestPath = string.Empty; var msiPackageCode = string.Empty; var msiProductCode = string.Empty; var name = string.Empty; var osVersionAtInstallTime = string.Empty; var packageFullName = string.Empty; var programId = string.Empty; var programInstanceId = string.Empty; var publisher = string.Empty; var registryKeyPath = string.Empty; var rootDirPath = string.Empty; var source = string.Empty; var storeAppType = string.Empty; var type = string.Empty; var uninstallString = string.Empty; var version = string.Empty; var installDateArpLastModified = string.Empty; DateTimeOffset?installDateMsi = null; var installDateFromLinkFile = string.Empty; var manufacturer = string.Empty; var driverVerVersion = string.Empty; try { foreach (var registryKeyValue in registryKey.Values) { switch (registryKeyValue.ValueName) { case "BundleManifestPath": bundleManifestPath = registryKeyValue.ValueData; break; case "HiddenArp": hiddenArp = registryKeyValue.ValueData == "1"; break; case "InboxModernApp": inboxModernApp = registryKeyValue.ValueData == "1"; break; case "InstallDate": if (registryKeyValue.ValueData.Length > 0) { // _logger.Warn($"registryKeyValue.ValueData for InstallDate as InvariantCulture: {registryKeyValue.ValueData.ToString(CultureInfo.InvariantCulture)}"); var d = new DateTimeOffset( DateTime.Parse(registryKeyValue.ValueData, DateTimeFormatInfo.InvariantInfo) .Ticks, TimeSpan.Zero); installDate = d; } break; case "Language": if (registryKeyValue.ValueData.Length == 0) { language = 0; } else { language = int.Parse(registryKeyValue.ValueData); } break; case "ManifestPath": manifestPath = registryKeyValue.ValueData; break; case "MsiPackageCode": msiPackageCode = registryKeyValue.ValueData; break; case "MsiProductCode": msiProductCode = registryKeyValue.ValueData; break; case "Name": name = registryKeyValue.ValueData; break; case "OSVersionAtInstallTime": osVersionAtInstallTime = registryKeyValue.ValueData; break; case "PackageFullName": packageFullName = registryKeyValue.ValueData; break; case "ProgramId": programId = registryKeyValue.ValueData; break; case "ProgramInstanceId": programInstanceId = registryKeyValue.ValueData; break; case "Publisher": publisher = registryKeyValue.ValueData; break; case "RegistryKeyPath": registryKeyPath = registryKeyValue.ValueData; break; case "RootDirPath": rootDirPath = registryKeyValue.ValueData; break; case "Source": source = registryKeyValue.ValueData; break; case "StoreAppType": storeAppType = registryKeyValue.ValueData; break; case "Type": type = registryKeyValue.ValueData; break; case "UninstallString": uninstallString = registryKeyValue.ValueData; break; case "Version": version = registryKeyValue.ValueData; break; case "InstallDateArpLastModified": if (registryKeyValue.ValueData.Length > 0) { installDateArpLastModified = registryKeyValue.ValueData; } break; case "InstallDateMsi": if (registryKeyValue.ValueData.Length > 0) { // _logger.Warn($"registryKeyValue.ValueData for InstallDate as InvariantCulture: {registryKeyValue.ValueData.ToString(CultureInfo.InvariantCulture)}"); var d = new DateTimeOffset( DateTime.Parse(registryKeyValue.ValueData, DateTimeFormatInfo.InvariantInfo) .Ticks, TimeSpan.Zero); installDateMsi = d; } break; case "InstallDateFromLinkFile": if (registryKeyValue.ValueData.Length > 0) { installDateFromLinkFile = registryKeyValue.ValueData; } break; case "DriverVerVersion": case "BusReportedDescription": case "HWID": case "COMPID": case "STACKID": case "UpperClassFilters": case "UpperFilters": case "LowerFilters": case "BinFileVersion": case "(default)": break; case "Manufacturer": if (registryKeyValue.ValueData.Length > 0) { manufacturer = registryKeyValue.ValueData; } break; default: _logger.Warn( $"Unknown value name in InventoryApplication at path {registryKey.KeyPath}: {registryKeyValue.ValueName}"); break; } } var pe = new ProgramsEntryNew(bundleManifestPath, hiddenArp, inboxModernApp, installDate, language, manifestPath, msiPackageCode, msiProductCode, name, osVersionAtInstallTime, packageFullName, programId, programInstanceId, publisher, registryKeyPath, rootDirPath, source, storeAppType, type, uninstallString, version, registryKey.LastWriteTime.Value, installDateArpLastModified, installDateMsi, installDateFromLinkFile, manufacturer); ProgramsEntries.Add(pe); } catch (Exception ex) { if (registryKey.NkRecord.IsFree == false) { _logger.Error($"Error parsing ProgramsEntry at {registryKey.KeyPath}. Error: {ex.Message}"); _logger.Error( $"Please send the following text to [email protected]. \r\n\r\nKey data: {registryKey}"); } } } } else { _logger.Warn("Hive does not contain a Root\\InventoryApplication key."); } _logger.Debug("Getting Files data"); if (fileKey != null) { foreach (var subKey in fileKey.SubKeys) { var binaryType = string.Empty; var binFileVersion = string.Empty; var binProductVersion = string.Empty; var fileId = string.Empty; var isOsComponent = false; var isPeFile = false; var language = 0; DateTimeOffset?linkDate = null; var longPathHash = string.Empty; var lowerCaseLongPath = string.Empty; var name = string.Empty; var productName = string.Empty; var productVersion = string.Empty; var programId = string.Empty; var publisher = string.Empty; long size = 0; ulong usn = 0; var version = string.Empty; var description = string.Empty; var hasLinkedProgram = false; try { foreach (var subKeyValue in subKey.Values) { switch (subKeyValue.ValueName) { case "BinaryType": binaryType = subKeyValue.ValueData; break; case "BinFileVersion": binFileVersion = subKeyValue.ValueData; break; case "BinProductVersion": binProductVersion = subKeyValue.ValueData; break; case "FileId": fileId = subKeyValue.ValueData; break; case "IsOsComponent": isOsComponent = subKeyValue.ValueData == "1"; break; case "IsPeFile": isPeFile = subKeyValue.ValueData == "1"; break; case "Language": language = int.Parse(subKeyValue.ValueData); break; case "LinkDate": if (subKeyValue.ValueData.Length > 0) { var d = new DateTimeOffset( DateTime.Parse(subKeyValue.ValueData, DateTimeFormatInfo.InvariantInfo) .Ticks, TimeSpan.Zero); linkDate = d; } break; case "LongPathHash": longPathHash = subKeyValue.ValueData; break; case "LowerCaseLongPath": lowerCaseLongPath = subKeyValue.ValueData; break; case "Name": name = subKeyValue.ValueData; break; case "ProductName": productName = subKeyValue.ValueData; break; case "ProductVersion": productVersion = subKeyValue.ValueData; break; case "ProgramId": programId = subKeyValue.ValueData; var program = ProgramsEntries.SingleOrDefault(t => t.ProgramId == programId); if (program != null) { hasLinkedProgram = true; } break; case "Publisher": publisher = subKeyValue.ValueData; break; case "Size": try { if (subKeyValue.ValueData.StartsWith("0x")) { size = long.Parse(subKeyValue.ValueData.Replace("0x", ""), NumberStyles.HexNumber); } else { size = long.Parse(subKeyValue.ValueData); } } catch (Exception e) { } break; case "BusReportedDescription": case "FileSize": case "Model": case "Manufacturer": case "ParentId": case "MatchingID": case "ClassGuid": case "DriverName": case "Enumerator": case "Service": case "DeviceState": case "InstallState": case "DriverVerVersion": case "DriverPackageStrongName": case "DriverVerDate": case "AppxPackageRelativeId": case "AppxPackageFullName": case "ContainerId": case "HiddenArp": case "Inf": case "ProblemCode": case "Provider": case "Class": break; case "Description": description = subKeyValue.ValueData; break; case "Version": version = subKeyValue.ValueData; break; case "Usn": usn = ulong.Parse(subKeyValue.ValueData); break; default: if (subKeyValue.VkRecord.IsFree == false) { _logger.Warn( $"Unknown value name when processing FileEntry at path '{subKey.KeyPath}': {subKeyValue.ValueName}"); } break; } } } catch (Exception ex) { if (subKey.NkRecord.IsFree == false) { _logger.Error($"Error parsing FileEntry at {subKey.KeyPath}. Error: {ex.Message}"); _logger.Error( $"Please send the following text to [email protected]. \r\n\r\nKey data: {subKey}"); } } TotalFileEntries += 1; var fe = new FileEntryNew(binaryType, binFileVersion, productVersion, fileId, isOsComponent, isPeFile, language, linkDate, longPathHash, lowerCaseLongPath, name, productName, productVersion, programId, publisher, size, version, subKey.LastWriteTime.Value, binProductVersion, usn, description); if (hasLinkedProgram) { var program = ProgramsEntries.SingleOrDefault(t => t.ProgramId == fe.ProgramId); if (program != null) { fe.ApplicationName = program.Name; program.FileEntries.Add(fe); } } else { fe.ApplicationName = "Unassociated"; UnassociatedFileEntries.Add(fe); } } } else { _logger.Warn("Hive does not contain a Root\\InventoryApplicationFile key."); } _logger.Debug("Getting Shortcut data"); var shortCutkey = reg.GetKey(@"Root\InventoryApplicationShortcut"); if (shortCutkey != null) { foreach (var shortCutkeySubKey in shortCutkey.SubKeys) { var lnkName = ""; if (shortCutkeySubKey.Values.Count > 0) { lnkName = shortCutkeySubKey.Values.First().ValueData; } ShortCuts.Add(new Shortcut(shortCutkeySubKey.KeyName, lnkName, shortCutkeySubKey.LastWriteTime.Value)); } } _logger.Debug("Getting InventoryDeviceContainer data"); var deviceKey = reg.GetKey(@"Root\InventoryDeviceContainer"); if (deviceKey != null) { foreach (var deviceSubKey in deviceKey.SubKeys) { var categories = string.Empty; var discoveryMethod = string.Empty; var friendlyName = string.Empty; var icon = string.Empty; var isActive = false; var isConnected = false; var isMachineContainer = false; var isNetworked = false; var isPaired = false; var manufacturer = string.Empty; var modelId = string.Empty; var modelName = string.Empty; var modelNumber = string.Empty; var primaryCategory = string.Empty; var state = string.Empty; try { foreach (var keyValue in deviceSubKey.Values) { switch (keyValue.ValueName) { case "Categories": categories = keyValue.ValueData; break; case "DiscoveryMethod": discoveryMethod = keyValue.ValueData; break; case "FriendlyName": friendlyName = keyValue.ValueData; break; case "Icon": icon = keyValue.ValueData; break; case "IsActive": isActive = keyValue.ValueData == "1"; break; case "IsConnected": isConnected = keyValue.ValueData == "1"; break; case "IsMachineContainer": isMachineContainer = keyValue.ValueData == "1"; break; case "IsNetworked": isNetworked = keyValue.ValueData == "1"; break; case "IsPaired": isPaired = keyValue.ValueData == "1"; break; case "Manufacturer": manufacturer = keyValue.ValueData; break; case "ModelId": modelId = keyValue.ValueData; break; case "ModelName": modelName = keyValue.ValueData; break; case "ModelNumber": modelNumber = keyValue.ValueData; break; case "PrimaryCategory": primaryCategory = keyValue.ValueData; break; case "State": state = keyValue.ValueData; break; case "(default)": case "Model": case "BusReportedDescription": case "Version": case "LowerClassFilters": case "ManifestPath": case "UpperClassFilters": break; default: _logger.Warn( $"Unknown value name when processing DeviceContainer at path '{deviceSubKey.KeyPath}': {keyValue.ValueName}"); break; } } var dc = new DeviceContainer(deviceSubKey.KeyName, deviceSubKey.LastWriteTime.Value, categories, discoveryMethod, friendlyName, icon, isActive, isConnected, isMachineContainer, isNetworked, isPaired, manufacturer, modelId, modelName, modelNumber, primaryCategory, state); DeviceContainers.Add(dc); } catch (Exception ex) { if (deviceSubKey.NkRecord.IsFree == false) { _logger.Error( $"Error parsing DeviceContainer at {deviceSubKey.KeyPath}. Error: {ex.Message}"); _logger.Error( $"Please send the following text to [email protected]. \r\n\r\nKey data: {deviceSubKey}"); } } } } _logger.Debug("Getting InventoryDevicePnp data"); var pnpKey = reg.GetKey(@"Root\InventoryDevicePnp"); if (pnpKey != null) { foreach (var pnpsKey in pnpKey.SubKeys) { var busReportedDescription = string.Empty; var Class = string.Empty; var classGuid = string.Empty; var compid = string.Empty; var containerId = string.Empty; var description = string.Empty; var deviceState = string.Empty; var driverId = string.Empty; var driverName = string.Empty; var driverPackageStrongName = string.Empty; var driverVerDate = string.Empty; var driverVerVersion = string.Empty; var enumerator = string.Empty; var hwid = string.Empty; var inf = string.Empty; var installState = string.Empty; var manufacturer = string.Empty; var matchingId = string.Empty; var model = string.Empty; var parentId = string.Empty; var problemCode = string.Empty; var provider = string.Empty; var service = string.Empty; var stackid = string.Empty; try { foreach (var keyValue in pnpsKey.Values) { switch (keyValue.ValueName) { case "BusReportedDescription": busReportedDescription = keyValue.ValueData; break; case "Class": Class = keyValue.ValueData; break; case "ClassGuid": classGuid = keyValue.ValueData; break; case "COMPID": compid = keyValue.ValueData; break; case "ContainerId": containerId = keyValue.ValueData; break; case "Description": description = keyValue.ValueData; break; case "DeviceState": deviceState = keyValue.ValueData; break; case "DriverId": driverId = keyValue.ValueData; break; case "DriverName": driverName = keyValue.ValueData; break; case "DriverPackageStrongName": driverPackageStrongName = keyValue.ValueData; break; case "DriverVerDate": driverVerDate = keyValue.ValueData; break; case "DriverVerVersion": driverVerVersion = keyValue.ValueData; break; case "Enumerator": enumerator = keyValue.ValueData; break; case "HWID": hwid = keyValue.ValueData; break; case "Inf": inf = keyValue.ValueData; break; case "InstallState": installState = keyValue.ValueData; break; case "LowerClassFilters": case "LowerFilters": break; case "Manufacturer": manufacturer = keyValue.ValueData; break; case "MatchingID": matchingId = keyValue.ValueData; break; case "Model": model = keyValue.ValueData; break; case "ParentId": parentId = keyValue.ValueData; break; case "ProblemCode": problemCode = keyValue.ValueData; break; case "Provider": provider = keyValue.ValueData; break; case "Service": service = keyValue.ValueData; break; case "STACKID": stackid = keyValue.ValueData; break; case "UpperClassFilters": case "UpperFilters": case "ExtendedInfs": case "DeviceInterfaceClasses": case "(default)": case "DeviceExtDriversFlightIds": case "InstallDate": case "FirstInstallDate": case "DeviceDriverFlightId": _logger.Debug($"Value: '{keyValue.ValueName}' --> {keyValue.ValueData}"); break; default: _logger.Warn( $"Unknown value name when processing DevicePnp at path '{pnpsKey.KeyPath}': {keyValue.ValueName}"); break; } } var dp = new DevicePnp(pnpsKey.KeyName, pnpsKey.LastWriteTime.Value, busReportedDescription, Class, classGuid, compid, containerId, description, deviceState, driverId, driverName, driverPackageStrongName, driverVerDate, driverVerVersion, enumerator, hwid, inf, installState, manufacturer, matchingId, model, parentId, problemCode, provider, service, stackid); DevicePnps.Add(dp); } catch (Exception ex) { if (pnpKey.NkRecord.IsFree == false) { _logger.Error($"Error parsing DevicePnp at {pnpKey.KeyPath}. Error: {ex.Message}"); _logger.Error( $"Please send the following text to [email protected]. \r\n\r\nKey data: {pnpKey}"); } } } } _logger.Debug("Getting InventoryDriverBinary data"); var binaryKey = reg.GetKey(@"Root\InventoryDriverBinary"); if (binaryKey != null) { foreach (var binKey in binaryKey.SubKeys) { var driverCheckSum = 0; var driverCompany = string.Empty; var driverId = string.Empty; var driverInBox = false; var driverIsKernelMode = false; DateTimeOffset?driverLastWriteTime = null; var driverName = string.Empty; var driverPackageStrongName = string.Empty; var driverSigned = false; DateTimeOffset?driverTimeStamp = null; var driverType = string.Empty; var driverVersion = string.Empty; var imageSize = 0; var inf = string.Empty; var product = string.Empty; var productVersion = string.Empty; var service = string.Empty; var wdfVersion = string.Empty; try { foreach (var keyValue in binKey.Values) { switch (keyValue.ValueName) { case "DriverCheckSum": driverCheckSum = int.Parse(keyValue.ValueData); break; case "DriverCompany": driverCompany = keyValue.ValueData; break; case "DriverId": driverId = keyValue.ValueData; break; case "DriverInBox": driverInBox = keyValue.ValueData == "1"; break; case "DriverIsKernelMode": driverIsKernelMode = keyValue.ValueData == "1"; break; case "DriverLastWriteTime": if (keyValue.ValueData.Length > 0) { var d = new DateTimeOffset( DateTime.Parse(keyValue.ValueData, DateTimeFormatInfo.InvariantInfo).Ticks, TimeSpan.Zero); driverLastWriteTime = d; } break; case "DriverName": driverName = keyValue.ValueData; break; case "DriverPackageStrongName": driverPackageStrongName = keyValue.ValueData; break; case "DriverSigned": driverSigned = keyValue.ValueData == "1"; break; case "DriverTimeStamp": //DateTimeOffset.FromUnixTimeSeconds(seca).ToUniversalTime(); var seca = long.Parse(keyValue.ValueData); if (seca > 0) { driverTimeStamp = DateTimeOffset.FromUnixTimeSeconds(seca).ToUniversalTime(); } break; case "DriverType": driverType = keyValue.ValueData; break; case "DriverVersion": driverVersion = keyValue.ValueData; break; case "ImageSize": imageSize = int.Parse(keyValue.ValueData); break; case "Inf": inf = keyValue.ValueData; break; case "Product": product = keyValue.ValueData; break; case "ProductVersion": productVersion = keyValue.ValueData; break; case "Service": service = keyValue.ValueData; break; case "WdfVersion": wdfVersion = keyValue.ValueData; break; case "(default)": case "COMPID": case "HWID": break; default: _logger.Warn( $"Unknown value name when processing DriverBinary at path '{binKey.KeyPath}': {keyValue.ValueName}"); break; } } var db = new DriverBinary(binKey.KeyName, binKey.LastWriteTime.Value, driverCheckSum, driverCompany, driverId, driverInBox, driverIsKernelMode, driverLastWriteTime, driverName, driverPackageStrongName, driverSigned, driverTimeStamp, driverType, driverVersion, imageSize, inf, product, productVersion, service, wdfVersion); DriveBinaries.Add(db); } catch (Exception ex) { if (binaryKey.NkRecord.IsFree == false) { _logger.Error($"Error parsing DriverBinary at {binaryKey.KeyPath}. Error: {ex.Message}"); _logger.Error( $"Please send the following text to [email protected]. \r\n\r\nKey data: {binaryKey}"); } } } } _logger.Debug("Getting InventoryDriverPackage data"); var packaheKey = reg.GetKey(@"Root\InventoryDriverPackage"); if (packaheKey != null) { foreach (var packKey in packaheKey.SubKeys) { var Class = string.Empty; var ClassGuid = string.Empty; DateTimeOffset?Date = null; var Directory = string.Empty; var DriverInBox = false; var Hwids = string.Empty; var Inf = string.Empty; var Provider = string.Empty; var SubmissionId = string.Empty; var SYSFILE = string.Empty; var Version = string.Empty; try { foreach (var keyValue in packKey.Values) { switch (keyValue.ValueName) { case "Class": Class = keyValue.ValueData; break; case "ClassGuid": ClassGuid = keyValue.ValueData; break; case "Date": if (keyValue.ValueData.Length > 0) { var d = new DateTimeOffset( DateTime.Parse(keyValue.ValueData, DateTimeFormatInfo.InvariantInfo).Ticks, TimeSpan.Zero); Date = d; } break; case "Directory": Directory = keyValue.ValueData; break; case "DriverInBox": DriverInBox = keyValue.ValueData == "1"; break; case "Hwids": Hwids = keyValue.ValueData; break; case "Inf": Inf = keyValue.ValueData; break; case "Provider": Provider = keyValue.ValueData; break; case "SubmissionId": SubmissionId = keyValue.ValueData; break; case "SYSFILE": SYSFILE = keyValue.ValueData; break; case "Version": Version = keyValue.ValueData; break; case "IsActive": break; default: _logger.Warn( $"Unknown value name when processing DriverPackage at path '{packKey.KeyPath}': {keyValue.ValueName}"); break; } } var dp = new DriverPackage(packKey.KeyName, packKey.LastWriteTime.Value, Class, ClassGuid, Date, Directory, DriverInBox, Hwids, Inf, Provider, SubmissionId, SYSFILE, Version); DriverPackages.Add(dp); } catch (Exception ex) { if (packaheKey.NkRecord.IsFree == false) { _logger.Error($"Error parsing DriverPackage at {packaheKey.KeyPath}. Error: {ex.Message}"); _logger.Error( $"Please send the following text to [email protected]. \r\n\r\nKey data: {packaheKey}"); } } } } }
public AppCompatCache(string filename, int controlSet, bool noLogs) { byte[] rawBytes = null; Caches = new List <IAppCompatCache>(); var controlSetIds = new List <int>(); RegistryKey subKey = null; var isLiveRegistry = string.IsNullOrEmpty(filename); if (isLiveRegistry) { var keyCurrUser = Microsoft.Win32.Registry.LocalMachine; var subKey2 = keyCurrUser.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache"); if (subKey2 == null) { subKey2 = keyCurrUser.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatibility"); if (subKey2 == null) { Console.WriteLine( @"'CurrentControlSet\Control\Session Manager\AppCompatCache' key not found! Exiting"); return; } } rawBytes = (byte[])subKey2.GetValue("AppCompatCache", null); subKey2 = keyCurrUser.OpenSubKey(@"SYSTEM\Select"); ControlSet = (int)subKey2.GetValue("Current"); var is32Bit = Is32Bit(filename, null); var cache = Init(rawBytes, is32Bit, ControlSet); Caches.Add(cache); return; } RegistryHive reg; Privilege[] privileges = { Privilege.EnableDelegation, Privilege.Impersonate, Privilege.Tcb }; using (new PrivilegeEnabler(Privilege.Backup, privileges)) { ControlSet = controlSet; if (File.Exists(filename) == false && RawCopy.Helper.RawFileExists(filename) == false) { throw new FileNotFoundException($"File not found ({filename})!"); } var dirname = Path.GetDirectoryName(filename); var hiveBase = Path.GetFileName(filename); List <RawCopy.RawCopyReturn> rawFiles = null; try { reg = new RegistryHive(filename) { RecoverDeleted = true }; } catch (IOException) { //file is in use if (RawCopy.Helper.IsAdministrator() == false) { throw new UnauthorizedAccessException("Administrator privileges not found!"); } _logger.Warn($"'{filename}' is in use. Rerouting...\r\n"); var files = new List <string>(); files.Add(filename); var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?").ToList(); var log1 = $"{dirname}\\{hiveBase}.LOG1"; var log2 = $"{dirname}\\{hiveBase}.LOG2"; if (logFiles.Count == 0) { if (RawCopy.Helper.RawFileExists(log1)) { logFiles.Add(log1); } if (RawCopy.Helper.RawFileExists(log2)) { logFiles.Add(log2); } } foreach (var logFile in logFiles) { files.Add(logFile); } rawFiles = RawCopy.Helper.GetFiles(files); reg = new RegistryHive(rawFiles.First().FileBytes, rawFiles.First().InputFilename); } if (reg.Header.PrimarySequenceNumber != reg.Header.SecondarySequenceNumber) { if (string.IsNullOrEmpty(dirname)) { dirname = "."; } var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?").ToList(); var log1 = $"{dirname}\\{hiveBase}.LOG1"; var log2 = $"{dirname}\\{hiveBase}.LOG2"; if (logFiles.Count == 0) { if (File.Exists(log1)) { logFiles.Add(log1); } if (File.Exists(log2)) { logFiles.Add(log2); } } if (logFiles.Count == 0) { if (RawCopy.Helper.RawFileExists(log1)) { logFiles.Add(log1); } if (RawCopy.Helper.RawFileExists(log2)) { logFiles.Add(log2); } } if (logFiles.Count == 0) { if (noLogs == false) { _logger.Warn("Registry hive is dirty and no transaction logs were found in the same directory! LOGs should have same base name as the hive. Aborting!!"); throw new Exception("Sequence numbers do not match and transaction logs were not found in the same directory as the hive. Aborting"); } else { _logger.Warn("Registry hive is dirty and no transaction logs were found in the same directory. Data may be missing! Continuing anyways..."); } } else { if (noLogs == false) { if (rawFiles != null) { var lt = new List <TransactionLogFileInfo>(); foreach (var rawCopyReturn in rawFiles.Skip(1).ToList()) { var tt = new TransactionLogFileInfo(rawCopyReturn.InputFilename, rawCopyReturn.FileBytes); lt.Add(tt); } reg.ProcessTransactionLogs(lt, true); } else { reg.ProcessTransactionLogs(logFiles.ToList(), true); } } else { _logger.Warn("Registry hive is dirty and transaction logs were found in the same directory, but --nl was provided. Data may be missing! Continuing anyways..."); } } } reg.ParseHive(); } if (controlSet == -1) { for (var i = 0; i < 10; i++) { subKey = reg.GetKey($@"ControlSet00{i}\Control\Session Manager\AppCompatCache"); if (subKey == null) { subKey = reg.GetKey($@"ControlSet00{i}\Control\Session Manager\AppCompatibility"); } if (subKey != null) { controlSetIds.Add(i); } } if (controlSetIds.Count > 1) { _logger.Warn( $"***The following ControlSet00x keys will be exported: {string.Join(",", controlSetIds)}. Use -c to process keys individually\r\n"); } } else { //a control set was passed in subKey = reg.GetKey($@"ControlSet00{ControlSet}\Control\Session Manager\AppCompatCache"); if (subKey == null) { subKey = reg.GetKey($@"ControlSet00{ControlSet}\Control\Session Manager\AppCompatibility"); } if (subKey == null) { throw new Exception($"Could not find ControlSet00{ControlSet}. Exiting"); } controlSetIds.Add(ControlSet); } var is32 = Is32Bit(filename, reg); _logger.Debug($@"**** Found {controlSetIds.Count} ids to process"); foreach (var id in controlSetIds) { _logger.Debug($@"**** Processing id {id}"); // var hive2 = new RegistryHiveOnDemand(filename); subKey = reg.GetKey($@"ControlSet00{id}\Control\Session Manager\AppCompatCache"); if (subKey == null) { _logger.Debug($@"**** Initial subkey null, getting appCompatability key"); subKey = reg.GetKey($@"ControlSet00{id}\Control\Session Manager\AppCompatibility"); } _logger.Debug($@"**** Looking AppCompatcache value"); var val = subKey?.Values.SingleOrDefault(c => c.ValueName == "AppCompatCache"); if (val != null) { _logger.Debug($@"**** Found AppCompatcache value"); rawBytes = val.ValueDataRaw; } if (rawBytes == null) { _logger.Error($@"'AppCompatCache' value not found for 'ControlSet00{id}'! Exiting"); } var cache = Init(rawBytes, is32, id); Caches.Add(cache); } }
public AmcacheOld(string hive, bool recoverDeleted, bool noLogs) { _logger = LogManager.GetLogger("AmcacheOld"); RegistryHive reg; var dirname = Path.GetDirectoryName(hive); var hiveBase = Path.GetFileName(hive); List <RawCopy.RawCopyReturn> rawFiles = null; try { reg = new RegistryHive(hive) { RecoverDeleted = true }; } catch (IOException) { //file is in use if (RawCopy.Helper.IsAdministrator() == false) { throw new UnauthorizedAccessException("Administrator privileges not found!"); } _logger.Warn($"'{hive}' is in use. Rerouting...\r\n"); var files = new List <string>(); files.Add(hive); var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?"); foreach (var logFile in logFiles) { files.Add(logFile); } rawFiles = RawCopy.Helper.GetFiles(files); var b = new byte[rawFiles.First().FileStream.Length]; rawFiles.First().FileStream.Read(b, 0, (int)rawFiles.First().FileStream.Length); reg = new RegistryHive(b, rawFiles.First().InputFilename); } if (reg.Header.PrimarySequenceNumber != reg.Header.SecondarySequenceNumber) { if (string.IsNullOrEmpty(dirname)) { dirname = "."; } var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?"); var log = LogManager.GetCurrentClassLogger(); if (logFiles.Length == 0) { if (noLogs == false) { log.Warn("Registry hive is dirty and no transaction logs were found in the same directory! LOGs should have same base name as the hive. Aborting!!"); throw new Exception("Sequence numbers do not match and transaction logs were not found in the same directory as the hive. Aborting"); } else { log.Warn("Registry hive is dirty and no transaction logs were found in the same directory. Data may be missing! Continuing anyways..."); } } else { if (noLogs == false) { if (rawFiles != null) { var lt = new List <TransactionLogFileInfo>(); foreach (var rawCopyReturn in rawFiles.Skip(1).ToList()) { var b = new byte[rawCopyReturn.FileStream.Length]; rawCopyReturn.FileStream.Read(b, 0, (int)rawCopyReturn.FileStream.Length); var tt = new TransactionLogFileInfo(rawCopyReturn.InputFilename, b); lt.Add(tt); } reg.ProcessTransactionLogs(lt, true); } else { reg.ProcessTransactionLogs(logFiles.ToList(), true); } } else { log.Warn("Registry hive is dirty and transaction logs were found in the same directory, but --nl was provided. Data may be missing! Continuing anyways..."); } } } reg.ParseHive(); var fileKey = reg.GetKey(@"Root\File"); var programsKey = reg.GetKey(@"Root\Programs"); UnassociatedFileEntries = new List <FileEntryOld>(); ProgramsEntries = new List <ProgramsEntryOld>(); if (fileKey == null || programsKey == null) { _logger.Error("Hive does not contain a File and/or Programs key. Processing cannot continue"); return; } //First, we get data for all the Program entries under Programs key _logger.Debug("Getting Programs data"); foreach (var registryKey in programsKey.SubKeys) { var ProgramName0 = ""; var ProgramVersion1 = ""; var Guid10 = ""; var UninstallGuid11 = ""; var Guid12 = ""; var Dword13 = 0; var Dword14 = 0; var Dword15 = 0; var UnknownBytes = new byte[0]; long Qword17 = 0; var Dword18 = 0; var VenderName2 = ""; var LocaleID3 = ""; var Dword5 = 0; var InstallSource6 = ""; var UninstallKey7 = ""; DateTimeOffset?EpochA = null; DateTimeOffset?EpochB = null; var PathListd = ""; var Guidf = ""; var RawFiles = ""; try { foreach (var value in registryKey.Values) { switch (value.ValueName) { case "0": ProgramName0 = value.ValueData; break; case "1": ProgramVersion1 = value.ValueData; break; case "2": VenderName2 = value.ValueData; break; case "3": LocaleID3 = value.ValueData; break; case "5": Dword5 = int.Parse(value.ValueData); break; case "6": InstallSource6 = value.ValueData; break; case "7": UninstallKey7 = value.ValueData; break; case "a": try { var seca = long.Parse(value.ValueData); if (seca > 0) { EpochA = DateTimeOffset.FromUnixTimeSeconds(seca).ToUniversalTime(); } } catch (Exception) { //sometimes the number is way too big } break; case "b": var seconds = long.Parse(value.ValueData); if (seconds > 0) { EpochB = DateTimeOffset.FromUnixTimeSeconds(seconds).ToUniversalTime(); } break; case "d": PathListd = value.ValueData; break; case "f": Guidf = value.ValueData; break; case "10": Guid10 = value.ValueData; break; case "11": UninstallGuid11 = value.ValueData; break; case "12": Guid12 = value.ValueData; break; case "13": Dword13 = int.Parse(value.ValueData); break; case "14": Dword13 = int.Parse(value.ValueData); break; case "15": Dword13 = int.Parse(value.ValueData); break; case "16": UnknownBytes = value.ValueDataRaw; break; case "17": Qword17 = long.Parse(value.ValueData); break; case "18": Dword18 = int.Parse(value.ValueData); break; case "Files": RawFiles = value.ValueData; break; default: _logger.Warn( $"Unknown value name in Program at path {registryKey.KeyPath}: {value.ValueName}"); break; } } var pe = new ProgramsEntryOld(ProgramName0, ProgramVersion1, VenderName2, LocaleID3, InstallSource6, UninstallKey7, Guid10, Guid12, UninstallGuid11, Dword5, Dword13, Dword14, Dword15, UnknownBytes, Qword17, Dword18, EpochA, EpochB, PathListd, Guidf, RawFiles, registryKey.KeyName, registryKey.LastWriteTime.Value); ProgramsEntries.Add(pe); } catch (Exception ex) { _logger.Error($"Error parsing ProgramsEntry at {registryKey.KeyPath}. Error: {ex.Message}"); _logger.Error( $"Please send the following text to [email protected]. \r\n\r\nKey data: {registryKey}"); } } //For each Programs entry, add the related Files entries from Files\Volume subkey, put the rest in unassociated _logger.Debug("Getting Files data"); foreach (var registryKey in fileKey.SubKeys) { //These are the guids for volumes foreach (var subKey in registryKey.SubKeys) { var prodName = ""; int?langId = null; var fileVerString = ""; var fileVerNum = ""; var fileDesc = ""; var compName = ""; var fullPath = ""; var switchBack = ""; var peHash = ""; var progID = ""; var sha = ""; long binProdVersion = 0; ulong binFileVersion = 0; var linkerVersion = 0; var binType = 0; var isLocal = 0; var gProgramID = 0; int? fileSize = null; int? sizeOfImage = null; uint? peHeaderChecksum = null; DateTimeOffset?created = null; DateTimeOffset?lm = null; DateTimeOffset?lmStore = null; DateTimeOffset?linkDate = null; var hasLinkedProgram = false; try { //these are the files executed from the volume foreach (var keyValue in subKey.Values) { var keyVal = int.Parse(keyValue.ValueName, NumberStyles.HexNumber); switch (keyVal) { case ProductName: prodName = keyValue.ValueData; break; case CompanyName: compName = keyValue.ValueData; break; case FileVersionNumber: fileVerNum = keyValue.ValueData; break; case LanguageCode: langId = int.Parse(keyValue.ValueData); break; case SwitchBackContext: switchBack = keyValue.ValueData; break; case FileVersionString: fileVerString = keyValue.ValueData; break; case FileSize: fileSize = int.Parse(keyValue.ValueData); break; case SizeOfImage: sizeOfImage = int.Parse(keyValue.ValueData); break; case PEHeaderHash: peHash = keyValue.ValueData; break; case PEHeaderChecksum: peHeaderChecksum = uint.Parse(keyValue.ValueData); break; case BinProductVersion: binProdVersion = long.Parse(keyValue.ValueData); break; case BinFileVersion: binFileVersion = ulong.Parse(keyValue.ValueData); break; case FileDescription: fileDesc = keyValue.ValueData; break; case LinkerVersion: linkerVersion = int.Parse(keyValue.ValueData); break; case LinkDate: linkDate = DateTimeOffset.FromUnixTimeSeconds(long.Parse(keyValue.ValueData)) .ToUniversalTime(); break; case BinaryType: binType = int.Parse(keyValue.ValueData); break; case LastModified: lm = DateTimeOffset.FromFileTime(long.Parse(keyValue.ValueData)).ToUniversalTime(); break; case Created: created = DateTimeOffset.FromFileTime(long.Parse(keyValue.ValueData)).ToUniversalTime(); break; case FullPath: fullPath = keyValue.ValueData; break; case IsLocal: isLocal = int.Parse(keyValue.ValueData); break; case GuessProgramID: gProgramID = int.Parse(keyValue.ValueData); break; case LastModifiedStore: lmStore = DateTimeOffset.FromFileTime(long.Parse(keyValue.ValueData)) .ToUniversalTime(); break; case ProgramID: progID = keyValue.ValueData; var program = ProgramsEntries.SingleOrDefault(t => t.ProgramID == progID); if (program != null) { hasLinkedProgram = true; } break; case SHA1: sha = keyValue.ValueData; break; default: _logger.Warn( $"Unknown value name when processing FileEntry at path '{subKey.KeyPath}': 0x{keyVal:X}"); break; } } if (fullPath.Length == 0) { continue; } TotalFileEntries += 1; var fe = new FileEntryOld(prodName, progID, sha, fullPath, lmStore, registryKey.KeyName, registryKey.LastWriteTime.Value, subKey.KeyName, subKey.LastWriteTime.Value, isLocal, compName, langId, fileVerString, peHash, fileVerNum, fileDesc, binProdVersion, binFileVersion, linkerVersion, binType, switchBack, fileSize, linkDate, sizeOfImage, lm, created, peHeaderChecksum, gProgramID, subKey.KeyName); if (hasLinkedProgram) { var program = ProgramsEntries.SingleOrDefault(t => t.ProgramID == fe.ProgramID); fe.ProgramName = program.ProgramName_0; program.FileEntries.Add(fe); } else { fe.ProgramName = "Unassociated"; UnassociatedFileEntries.Add(fe); } } catch (Exception ex) { _logger.Error($"Error parsing FileEntry at {subKey.KeyPath}. Error: {ex.Message}"); _logger.Error( $"Please send the following text to [email protected]. \r\n\r\nKey data: {subKey}"); } } } }
private static void ProcessFile(string arg) { FileInfo fi = new FileInfo(arg); if (fi.Length < 4 || !IsRegistryFile(arg)) { return; } byte[] raw = File.ReadAllBytes(arg); RegistryHive reg = new RegistryHive(raw, arg) { RecoverDeleted = true, FlushRecordListsAfterParse = false }; string name; using (FileStream fs = new FileStream(arg, FileMode.Open, FileAccess.Read)) { name = Hashes.CalculateMD5FromStream(fs); } string path = $"regdrop/{name}"; Directory.CreateDirectory(path); File.WriteAllText($"{path}/info.txt", reg.Header.ToString()); if (!reg.Header.ValidateCheckSum()) { Console.Error.WriteLine("Checksum validation error. Exiting."); return; } if (reg.Header.PrimarySequenceNumber != reg.Header.SecondarySequenceNumber) { string filePath = Path.GetDirectoryName(arg); string fileName = Path.GetFileNameWithoutExtension(arg); var logFiles = Directory.GetFiles(filePath, $"{fileName}.LOG?"); if (logFiles.Length == 0) { Console.Error.WriteLine($"[{arg}] Transaction logs missing. Exiting."); return; } else { reg.ProcessTransactionLogs(logFiles.ToList(), true); } } reg.ParseHive(); string dumpFilePathTmp = $"{path}/dump.tmp"; reg.ExportDataToCommonFormat(dumpFilePathTmp, false); string dumpFilePathCsv = $"{path}/dump.csv"; string dumpFilePathJson = $"{path}/dump.json"; using (DataTable dt = new DataTable()) { dt.Columns.Add("type", typeof(string)); dt.Columns.Add("active", typeof(string)); dt.Columns.Add("offset", typeof(decimal)); dt.Columns.Add("path", typeof(string)); dt.Columns.Add("name", typeof(string)); dt.Columns.Add("dataType", typeof(decimal)); dt.Columns.Add("value", typeof(string)); dt.Columns.Add("lastWriteTime", typeof(string)); using (var fs = new FileStream(dumpFilePathTmp, FileMode.Open, FileAccess.Read, FileShare.Read)) { dt.FromCsv(fs, false); } DataColumn type = dt.Columns["type"]; foreach (var dr in dt.Rows .OfType <DataRow>() .Where(x => (string)x[type] == "value")) { DataColumn dataType = dt.Columns["dataType"]; DataColumn value = dt.Columns["value"]; byte[] data = ConvertToBytes((string)dr[value]); decimal dataTypeVal = (decimal)dr[dataType]; if (dataTypeVal == 0x2) { string txt = Encoding.Unicode.GetString(data).TrimEnd('\0'); dr[value] = txt; } else if (dataTypeVal == 0x4 && data.Length == 4) { int val = BitConverter.ToInt32(data); dr[value] = val.ToString(); } else if (dataTypeVal == 0x5 && data.Length == 4) { int val = BitConverter.ToInt32(data.Reverse().ToArray()); dr[value] = val.ToString(); } else if (dataTypeVal == 0x7) { string txtlist = Encoding.Unicode.GetString(data).TrimEnd('\0'); string[] split = txtlist.Split('\0', StringSplitOptions.RemoveEmptyEntries); dr[value] = string.Join("\n", split); } else if (dataTypeVal == 0xb && data.Length == 8) { long val = BitConverter.ToInt64(data); dr[value] = val.ToString(); } else { dr[value] = Convert.ToBase64String(data); } } using (var fs = new FileStream(dumpFilePathCsv, FileMode.Create, FileAccess.Write, FileShare.Read)) { dt.ToCsv(fs); } JsonDocument jdoc; dt.ToJson(out jdoc); using (var fs = new FileStream(dumpFilePathJson, FileMode.Create, FileAccess.Write, FileShare.Read)) { Utf8JsonWriter writer = new Utf8JsonWriter(fs); jdoc.WriteTo(writer); writer.Flush(); } } if (File.Exists(dumpFilePathTmp)) { File.Delete(dumpFilePathTmp); } }
private static void DoWork(string d, string f, string @out, bool ca, bool cn, bool debug, bool trace) { if (f.IsNullOrEmpty() == false || d.IsNullOrEmpty() == false) { if (@out.IsNullOrEmpty()) { var helpBld = new HelpBuilder(LocalizationResources.Instance, Console.WindowWidth); var hc = new HelpContext(helpBld, _rootCommand, Console.Out); helpBld.Write(hc); Console.WriteLine(); _logger.Warn("--out is required. Exiting"); Console.WriteLine(); return; } } if (debug) { foreach (var r in LogManager.Configuration.LoggingRules) { r.EnableLoggingForLevel(LogLevel.Debug); } LogManager.ReconfigExistingLoggers(); _logger.Debug("Enabled debug messages..."); } if (trace) { foreach (var r in LogManager.Configuration.LoggingRules) { r.EnableLoggingForLevel(LogLevel.Trace); } LogManager.ReconfigExistingLoggers(); _logger.Trace("Enabled trace messages..."); } var hivesToProcess = new List <string>(); _logger.Info(Header); _logger.Info(""); _logger.Info($"Command line: {string.Join(" ", Environment.GetCommandLineArgs().Skip(1))}\r\n"); if (f?.Length > 0) { if (File.Exists(f) == false) { _logger.Error($"File '{f}' does not exist."); return; } hivesToProcess.Add(f); } else if (d?.Length > 0) { if (Directory.Exists(d) == false) { _logger.Error($"Directory '{d}' does not exist."); return; } var okFileParts = new HashSet <string>(); okFileParts.Add("USRCLASS"); okFileParts.Add("NTUSER"); okFileParts.Add("SYSTEM"); okFileParts.Add("SAM"); okFileParts.Add("SOFTWARE"); okFileParts.Add("AMCACHE"); okFileParts.Add("SYSCACHE"); okFileParts.Add("SECURITY"); okFileParts.Add("DRIVERS"); okFileParts.Add("COMPONENTS"); var directoryEnumerationFilters = new DirectoryEnumerationFilters(); directoryEnumerationFilters.InclusionFilter = fsei => { if (fsei.Extension.ToUpperInvariant() == ".LOG1" || fsei.Extension.ToUpperInvariant() == ".LOG2" || fsei.Extension.ToUpperInvariant() == ".DLL" || fsei.Extension.ToUpperInvariant() == ".LOG" || fsei.Extension.ToUpperInvariant() == ".CSV" || fsei.Extension.ToUpperInvariant() == ".BLF" || fsei.Extension.ToUpperInvariant() == ".REGTRANS-MS" || fsei.Extension.ToUpperInvariant() == ".EXE" || fsei.Extension.ToUpperInvariant() == ".TXT" || fsei.Extension.ToUpperInvariant() == ".INI") { return(false); } var foundOkFilePart = false; foreach (var okFilePart in okFileParts) { if (fsei.FileName.ToUpperInvariant().Contains(okFilePart)) { foundOkFilePart = true; // return true; } } if (foundOkFilePart == false) { return(false); } var fi = new FileInfo(fsei.FullPath); if (fi.Length < 4) { return(false); } try { using (var fs = new FileStream(fsei.FullPath, FileMode.Open, FileAccess.Read)) { using (var br = new BinaryReader(fs, new ASCIIEncoding())) { try { var chunk = br.ReadBytes(4); var sig = BitConverter.ToInt32(chunk, 0); if (sig == 0x66676572) { return(true); } } catch (Exception) { } return(false); } } } catch (IOException) { if (Helper.IsAdministrator() == false) { throw new UnauthorizedAccessException("Administrator privileges not found!"); } var files = new List <string>(); files.Add(fsei.FullPath); var rawf = Helper.GetRawFiles(files); if (rawf.First().FileStream.Length == 0) { return(false); } try { var b = new byte[4]; rawf.First().FileStream.ReadExactly(b, 4); var sig = BitConverter.ToInt32(b, 0); if (sig == 0x66676572) { return(true); } } catch (Exception) { } return(false); } }; directoryEnumerationFilters.RecursionFilter = entryInfo => !entryInfo.IsMountPoint && !entryInfo.IsSymbolicLink; directoryEnumerationFilters.ErrorFilter = (errorCode, errorMessage, pathProcessed) => true; var dirEnumOptions = DirectoryEnumerationOptions.Files | DirectoryEnumerationOptions.Recursive | DirectoryEnumerationOptions.SkipReparsePoints | DirectoryEnumerationOptions.ContinueOnException | DirectoryEnumerationOptions.BasicSearch; if (Directory.Exists(@out) == false) { _logger.Info($"Creating --out directory '{@out}'..."); Directory.CreateDirectory(@out); } else { if (Directory.GetFiles(@out).Length > 0 && cn) { _logger.Warn($"'{@out}' contains files! This may cause --cn to revert back to uncompressed names. Ideally, '{@out}' should be empty."); Console.WriteLine(); } } _logger.Fatal($"Searching '{d}' for hives..."); var files2 = Alphaleonis.Win32.Filesystem.Directory.EnumerateFileSystemEntries(d, dirEnumOptions, directoryEnumerationFilters); var count = 0; try { hivesToProcess.AddRange(files2); count = hivesToProcess.Count; _logger.Info($"\tHives found: {count:N0}"); } catch (Exception ex) { _logger.Fatal($"Could not access all files in '{d}'! Error: {ex.Message}"); _logger.Error(""); _logger.Fatal("Rerun the program with Administrator privileges to try again\r\n"); //Environment.Exit(-1); } } else { var helpBld = new HelpBuilder(LocalizationResources.Instance, Console.WindowWidth); var hc = new HelpContext(helpBld, _rootCommand, Console.Out); helpBld.Write(hc); return; } if (hivesToProcess.Count == 0) { _logger.Warn("No hives were found. Exiting..."); return; } _sw = new Stopwatch(); _sw.Start(); foreach (var hiveToProcess in hivesToProcess) { _logger.Info(""); byte[] updatedBytes = null; _logger.Info($"Processing hive '{hiveToProcess}'"); if (File.Exists(hiveToProcess) == false) { _logger.Warn($"'{hiveToProcess}' does not exist. Skipping"); continue; } try { RegistryHive reg; var dirname = Path.GetDirectoryName(hiveToProcess); var hiveBase = Path.GetFileName(hiveToProcess); List <RawCopyReturn> rawFiles = null; try { using (var fs = new FileStream(hiveToProcess, FileMode.Open, FileAccess.Read)) { reg = new RegistryHive(fs.ReadFully(), hiveToProcess); } } catch (IOException) { //file is in use if (Helper.IsAdministrator() == false) { throw new UnauthorizedAccessException("Administrator privileges not found!"); } _logger.Warn($"\t'{hiveToProcess}' is in use. Rerouting...\r\n"); var files = new List <string>(); files.Add(hiveToProcess); var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?"); foreach (var logFile in logFiles) { files.Add(logFile); } rawFiles = Helper.GetRawFiles(files); if (rawFiles.First().FileStream.Length == 0) { continue; } var bb = rawFiles.First().FileStream.ReadFully(); reg = new RegistryHive(bb, rawFiles.First().InputFilename); } if (reg.Header.PrimarySequenceNumber != reg.Header.SecondarySequenceNumber) { if (string.IsNullOrEmpty(dirname)) { dirname = "."; } var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?"); if (logFiles.Length == 0) { if (ca) { _logger.Info($"\tHive '{hiveToProcess}' is dirty, but no logs were found in the same directory. --ca is true. Copying..."); updatedBytes = File.ReadAllBytes(hiveToProcess); } else { _logger.Info($"\tHive '{hiveToProcess}' is dirty and no transaction logs were found in the same directory. --ca is false. Skipping..."); continue; } } if (updatedBytes == null) { if (rawFiles != null) { var lt = new List <TransactionLogFileInfo>(); foreach (var rawCopyReturn in rawFiles.Skip(1).ToList()) { var bb1 = rawCopyReturn.FileStream.ReadFully(); var tt = new TransactionLogFileInfo(rawCopyReturn.InputFilename, bb1); lt.Add(tt); } updatedBytes = reg.ProcessTransactionLogs(lt); } else { updatedBytes = reg.ProcessTransactionLogs(logFiles.ToList()); } } } if (updatedBytes == null) { if (ca) { _logger.Info($"\tHive '{hiveToProcess}' is not dirty, but --ca is true. Copying..."); updatedBytes = File.ReadAllBytes(hiveToProcess); } else { _logger.Info($"\tHive '{hiveToProcess}' is not dirty and --ca is false. Skipping..."); continue; } } var outFile = hiveToProcess.Replace(":", "").Replace("\\", "_"); var outFileAll = Path.Combine(@out, outFile); if (cn && (outFileAll.ToUpperInvariant().Contains("NTUSER") || outFileAll.ToUpperInvariant().Contains("USRCLASS"))) { var dl = hiveToProcess[0].ToString(); var segs = hiveToProcess.SplitAndTrim('\\'); var profile = segs[2]; var filename = Path.GetFileName(hiveToProcess); var outFile2 = $"{dl}_{profile}_{filename}"; outFileAll = Path.Combine(@out, outFile2); } if (File.Exists(outFileAll)) { var oldOut = outFileAll; outFileAll = Path.Combine(@out, outFile); _logger.Warn($"\tFile '{oldOut}' exists! Saving as non-compressed name: '{outFileAll}'"); } _logger.Fatal($"\tSaving updated hive to '{outFileAll}'"); using (var fs = new FileStream(outFileAll, FileMode.Create)) { fs.Write(updatedBytes, 0, updatedBytes.Length); fs.Flush(); fs.Close(); } } catch (Exception ex) { if (ex.Message.Contains("Sequence numbers do not match and transaction") == false) { if (ex.Message.Contains("Administrator privileges not found")) { _logger.Fatal($"Could not access '{hiveToProcess}' because it is in use"); _logger.Error(""); _logger.Fatal("Rerun the program with Administrator privileges to try again\r\n"); } else { _logger.Error($"There was an error: {ex.Message}"); } } } } _sw.Stop(); _logger.Info(""); _logger.Info($"Total processing time: {_sw.Elapsed.TotalSeconds:N3} seconds"); _logger.Info(""); }
public AppCompatCache(string filename, int controlSet) { byte[] rawBytes = null; Caches = new List <IAppCompatCache>(); if (File.Exists(filename) == false) { throw new FileNotFoundException($"File not found ({filename})!"); } var controlSetIds = new List <int>(); // var hive = new RegistryHiveOnDemand(filename); var hive = new RegistryHive(filename); if (hive.Header.PrimarySequenceNumber != hive.Header.SecondarySequenceNumber) { var hiveBase = Path.GetFileName(filename); var dirname = Path.GetDirectoryName(filename); if (string.IsNullOrEmpty(dirname)) { dirname = "."; } var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?"); if (logFiles.Length == 0) { Console.WriteLine("Registry hive is dirty and no transaction logs were found. Try to parse without logs."); } else { hive.ProcessTransactionLogs(logFiles.ToList(), true); } } hive.ParseHive(); RegistryKey subKey = hive.GetKey("Select"); var ControlSet = int.Parse(subKey.Values.Single(c => c.ValueName == "Current").ValueData); // ControlSet = controlSet; if (controlSet == -1) { for (var i = 0; i < 10; i++) { subKey = hive.GetKey($@"ControlSet00{i}\Control\Session Manager\AppCompatCache"); if (subKey == null) { subKey = hive.GetKey($@"ControlSet00{i}\Control\Session Manager\AppCompatibility"); } if (subKey != null) { controlSetIds.Add(i); } } if (controlSetIds.Count > 1) { Console.WriteLine($"***The following ControlSet00x keys will be exported: {string.Join(",", controlSetIds)}.\r\n"); } } else { //a control set was passed in subKey = hive.GetKey($@"ControlSet00{ControlSet}\Control\Session Manager\AppCompatCache"); if (subKey == null) { subKey = hive.GetKey($@"ControlSet00{ControlSet}\Control\Session Manager\AppCompatibility"); } if (subKey == null) { throw new Exception($"Could not find ControlSet00{ControlSet}. Exiting"); } controlSetIds.Add(ControlSet); } var is32 = Is32Bit(filename); string computerName = ComputerName(filename); foreach (var id in controlSetIds) { var hive2 = new RegistryHiveOnDemand(filename); subKey = hive2.GetKey($@"ControlSet00{id}\Control\Session Manager\AppCompatCache"); if (subKey == null) { subKey = hive2.GetKey($@"ControlSet00{id}\Control\Session Manager\AppCompatibility"); } var val = subKey?.Values.SingleOrDefault(c => c.ValueName == "AppCompatCache"); if (val != null) { rawBytes = val.ValueDataRaw; } if (rawBytes == null) { throw new Exception($@"'AppCompatCache' value not found for 'ControlSet00{id}'! Exiting"); } var cache = Init(rawBytes, is32, id, computerName); Caches.Add(cache); } }
public AppCompatCache(string filename, int controlSet, bool noLogs) { byte[] rawBytes = null; Caches = new List <IAppCompatCache>(); var controlSetIds = new List <int>(); RegistryKey subKey = null; var isLiveRegistry = string.IsNullOrEmpty(filename); if (isLiveRegistry) { var keyCurrUser = Microsoft.Win32.Registry.LocalMachine; var subKey2 = keyCurrUser.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache"); if (subKey2 == null) { subKey2 = keyCurrUser.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatibility"); if (subKey2 == null) { Console.WriteLine( @"'CurrentControlSet\Control\Session Manager\AppCompatCache' key not found! Exiting"); return; } } rawBytes = (byte[])subKey2.GetValue("AppCompatCache", null); subKey2 = keyCurrUser.OpenSubKey(@"SYSTEM\Select"); ControlSet = (int)subKey2.GetValue("Current"); var is32Bit = Is32Bit(filename); var cache = Init(rawBytes, is32Bit, ControlSet); Caches.Add(cache); return; } ControlSet = controlSet; if (File.Exists(filename) == false) { throw new FileNotFoundException($"File not found ({filename})!"); } var hive = new RegistryHive(filename); if (hive.Header.PrimarySequenceNumber != hive.Header.SecondarySequenceNumber) { var hiveBase = Path.GetFileName(filename); var dirname = Path.GetDirectoryName(filename); if (string.IsNullOrEmpty(dirname)) { dirname = "."; } var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?"); if (logFiles.Length == 0) { var log = LogManager.GetCurrentClassLogger(); if (noLogs == false) { log.Warn("Registry hive is dirty and no transaction logs were found in the same directory! LOGs should have same base name as the hive. Aborting!!"); throw new Exception("Sequence numbers do not match and transaction logs were not found in the same directory as the hive. Aborting"); } log.Warn("Registry hive is dirty and no transaction logs were found in the same directory. Data may be missing! Continuing anyways..."); } else { hive.ProcessTransactionLogs(logFiles.ToList(), true); } } hive.ParseHive(); if (controlSet == -1) { for (var i = 0; i < 10; i++) { subKey = hive.GetKey($@"ControlSet00{i}\Control\Session Manager\AppCompatCache"); if (subKey == null) { subKey = hive.GetKey($@"ControlSet00{i}\Control\Session Manager\AppCompatibility"); } if (subKey != null) { controlSetIds.Add(i); } } if (controlSetIds.Count > 1) { var log = LogManager.GetCurrentClassLogger(); log.Warn( $"***The following ControlSet00x keys will be exported: {string.Join(",", controlSetIds)}. Use -c to process keys individually\r\n"); } } else { //a control set was passed in subKey = hive.GetKey($@"ControlSet00{ControlSet}\Control\Session Manager\AppCompatCache"); if (subKey == null) { subKey = hive.GetKey($@"ControlSet00{ControlSet}\Control\Session Manager\AppCompatibility"); } if (subKey == null) { throw new Exception($"Could not find ControlSet00{ControlSet}. Exiting"); } controlSetIds.Add(ControlSet); } var is32 = Is32Bit(filename); var log1 = LogManager.GetCurrentClassLogger(); log1.Debug($@"**** Found {controlSetIds.Count} ids to process"); foreach (var id in controlSetIds) { log1.Debug($@"**** Processing id {id}"); var hive2 = new RegistryHiveOnDemand(filename); subKey = hive2.GetKey($@"ControlSet00{id}\Control\Session Manager\AppCompatCache"); if (subKey == null) { log1.Debug($@"**** Initial subkey null, getting appCompatability key"); subKey = hive2.GetKey($@"ControlSet00{id}\Control\Session Manager\AppCompatibility"); } log1.Debug($@"**** Looking AppCompatcache value"); var val = subKey?.Values.SingleOrDefault(c => c.ValueName == "AppCompatCache"); if (val != null) { log1.Debug($@"**** Found AppCompatcache value"); rawBytes = val.ValueDataRaw; } if (rawBytes == null) { var log = LogManager.GetCurrentClassLogger(); log.Error($@"'AppCompatCache' value not found for 'ControlSet00{id}'! Exiting"); } var cache = Init(rawBytes, is32, id); Caches.Add(cache); } }
static void Main(string[] args) { Exceptionless.ExceptionlessClient.Default.Startup("fTcEOUkt1CxljTyOZfsr8AcSGQwWE4aYaYqk7cE1"); SetupNLog(); _logger = LogManager.GetCurrentClassLogger(); _fluentCommandLineParser = new FluentCommandLineParser <ApplicationArguments> { IsCaseSensitive = false }; _fluentCommandLineParser.Setup(arg => arg.Directory) .As('d') .WithDescription( "Directory to look for hives (recursively). -f or -d is required."); _fluentCommandLineParser.Setup(arg => arg.HiveFile) .As('f') .WithDescription("Hive to process. -f or -d is required.\r\n"); _fluentCommandLineParser.Setup(arg => arg.OutDirectory) .As("out") .WithDescription( "Directory to save updated hives to. Only dirty hives with logs applied will end up in --out directory\r\n"); _fluentCommandLineParser.Setup(arg => arg.CopyAlways) .As("ca") .WithDescription( "When true, always copy hives to --out directory, even if they aren't dirty. Default is TRUE").SetDefault(true); _fluentCommandLineParser.Setup(arg => arg.CompressNames) .As("cn") .WithDescription( "When true, compress names for profile based hives. Default is TRUE\r\n").SetDefault(true); _fluentCommandLineParser.Setup(arg => arg.Debug) .As("debug") .WithDescription("Show debug information during processing").SetDefault(false); _fluentCommandLineParser.Setup(arg => arg.Trace) .As("trace") .WithDescription("Show trace information during processing").SetDefault(false); var header = $"rla version {Assembly.GetExecutingAssembly().GetName().Version}" + "\r\n\r\nAuthor: Eric Zimmerman ([email protected])" + "\r\nhttps://github.com/EricZimmerman/RECmd\r\n\r\nNote: Enclose all strings containing spaces (and all RegEx) with double quotes"; var footer = @"Example: rla.exe --f ""C:\Temp\UsrClass 1.dat"" --out C:\temp" + "\r\n\t " + @"rla.exe --d ""D:\temp\"" --out c:\temp" + "\r\n"; _fluentCommandLineParser.SetupHelp("?", "help").WithHeader(header) .Callback(text => _logger.Info(text + "\r\n" + footer)); var result = _fluentCommandLineParser.Parse(args); if (_fluentCommandLineParser.Object.HiveFile.IsNullOrEmpty() == false || _fluentCommandLineParser.Object.Directory.IsNullOrEmpty() == false) { if (_fluentCommandLineParser.Object.OutDirectory.IsNullOrEmpty()) { _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options); Console.WriteLine(); _logger.Warn($"--out is required. Exiting"); Console.WriteLine(); return; } } if (_fluentCommandLineParser.Object.Debug) { foreach (var r in LogManager.Configuration.LoggingRules) { r.EnableLoggingForLevel(LogLevel.Debug); } LogManager.ReconfigExistingLoggers(); _logger.Debug("Enabled debug messages..."); } if (_fluentCommandLineParser.Object.Trace) { foreach (var r in LogManager.Configuration.LoggingRules) { r.EnableLoggingForLevel(LogLevel.Trace); } LogManager.ReconfigExistingLoggers(); _logger.Trace("Enabled trace messages..."); } if (result.HelpCalled) { return; } if (result.HasErrors) { _logger.Error(""); _logger.Error(result.ErrorText); _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options); return; } var hivesToProcess = new List <string>(); _logger.Info(header); _logger.Info(""); _logger.Info($"Command line: {string.Join(" ", Environment.GetCommandLineArgs().Skip(1))}\r\n"); if (_fluentCommandLineParser.Object.HiveFile?.Length > 0) { if (File.Exists(_fluentCommandLineParser.Object.HiveFile) == false) { _logger.Error($"File '{_fluentCommandLineParser.Object.HiveFile}' does not exist."); return; } hivesToProcess.Add(_fluentCommandLineParser.Object.HiveFile); } else if (_fluentCommandLineParser.Object.Directory?.Length > 0) { if (Directory.Exists(_fluentCommandLineParser.Object.Directory) == false) { _logger.Error($"Directory '{_fluentCommandLineParser.Object.Directory}' does not exist."); return; } var okFileParts = new HashSet <string>(); okFileParts.Add("USRCLASS"); okFileParts.Add("NTUSER"); okFileParts.Add("SYSTEM"); okFileParts.Add("SAM"); okFileParts.Add("SOFTWARE"); okFileParts.Add("AMCACHE"); okFileParts.Add("SYSCACHE"); okFileParts.Add("SECURITY"); okFileParts.Add("DRIVERS"); okFileParts.Add("COMPONENTS"); var f = new DirectoryEnumerationFilters(); f.InclusionFilter = fsei => { if (fsei.Extension.ToUpperInvariant() == ".LOG1" || fsei.Extension.ToUpperInvariant() == ".LOG2" || fsei.Extension.ToUpperInvariant() == ".DLL" || fsei.Extension.ToUpperInvariant() == ".LOG" || fsei.Extension.ToUpperInvariant() == ".CSV" || fsei.Extension.ToUpperInvariant() == ".BLF" || fsei.Extension.ToUpperInvariant() == ".REGTRANS-MS" || fsei.Extension.ToUpperInvariant() == ".EXE" || fsei.Extension.ToUpperInvariant() == ".TXT" || fsei.Extension.ToUpperInvariant() == ".INI") { return(false); } var foundOkFilePart = false; foreach (var okFilePart in okFileParts) { if (fsei.FileName.ToUpperInvariant().Contains(okFilePart)) { foundOkFilePart = true; // return true; } } if (foundOkFilePart == false) { return(false); } var fi = new FileInfo(fsei.FullPath); if (fi.Length < 4) { return(false); } try { using (var fs = new FileStream(fsei.FullPath, FileMode.Open, FileAccess.Read)) { using (var br = new BinaryReader(fs, new ASCIIEncoding())) { try { var chunk = br.ReadBytes(4); var sig = BitConverter.ToInt32(chunk, 0); if (sig == 0x66676572) { return(true); } } catch (Exception) { } return(false); } } } catch (IOException) { if (Helper.IsAdministrator() == false) { throw new UnauthorizedAccessException("Administrator privileges not found!"); } var files = new List <string>(); files.Add(fsei.FullPath); var rawf = Helper.GetFiles(files); if (rawf.First().FileStream.Length == 0) { return(false); } try { var b = new byte[4]; rawf.First().FileStream.ReadExactly(b, 4); var sig = BitConverter.ToInt32(b, 0); if (sig == 0x66676572) { return(true); } } catch (Exception) { } return(false); } }; f.RecursionFilter = entryInfo => !entryInfo.IsMountPoint && !entryInfo.IsSymbolicLink; f.ErrorFilter = (errorCode, errorMessage, pathProcessed) => true; var dirEnumOptions = DirectoryEnumerationOptions.Files | DirectoryEnumerationOptions.Recursive | DirectoryEnumerationOptions.SkipReparsePoints | DirectoryEnumerationOptions.ContinueOnException | DirectoryEnumerationOptions.BasicSearch; if (Directory.Exists(_fluentCommandLineParser.Object.OutDirectory) == false) { _logger.Info($"Creating --out directory '{_fluentCommandLineParser.Object.OutDirectory}'..."); Directory.CreateDirectory(_fluentCommandLineParser.Object.OutDirectory); } else { if (Directory.GetFiles(_fluentCommandLineParser.Object.OutDirectory).Length > 0 && _fluentCommandLineParser.Object.CompressNames) { _logger.Warn($"'{_fluentCommandLineParser.Object.OutDirectory}' contains files! This may cause --cn to revert back to uncompressed names. Ideally, '{_fluentCommandLineParser.Object.OutDirectory}' should be empty."); Console.WriteLine(); } } _logger.Fatal($"Searching '{_fluentCommandLineParser.Object.Directory}' for hives..."); var files2 = Directory.EnumerateFileSystemEntries(_fluentCommandLineParser.Object.Directory, dirEnumOptions, f); var count = 0; try { hivesToProcess.AddRange(files2); count = hivesToProcess.Count; _logger.Info($"\tHives found: {count:N0}"); } catch (Exception ex) { _logger.Fatal($"Could not access all files in '{_fluentCommandLineParser.Object.Directory}'! Error: {ex.Message}"); _logger.Error(""); _logger.Fatal("Rerun the program with Administrator privileges to try again\r\n"); //Environment.Exit(-1); } } else { _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options); return; } if (hivesToProcess.Count == 0) { _logger.Warn("No hives were found. Exiting..."); return; } _sw = new Stopwatch(); _sw.Start(); foreach (var hiveToProcess in hivesToProcess) { _logger.Info(""); byte[] updatedBytes = null; _logger.Info($"Processing hive '{hiveToProcess}'"); if (File.Exists(hiveToProcess) == false) { _logger.Warn($"'{hiveToProcess}' does not exist. Skipping"); continue; } try { RegistryHive reg; var dirname = Path.GetDirectoryName(hiveToProcess); var hiveBase = Path.GetFileName(hiveToProcess); List <RawCopyReturn> rawFiles = null; try { using (var fs = new FileStream(hiveToProcess, FileMode.Open, FileAccess.Read)) { reg = new RegistryHive(fs.ReadFully(), hiveToProcess) { }; } } catch (IOException) { //file is in use if (Helper.IsAdministrator() == false) { throw new UnauthorizedAccessException("Administrator privileges not found!"); } _logger.Warn($"\t'{hiveToProcess}' is in use. Rerouting...\r\n"); var files = new List <string>(); files.Add(hiveToProcess); var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?"); foreach (var logFile in logFiles) { files.Add(logFile); } rawFiles = Helper.GetFiles(files); if (rawFiles.First().FileStream.Length == 0) { continue; } var bb = rawFiles.First().FileStream.ReadFully(); reg = new RegistryHive(bb, rawFiles.First().InputFilename); } if (reg.Header.PrimarySequenceNumber != reg.Header.SecondarySequenceNumber) { if (string.IsNullOrEmpty(dirname)) { dirname = "."; } var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?"); if (logFiles.Length == 0) { if (_fluentCommandLineParser.Object.CopyAlways) { _logger.Info($"\tHive '{hiveToProcess}' is dirty, but no logs were found in the same directory. --ca is true. Copying..."); updatedBytes = File.ReadAllBytes(hiveToProcess); } else { _logger.Info($"\tHive '{hiveToProcess}' is dirty and no transaction logs were found in the same directory. --ca is false. Skipping..."); continue; } } if (updatedBytes == null) { if (rawFiles != null) { var lt = new List <TransactionLogFileInfo>(); foreach (var rawCopyReturn in rawFiles.Skip(1).ToList()) { var bb1 = rawCopyReturn.FileStream.ReadFully(); var tt = new TransactionLogFileInfo(rawCopyReturn.InputFilename, bb1); lt.Add(tt); } updatedBytes = reg.ProcessTransactionLogs(lt); } else { updatedBytes = reg.ProcessTransactionLogs(logFiles.ToList()); } } } if (updatedBytes == null) { if (_fluentCommandLineParser.Object.CopyAlways) { _logger.Info($"\tHive '{hiveToProcess}' is not dirty, but --ca is true. Copying..."); updatedBytes = File.ReadAllBytes(hiveToProcess); } else { _logger.Info($"\tHive '{hiveToProcess}' is not dirty and --ca is false. Skipping..."); continue; } } var outFile = hiveToProcess.Replace(":", "").Replace("\\", "_"); var outFileAll = Path.Combine(_fluentCommandLineParser.Object.OutDirectory, outFile); if (_fluentCommandLineParser.Object.CompressNames && (outFileAll.ToUpperInvariant().Contains("NTUSER") || outFileAll.ToUpperInvariant().Contains("USRCLASS"))) { var dl = hiveToProcess[0].ToString(); var segs = hiveToProcess.SplitAndTrim('\\'); var profile = segs[2]; var filename = Path.GetFileName(hiveToProcess); var outFile2 = $"{dl}_{profile}_{filename}"; outFileAll = Path.Combine(_fluentCommandLineParser.Object.OutDirectory, outFile2); } if (File.Exists(outFileAll)) { var oldOut = outFileAll; outFileAll = Path.Combine(_fluentCommandLineParser.Object.OutDirectory, outFile); _logger.Warn($"\tFile '{oldOut}' exists! Saving as non-compressed name: '{outFileAll}'"); } _logger.Fatal($"\tSaving updated hive to '{outFileAll}'"); using (var fs = new FileStream(outFileAll, FileMode.Create)) { fs.Write(updatedBytes, 0, updatedBytes.Length); fs.Flush(); fs.Close(); } } catch (Exception ex) { if (ex.Message.Contains("Sequence numbers do not match and transaction") == false) { if (ex.Message.Contains("Administrator privileges not found")) { _logger.Fatal($"Could not access '{hiveToProcess}' because it is in use"); _logger.Error(""); _logger.Fatal("Rerun the program with Administrator privileges to try again\r\n"); } else { _logger.Error($"There was an error: {ex.Message}"); } } } } _sw.Stop(); _logger.Info(""); _logger.Info($"Total processing time: {_sw.Elapsed.TotalSeconds:N3} seconds"); _logger.Info(""); }