示例#1
0
        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);
        }
示例#2
0
        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}");
                        }
                    }
                }
            }
        }
示例#3
0
        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);
            }
        }
示例#4
0
        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}");
                    }
                }
            }
        }
示例#5
0
    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("");
    }
示例#6
0
        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("");
        }