Exemplo n.º 1
0
    private static async Task Main(string[] args)
    {
        ExceptionlessClient.Default.Startup("tYeWS6A5K5uItgpB44dnNy2qSb2xJxiQWRRGWebq");

        _rootCommand = new RootCommand
        {
            new Option <string>(
                "-f",
                "File to process. This or -d is required"),

            new Option <string>(
                "-d",
                "Directory to process that contains evtx files. This or -f is required"),

            new Option <string>(
                "--csv",
                "Directory to save CSV formatted results to"),

            new Option <string>(
                "--csvf",
                "File name to save CSV formatted results to. When present, overrides default name"),

            new Option <string>(
                "--json",
                "Directory to save JSON formatted results to"),

            new Option <string>(
                "--jsonf",
                "File name to save JSON formatted results to. When present, overrides default name"),

            new Option <string>(
                "--xml",
                "Directory to save XML formatted results to"),

            new Option <string>(
                "--xmlf",
                "File name to save XML formatted results to. When present, overrides default name"),

            new Option <string>(
                "--dt",
                getDefaultValue: () => "yyyy-MM-dd HH:mm:ss.fffffff",
                "The custom date/time format to use when displaying time stamps"),

            new Option <string>(
                "--inc",
                "List of Event IDs to process. All others are ignored. Overrides --exc Format is 4624,4625,5410"),

            new Option <string>(
                "--exc",
                "List of Event IDs to IGNORE. All others are included. Format is 4624,4625,5410"),

            new Option <string>(
                "--sd",
                "Start date for including events (UTC). Anything OLDER than this is dropped. Format should match --dt"),

            new Option <string>(
                "--ed",
                "End date for including events (UTC). Anything NEWER than this is dropped. Format should match --dt"),

            new Option <bool>(
                "--fj",
                () => false,
                "When true, export all available data when using --json"),

            new Option <int>(
                "--tdt", () => 1,
                "The number of seconds to use for time discrepancy detection"),

            new Option <bool>(
                "--met",
                () => true,
                "When true, show metrics about processed event log"),

            new Option <string>(
                "--maps",
                () => Path.Combine(BaseDirectory, "Maps"),
                "The path where event maps are located. Defaults to 'Maps' folder where program was executed"),

            new Option <bool>(
                "--vss",
                () => false,
                "Process all Volume Shadow Copies that exist on drive specified by -f or -d"),

            new Option <bool>(
                "--dedupe",
                () => true,
                "Deduplicate -f or -d & VSCs based on SHA-1. First file found wins"),

            new Option <bool>(
                "--sync",
                () => false,
                "If true, the latest maps from https://github.com/EricZimmerman/evtx/tree/master/evtx/Maps are downloaded and local maps updated"),

            new Option <bool>(
                "--debug",
                () => false,
                "Show debug information during processing"),

            new Option <bool>(
                "--trace",
                () => false,
                "Show trace information during processing")
        };


        _rootCommand.Description = Header + "\r\n\r\n" + Footer;

        _rootCommand.Handler = CommandHandler.Create(DoWork);

        await _rootCommand.InvokeAsync(args);
    }
Exemplo n.º 2
0
        private static void Main(string[] args)
        {
            ExceptionlessClient.Default.Startup("tYeWS6A5K5uItgpB44dnNy2qSb2xJxiQWRRGWebq");

            SetupNLog();

            _logger = LogManager.GetLogger("EvtxECmd");

            _fluentCommandLineParser = new FluentCommandLineParser <ApplicationArguments>
            {
                IsCaseSensitive = false
            };

            _fluentCommandLineParser.Setup(arg => arg.File)
            .As('f')
            .WithDescription("File to process. This or -d is required");
            _fluentCommandLineParser.Setup(arg => arg.Directory)
            .As('d')
            .WithDescription("Directory to process that contains evtx files. This or -f is required\r\n");

            _fluentCommandLineParser.Setup(arg => arg.JsonDirectory)
            .As("json")
            .WithDescription(
                "Directory to save JSON formatted results to. This or --csv required");
            _fluentCommandLineParser.Setup(arg => arg.JsonName)
            .As("jsonf")
            .WithDescription(
                "File name to save JSON formatted results to. When present, overrides default name");

            _fluentCommandLineParser.Setup(arg => arg.CsvDirectory)
            .As("csv")
            .WithDescription(
                "Directory to save CSV formatted results to. This or --json required");

            _fluentCommandLineParser.Setup(arg => arg.CsvName)
            .As("csvf")
            .WithDescription(
                "File name to save CSV formatted results to. When present, overrides default name\r\n");

            _fluentCommandLineParser.Setup(arg => arg.DateTimeFormat)
            .As("dt")
            .WithDescription(
                "The custom date/time format to use when displaying time stamps. Default is: yyyy-MM-dd HH:mm:ss.fffffff")
            .SetDefault("yyyy-MM-dd HH:mm:ss.fffffff");

            _fluentCommandLineParser.Setup(arg => arg.ShowXml)
            .As('x')
            .WithDescription(
                "When true, show XML payload for event records. Default is FALSE.")
            .SetDefault(false);

            _fluentCommandLineParser.Setup(arg => arg.MapsDirectory)
            .As("maps")
            .WithDescription(
                "The path where event maps are located. Defaults to 'Maps' folder where program was executed from.")
            .SetDefault(Path.Combine(BaseDirectory, "Maps"));

            _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\r\n").SetDefault(false);

            var header =
                $"EvtxECmd version {Assembly.GetExecutingAssembly().GetName().Version}" +
                "\r\n\r\nAuthor: Eric Zimmerman ([email protected])" +
                "\r\nhttps://github.com/EricZimmerman/evtx";

            var footer =
                @"Examples: EvtxECmd.exe -f ""C:\Temp\Application.evtx"" --csv ""c:\temp\out"" --csvf MyOutputFile.csv" +
                "\r\n\t " +
                @" EvtxECmd.exe -f ""C:\Temp\Application.evtx"" --csv ""c:\temp\out""" + "\r\n\t " +
                @" EvtxECmd.exe -f ""C:\Temp\Application.evtx"" --json ""c:\temp\jsonout""" + "\r\n\t " +
                "\r\n\t" +
                "  Short options (single letter) are prefixed with a single dash. Long commands are prefixed with two dashes\r\n";

            _fluentCommandLineParser.SetupHelp("?", "help")
            .WithHeader(header)
            .Callback(text => _logger.Info(text + "\r\n" + footer));

            var result = _fluentCommandLineParser.Parse(args);

            if (result.HelpCalled)
            {
                return;
            }

            if (result.HasErrors)
            {
                _logger.Error("");
                _logger.Error(result.ErrorText);

                _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options);

                return;
            }

            if (_fluentCommandLineParser.Object.File.IsNullOrEmpty() &&
                _fluentCommandLineParser.Object.Directory.IsNullOrEmpty())
            {
                _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options);

                _logger.Warn("-f or -d is required. Exiting");
                return;
            }

            _logger.Info(header);
            _logger.Info("");
            _logger.Info($"Command line: {string.Join(" ", Environment.GetCommandLineArgs().Skip(1))}\r\n");

            if (IsAdministrator() == false)
            {
                _logger.Fatal("Warning: Administrator privileges not found!\r\n");
            }

            if (_fluentCommandLineParser.Object.Debug)
            {
                LogManager.Configuration.LoggingRules.First().EnableLoggingForLevel(LogLevel.Debug);
            }

            if (_fluentCommandLineParser.Object.Trace)
            {
                LogManager.Configuration.LoggingRules.First().EnableLoggingForLevel(LogLevel.Trace);
            }

            LogManager.ReconfigExistingLoggers();

            var sw = new Stopwatch();

            sw.Start();

            _errorFiles = new Dictionary <string, int>();

            if (_fluentCommandLineParser.Object.CsvDirectory.IsNullOrEmpty() == false)
            {
                if (Directory.Exists(_fluentCommandLineParser.Object.CsvDirectory) == false)
                {
                    _logger.Warn(
                        $"Path to '{_fluentCommandLineParser.Object.CsvDirectory}' doesn't exist. Creating...");

                    try
                    {
                        Directory.CreateDirectory(_fluentCommandLineParser.Object.CsvDirectory);
                    }
                    catch (Exception)
                    {
                        _logger.Fatal(
                            $"Unable to create directory '{_fluentCommandLineParser.Object.CsvDirectory}'. Does a file with the same name exist? Exiting");
                        return;
                    }
                }

                var outName = $"{DateTimeOffset.UtcNow:yyyyMMddHHmmss}_EvtxECmd_Output.csv";

                if (_fluentCommandLineParser.Object.CsvName.IsNullOrEmpty() == false)
                {
                    outName = Path.GetFileName(_fluentCommandLineParser.Object.CsvName);
                }

                var outFile = Path.Combine(_fluentCommandLineParser.Object.CsvDirectory, outName);

                _logger.Warn($"CSV output will be saved to '{outFile}'\r\n");

                _swCsv = new StreamWriter(outFile, false, Encoding.UTF8);

                _csvWriter = new CsvWriter(_swCsv);

                var foo = _csvWriter.Configuration.AutoMap <EventRecord>();

                foo.Map(t => t.PayloadXml).Ignore();
                foo.Map(t => t.RecordPosition).Ignore();
                foo.Map(t => t.Size).Ignore();
                foo.Map(t => t.Timestamp).Ignore();


                foo.Map(t => t.RecordNumber).Index(0);
                foo.Map(t => t.TimeCreated).Index(1);
                foo.Map(t => t.EventId).Index(2);
                foo.Map(t => t.Level).Index(3);
                foo.Map(t => t.Provider).Index(4);
                foo.Map(t => t.Channel).Index(5);
                foo.Map(t => t.ProcessId).Index(6);
                foo.Map(t => t.ThreadId).Index(7);
                foo.Map(t => t.Computer).Index(8);
                foo.Map(t => t.UserId).Index(9);
                foo.Map(t => t.UserName).Index(10);
                foo.Map(t => t.RemoteHost).Index(11);
                foo.Map(t => t.PayloadData1).Index(12);
                foo.Map(t => t.PayloadData2).Index(13);
                foo.Map(t => t.PayloadData3).Index(14);
                foo.Map(t => t.PayloadData4).Index(15);
                foo.Map(t => t.PayloadData5).Index(16);
                foo.Map(t => t.PayloadData6).Index(17);
                foo.Map(t => t.ExecutableInfo).Index(18);
                foo.Map(t => t.SourceFile).Index(19);

                _csvWriter.Configuration.RegisterClassMap(foo);
                _csvWriter.WriteHeader <EventRecord>();
                _csvWriter.NextRecord();
            }

            if (Directory.Exists(_fluentCommandLineParser.Object.MapsDirectory) == false)
            {
                _logger.Warn($"Maps directory '{_fluentCommandLineParser.Object.MapsDirectory}' does not exist! Event ID maps will not be loaded!!");
            }
            else
            {
                _logger.Debug($"Loading maps from '{Path.GetFullPath(_fluentCommandLineParser.Object.MapsDirectory)}'");
                EventLog.LoadMaps(Path.GetFullPath(_fluentCommandLineParser.Object.MapsDirectory));

                _logger.Info($"Maps loaded: {EventLog.EventLogMaps.Count:N0}");
            }


            if (_fluentCommandLineParser.Object.File.IsNullOrEmpty() == false)
            {
                if (File.Exists(_fluentCommandLineParser.Object.File) == false)
                {
                    _logger.Warn($"'{_fluentCommandLineParser.Object.File}' does not exist! Exiting");
                    return;
                }

                ProcessFile(_fluentCommandLineParser.Object.File);
            }
            else
            {
                _logger.Info($"Looking for event log files in '{_fluentCommandLineParser.Object.Directory}'");
                _logger.Info("");

                var f = new DirectoryEnumerationFilters();
                f.InclusionFilter = fsei => fsei.Extension.ToUpperInvariant() == ".EVTX";

                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;

                var files2 =
                    Directory.EnumerateFileSystemEntries(_fluentCommandLineParser.Object.Directory, dirEnumOptions, f);

                foreach (var file in files2)
                {
                    ProcessFile(file);
                }
            }

            _swCsv?.Flush();
            _swCsv?.Close();

            sw.Stop();
            _logger.Info("");

            var suff = string.Empty;

            if (_fileCount != 1)
            {
                suff = "s";
            }

            _logger.Error(
                $"Processed {_fileCount:N0} file{suff} in {sw.Elapsed.TotalSeconds:N4} seconds\r\n");

            if (_errorFiles.Count > 0)
            {
                _logger.Info("");
                _logger.Error("Files with errors");
                foreach (var errorFile in _errorFiles)
                {
                    _logger.Info($"'{errorFile.Key}' error count: {errorFile.Value:N0}");
                }
                _logger.Info("");
            }
        }
Exemplo n.º 3
0
        private void DumpGetFinalPathNameByHandle(bool isLocal)
        {
            Console.WriteLine("\n=== TEST {0} ===", isLocal ? UnitTestConstants.Local : UnitTestConstants.Network);

            var tempFile = Path.GetTempFileName();

            if (!isLocal)
            {
                tempFile = Path.LocalToUnc(tempFile);
            }

            var  longTempStream = Path.LongPathPrefix + tempFile;
            bool gotFileNameNormalized;
            bool gotFileNameOpened;
            bool gotVolumeNameDos;
            bool gotVolumeNameGuid;
            bool gotVolumeNameNt;
            bool gotVolumeNameNone;
            bool gotSomething;

            using (var stream = File.Create(tempFile))
            {
                // For Windows versions < Vista, the file must be > 0 bytes.
                if (!NativeMethods.IsAtLeastWindowsVista)
                {
                    stream.WriteByte(1);
                }

                var handle = stream.SafeFileHandle;

                UnitTestConstants.StopWatcher(true);
                var fileNameNormalized = Path.GetFinalPathNameByHandle(handle);
                var fileNameOpened     = Path.GetFinalPathNameByHandle(handle, FinalPathFormats.FileNameOpened);

                var volumeNameDos  = Path.GetFinalPathNameByHandle(handle, FinalPathFormats.None);
                var volumeNameGuid = Path.GetFinalPathNameByHandle(handle, FinalPathFormats.VolumeNameGuid);
                var volumeNameNt   = Path.GetFinalPathNameByHandle(handle, FinalPathFormats.VolumeNameNT);
                var volumeNameNone = Path.GetFinalPathNameByHandle(handle, FinalPathFormats.VolumeNameNone);

                // These three output the same.
                gotFileNameNormalized = !Utils.IsNullOrWhiteSpace(fileNameNormalized) && longTempStream.Equals(fileNameNormalized);
                gotFileNameOpened     = !Utils.IsNullOrWhiteSpace(fileNameOpened) && longTempStream.Equals(fileNameOpened);
                gotVolumeNameDos      = !Utils.IsNullOrWhiteSpace(volumeNameDos) && longTempStream.Equals(volumeNameDos);

                gotVolumeNameGuid = !Utils.IsNullOrWhiteSpace(volumeNameGuid) && volumeNameGuid.StartsWith(Path.VolumePrefix) && volumeNameGuid.EndsWith(volumeNameNone);
                gotVolumeNameNt   = !Utils.IsNullOrWhiteSpace(volumeNameNt) && volumeNameNt.StartsWith(Path.DevicePrefix);
                gotVolumeNameNone = !Utils.IsNullOrWhiteSpace(volumeNameNone) && tempFile.EndsWith(volumeNameNone);

                Console.WriteLine("\nInput Path: [{0}]", tempFile);
                Console.WriteLine("\n\tFilestream.Name  : [{0}]", stream.Name);
                Console.WriteLine("\tFilestream.Length: [{0}] (Note: For Windows versions < Vista, the file must be > 0 bytes.)\n", Utils.UnitSizeToText(stream.Length));

                Console.WriteLine("\tFinalPathFormats.None          : [{0}]", fileNameNormalized);
                Console.WriteLine("\tFinalPathFormats.FileNameOpened: [{0}]", fileNameOpened);
                Console.WriteLine("\tFinalPathFormats.VolumeNameDos : [{0}]", volumeNameDos);
                Console.WriteLine("\tFinalPathFormats.VolumeNameGuid: [{0}]", volumeNameGuid);
                Console.WriteLine("\tFinalPathFormats.VolumeNameNT  : [{0}]", volumeNameNt);
                Console.WriteLine("\tFinalPathFormats.VolumeNameNone: [{0}]", volumeNameNone);

                Console.WriteLine("\n{0}", UnitTestConstants.Reporter(true));

                gotSomething = true;
            }


            var fileExists = File.Exists(tempFile);

            File.Delete(tempFile, true);
            Assert.IsFalse(File.Exists(tempFile), "Cleanup failed: File should have been removed.");

            Assert.IsTrue(fileExists);
            Assert.IsTrue(gotFileNameNormalized);
            Assert.IsTrue(gotFileNameOpened);
            Assert.IsTrue(gotVolumeNameDos);
            Assert.IsTrue(gotVolumeNameGuid);
            Assert.IsTrue(gotVolumeNameNt);
            Assert.IsTrue(gotVolumeNameNone);
            Assert.IsTrue(gotSomething);



            // AlphaFS implementation of fileStream.Name returns = "[Unknown]"
            // System.IO returns the full path.
            Console.WriteLine();
            var fileName = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%") + "foo.bar");

            var fileStream2 = System.IO.File.Create(fileName);

            Assert.AreEqual(fileStream2.Name, fileName);
            fileStream2.Close();
            File.Delete(fileName);

            var fileStream     = File.Create(fileName);
            var fileStreamName = Path.GetFinalPathNameByHandle(fileStream.SafeFileHandle);

            Assert.AreNotEqual(fileName, fileStream.Name);
            Assert.AreEqual(fileName, Path.GetRegularPath(fileStreamName));

            fileStream.Close();
            File.Delete(fileName);
        }
Exemplo n.º 4
0
        private async Task InstallArchive(WorkQueue queue, Archive archive, string absolutePath, IGrouping <string, FromArchive> grouping)
        {
            Status($"Extracting {archive.Name}");

            List <FromArchive> vFiles = grouping.Select(g =>
            {
                var file   = VFS.Index.FileForArchiveHashPath(g.ArchiveHashPath);
                g.FromFile = file;
                return(g);
            }).ToList();

            var onFinish = await VFS.Stage(vFiles.Select(f => f.FromFile).Distinct());


            Status($"Copying files for {archive.Name}");

            void CopyFile(string from, string to, bool useMove)
            {
                if (File.Exists(to))
                {
                    var fi = new FileInfo(to);
                    if (fi.IsReadOnly)
                    {
                        fi.IsReadOnly = false;
                    }
                    File.Delete(to);
                }

                if (File.Exists(from))
                {
                    var fi = new FileInfo(from);
                    if (fi.IsReadOnly)
                    {
                        fi.IsReadOnly = false;
                    }
                }


                if (useMove)
                {
                    File.Move(from, to);
                }
                else
                {
                    File.Copy(from, to);
                }
                // If we don't do this, the file will use the last-modified date of the file when it was compressed
                // into an archive, which isn't really what we want in the case of files installed archives
                File.SetLastWriteTime(to, DateTime.Now);
            }

            await vFiles.GroupBy(f => f.FromFile)
            .PDoIndexed(queue, (idx, group) =>
            {
                Utils.Status("Installing files", Percent.FactoryPutInRange(idx, vFiles.Count));
                var firstDest = Path.Combine(OutputFolder, group.First().To);
                CopyFile(group.Key.StagedPath, firstDest, true);

                foreach (var copy in group.Skip(1))
                {
                    var nextDest = Path.Combine(OutputFolder, copy.To);
                    CopyFile(firstDest, nextDest, false);
                }
            });

            Status("Unstaging files");
            onFinish();

            // Now patch all the files from this archive
            foreach (var toPatch in grouping.OfType <PatchedFromArchive>())
            {
                using (var patchStream = new MemoryStream())
                {
                    Status($"Patching {Path.GetFileName(toPatch.To)}");
                    // Read in the patch data

                    byte[] patchData = LoadBytesFromPath(toPatch.PatchID);

                    var toFile  = Path.Combine(OutputFolder, toPatch.To);
                    var oldData = new MemoryStream(File.ReadAllBytes(toFile));

                    // Remove the file we're about to patch
                    File.Delete(toFile);

                    // Patch it
                    using (var outStream = File.Open(toFile, FileMode.Create))
                    {
                        BSDiff.Apply(oldData, () => new MemoryStream(patchData), outStream);
                    }

                    Status($"Verifying Patch {Path.GetFileName(toPatch.To)}");
                    var resultSha = toFile.FileHash();
                    if (resultSha != toPatch.Hash)
                    {
                        throw new InvalidDataException($"Invalid Hash for {toPatch.To} after patching");
                    }
                }
            }
        }
Exemplo n.º 5
0
 public TestUtils()
 {
     RNG = new Random();
     ID  = RandomName();
     WorkingDirectory = Path.Combine(Directory.GetCurrentDirectory(), "tmp_data");
 }
Exemplo n.º 6
0
    private static void DoWork(string d, string f, bool q, string csv, string csvf, string dt, bool debug, bool trace)
    {
        ActiveDateTimeFormat = dt;

        var formatter =
            new DateTimeOffsetFormatter(CultureInfo.CurrentCulture);

        var levelSwitch = new LoggingLevelSwitch();

        var template = "{Message:lj}{NewLine}{Exception}";

        if (debug)
        {
            levelSwitch.MinimumLevel = LogEventLevel.Debug;
            template = "[{Timestamp:HH:mm:ss.fff} {Level:u3}] {Message:lj}{NewLine}{Exception}";
        }

        if (trace)
        {
            levelSwitch.MinimumLevel = LogEventLevel.Verbose;
            template = "[{Timestamp:HH:mm:ss.fff} {Level:u3}] {Message:lj}{NewLine}{Exception}";
        }

        var conf = new LoggerConfiguration()
                   .WriteTo.Console(outputTemplate: template, formatProvider: formatter)
                   .MinimumLevel.ControlledBy(levelSwitch);

        Log.Logger = conf.CreateLogger();

        if (f.IsNullOrEmpty() &&
            d.IsNullOrEmpty())
        {
            var helpBld = new HelpBuilder(LocalizationResources.Instance, Console.WindowWidth);
            var hc      = new HelpContext(helpBld, _rootCommand, Console.Out);

            helpBld.Write(hc);

            Log.Warning("Either -f or -d is required. Exiting");
            return;
        }

        if (f.IsNullOrEmpty() == false &&
            !File.Exists(f))
        {
            Log.Warning("File {F} not found. Exiting", f);
            return;
        }

        if (d.IsNullOrEmpty() == false &&
            !Directory.Exists(d))
        {
            Log.Warning("Directory {D} not found. Exiting", d);
            return;
        }

        Log.Information("{Header}", Header);
        Console.WriteLine();
        Log.Information("Command line: {Args}", string.Join(" ", Environment.GetCommandLineArgs().Skip(1)));

        if (IsAdministrator() == false)
        {
            Log.Warning("Warning: Administrator privileges not found!");
            Console.WriteLine();
        }

        _csvOuts     = new List <CsvOut>();
        _failedFiles = new List <string>();

        var files = new List <string>();

        var sw = new Stopwatch();

        sw.Start();

        if (f?.Length > 0)
        {
            files.Add(f);
        }
        else
        {
            Console.WriteLine();

            Log.Information("Looking for files in {Dir}", d);
            if (!q)
            {
                Console.WriteLine();
            }

            files = GetRecycleBinFiles(d);
        }

        Log.Information("Found {Count:N0} files. Processing...", files.Count);

        if (!q)
        {
            Console.WriteLine();
        }

        foreach (var file in files)
        {
            ProcessFile(file, q, dt);
        }

        sw.Stop();

        Console.WriteLine();
        Log.Information(
            "Processed {FailedFilesCount:N0} out of {Count:N0} files in {TotalSeconds:N4} seconds", files.Count - _failedFiles.Count, files.Count, sw.Elapsed.TotalSeconds);
        Console.WriteLine();

        if (_failedFiles.Count > 0)
        {
            Console.WriteLine();
            Log.Information("Failed files");
            foreach (var failedFile in _failedFiles)
            {
                Log.Information("  {FailedFile}", failedFile);
            }
        }

        if (csv.IsNullOrEmpty() == false && files.Count > 0)
        {
            if (Directory.Exists(csv) == false)
            {
                Log.Information("{Csv} does not exist. Creating...", csv);
                Directory.CreateDirectory(csv);
            }

            var outName = $"{DateTimeOffset.Now:yyyyMMddHHmmss}_RBCmd_Output.csv";

            if (csvf.IsNullOrEmpty() == false)
            {
                outName = Path.GetFileName(csvf);
            }


            var outFile = Path.Combine(csv, outName);

            outFile =
                Path.GetFullPath(outFile);

            Log.Warning("CSV output will be saved to {Path}", Path.GetFullPath(outFile));

            try
            {
                var sw1       = new StreamWriter(outFile);
                var csvWriter = new CsvWriter(sw1, CultureInfo.InvariantCulture);

                csvWriter.WriteHeader(typeof(CsvOut));
                csvWriter.NextRecord();

                foreach (var csvOut in _csvOuts)
                {
                    csvWriter.WriteRecord(csvOut);
                    csvWriter.NextRecord();
                }

                sw1.Flush();
                sw1.Close();
            }
            catch (Exception ex)
            {
                Log.Error(ex,
                          "Unable to open {OutFile} for writing. CSV export canceled. Error: {Message}", outFile, ex.Message);
            }
        }
    }
Exemplo n.º 7
0
        private static void Main(string[] args)
        {
            ExceptionlessClient.Default.Startup("tYeWS6A5K5uItgpB44dnNy2qSb2xJxiQWRRGWebq");

            SetupNLog();

            _logger = LogManager.GetLogger("EvtxECmd");

            _fluentCommandLineParser = new FluentCommandLineParser <ApplicationArguments>
            {
                IsCaseSensitive = false
            };

            _fluentCommandLineParser.Setup(arg => arg.File)
            .As('f')
            .WithDescription("File to process. This or -d is required\r\n");
            _fluentCommandLineParser.Setup(arg => arg.Directory)
            .As('d')
            .WithDescription("Directory to process that contains evtx files. This or -f is required");

            _fluentCommandLineParser.Setup(arg => arg.CsvDirectory)
            .As("csv")
            .WithDescription(
                "Directory to save CSV formatted results to.");     // This, --json, or --xml required

            _fluentCommandLineParser.Setup(arg => arg.CsvName)
            .As("csvf")
            .WithDescription(
                "File name to save CSV formatted results to. When present, overrides default name");

            _fluentCommandLineParser.Setup(arg => arg.JsonDirectory)
            .As("json")
            .WithDescription(
                "Directory to save JSON formatted results to.");     // This, --csv, or --xml required
            _fluentCommandLineParser.Setup(arg => arg.JsonName)
            .As("jsonf")
            .WithDescription(
                "File name to save JSON formatted results to. When present, overrides default name");

            _fluentCommandLineParser.Setup(arg => arg.XmlDirectory)
            .As("xml")
            .WithDescription(
                "Directory to save XML formatted results to.");     // This, --csv, or --json required

            _fluentCommandLineParser.Setup(arg => arg.XmlName)
            .As("xmlf")
            .WithDescription(
                "File name to save XML formatted results to. When present, overrides default name\r\n");

            _fluentCommandLineParser.Setup(arg => arg.DateTimeFormat)
            .As("dt")
            .WithDescription(
                "The custom date/time format to use when displaying time stamps. Default is: yyyy-MM-dd HH:mm:ss.fffffff")
            .SetDefault("yyyy-MM-dd HH:mm:ss.fffffff");

            _fluentCommandLineParser.Setup(arg => arg.IncludeIds)
            .As("inc")
            .WithDescription(
                "List of Event IDs to process. All others are ignored. Overrides --exc Format is 4624,4625,5410")
            .SetDefault(string.Empty);

            _fluentCommandLineParser.Setup(arg => arg.ExcludeIds)
            .As("exc")
            .WithDescription(
                "List of Event IDs to IGNORE. All others are included. Format is 4624,4625,5410")
            .SetDefault(string.Empty);

            _fluentCommandLineParser.Setup(arg => arg.StartDate)
            .As("sd")
            .WithDescription(
                "Start date for including events (UTC). Anything OLDER than this is dropped. Format should match --dt")
            .SetDefault(string.Empty);

            _fluentCommandLineParser.Setup(arg => arg.EndDate)
            .As("ed")
            .WithDescription(
                "End date for including events (UTC). Anything NEWER than this is dropped. Format should match --dt")
            .SetDefault(string.Empty);

            _fluentCommandLineParser.Setup(arg => arg.FullJson)
            .As("fj")
            .WithDescription(
                "When true, export all available data when using --json. Default is FALSE.")
            .SetDefault(false);
            _fluentCommandLineParser.Setup(arg => arg.PayloadAsJson)
            .As("pj")
            .WithDescription(
                "When true, include event *payload* as json. Default is TRUE.")
            .SetDefault(true);

            _fluentCommandLineParser.Setup(arg => arg.TimeDiscrepancyThreshold)
            .As("tdt")
            .WithDescription(
                "The number of seconds to use for time discrepancy detection. Default is 1 second")
            .SetDefault(1);

            _fluentCommandLineParser.Setup(arg => arg.Metrics)
            .As("met")
            .WithDescription(
                "When true, show metrics about processed event log. Default is TRUE.\r\n")
            .SetDefault(true);

            _fluentCommandLineParser.Setup(arg => arg.MapsDirectory)
            .As("maps")
            .WithDescription(
                "The path where event maps are located. Defaults to 'Maps' folder where program was executed\r\n  ")
            .SetDefault(Path.Combine(BaseDirectory, "Maps"));

            _fluentCommandLineParser.Setup(arg => arg.Vss)
            .As("vss")
            .WithDescription(
                "Process all Volume Shadow Copies that exist on drive specified by -f or -d . Default is FALSE")
            .SetDefault(false);
            _fluentCommandLineParser.Setup(arg => arg.Dedupe)
            .As("dedupe")
            .WithDescription(
                "Deduplicate -f or -d & VSCs based on SHA-1. First file found wins. Default is TRUE\r\n")
            .SetDefault(true);

            _fluentCommandLineParser.Setup(arg => arg.Sync)
            .As("sync")
            .WithDescription(
                "If true, the latest maps from https://github.com/EricZimmerman/evtx/tree/master/evtx/Maps are downloaded and local maps updated. Default is FALSE\r\n")
            .SetDefault(false);

            _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\r\n").SetDefault(false);

            var header =
                $"EvtxECmd version {Assembly.GetExecutingAssembly().GetName().Version}" +
                "\r\n\r\nAuthor: Eric Zimmerman ([email protected])" +
                "\r\nhttps://github.com/EricZimmerman/evtx";

            var footer =
                @"Examples: EvtxECmd.exe -f ""C:\Temp\Application.evtx"" --csv ""c:\temp\out"" --csvf MyOutputFile.csv" +
                "\r\n\t " +
                @" EvtxECmd.exe -f ""C:\Temp\Application.evtx"" --csv ""c:\temp\out""" + "\r\n\t " +
                @" EvtxECmd.exe -f ""C:\Temp\Application.evtx"" --json ""c:\temp\jsonout""" + "\r\n\t " +
                "\r\n\t" +
                "  Short options (single letter) are prefixed with a single dash. Long commands are prefixed with two dashes\r\n";

            _fluentCommandLineParser.SetupHelp("?", "help")
            .WithHeader(header)
            .Callback(text => _logger.Info(text + "\r\n" + footer));

            var result = _fluentCommandLineParser.Parse(args);

            if (result.HelpCalled)
            {
                return;
            }

            if (result.HasErrors)
            {
                _logger.Error("");
                _logger.Error(result.ErrorText);

                _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options);

                return;
            }

            if (_fluentCommandLineParser.Object.Sync)
            {
                try
                {
                    _logger.Info(header);
                    UpdateFromRepo();
                }
                catch (Exception e)
                {
                    _logger.Error(e, $"There was an error checking for updates: {e.Message}");
                }

                Environment.Exit(0);
            }

            if (_fluentCommandLineParser.Object.File.IsNullOrEmpty() &&
                _fluentCommandLineParser.Object.Directory.IsNullOrEmpty())
            {
                _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options);

                _logger.Warn("-f or -d is required. Exiting");
                return;
            }

            _logger.Info(header);
            _logger.Info("");
            _logger.Info($"Command line: {string.Join(" ", Environment.GetCommandLineArgs().Skip(1))}\r\n");



            if (IsAdministrator() == false)
            {
                _logger.Fatal("Warning: Administrator privileges not found!\r\n");
            }

            if (_fluentCommandLineParser.Object.Debug)
            {
                LogManager.Configuration.LoggingRules.First().EnableLoggingForLevel(LogLevel.Debug);
            }

            if (_fluentCommandLineParser.Object.Trace)
            {
                LogManager.Configuration.LoggingRules.First().EnableLoggingForLevel(LogLevel.Trace);
            }

            LogManager.ReconfigExistingLoggers();

            if (_fluentCommandLineParser.Object.Vss & (IsAdministrator() == false))
            {
                _logger.Error("--vss is present, but administrator rights not found. Exiting\r\n");
                return;
            }

            var sw = new Stopwatch();

            sw.Start();

            var ts = DateTimeOffset.UtcNow;

            _errorFiles = new Dictionary <string, int>();

            if (_fluentCommandLineParser.Object.JsonDirectory.IsNullOrEmpty() == false)
            {
                if (Directory.Exists(_fluentCommandLineParser.Object.JsonDirectory) == false)
                {
                    _logger.Warn(
                        $"Path to '{_fluentCommandLineParser.Object.JsonDirectory}' doesn't exist. Creating...");

                    try
                    {
                        Directory.CreateDirectory(_fluentCommandLineParser.Object.JsonDirectory);
                    }
                    catch (Exception)
                    {
                        _logger.Fatal(
                            $"Unable to create directory '{_fluentCommandLineParser.Object.JsonDirectory}'. Does a file with the same name exist? Exiting");
                        return;
                    }
                }

                var outName = $"{ts:yyyyMMddHHmmss}_EvtxECmd_Output.json";

                if (_fluentCommandLineParser.Object.JsonName.IsNullOrEmpty() == false)
                {
                    outName = Path.GetFileName(_fluentCommandLineParser.Object.JsonName);
                }

                var outFile = Path.Combine(_fluentCommandLineParser.Object.JsonDirectory, outName);

                _logger.Warn($"json output will be saved to '{outFile}'\r\n");

                try
                {
                    _swJson = new StreamWriter(outFile, false, Encoding.UTF8);
                }
                catch (Exception)
                {
                    _logger.Error($"Unable to open '{outFile}'! Is it in use? Exiting!\r\n");
                    Environment.Exit(0);
                }

                JsConfig.DateHandler = DateHandler.ISO8601;
            }

            if (_fluentCommandLineParser.Object.XmlDirectory.IsNullOrEmpty() == false)
            {
                if (Directory.Exists(_fluentCommandLineParser.Object.XmlDirectory) == false)
                {
                    _logger.Warn(
                        $"Path to '{_fluentCommandLineParser.Object.XmlDirectory}' doesn't exist. Creating...");

                    try
                    {
                        Directory.CreateDirectory(_fluentCommandLineParser.Object.XmlDirectory);
                    }
                    catch (Exception)
                    {
                        _logger.Fatal(
                            $"Unable to create directory '{_fluentCommandLineParser.Object.XmlDirectory}'. Does a file with the same name exist? Exiting");
                        return;
                    }
                }

                var outName = $"{ts:yyyyMMddHHmmss}_EvtxECmd_Output.xml";

                if (_fluentCommandLineParser.Object.XmlName.IsNullOrEmpty() == false)
                {
                    outName = Path.GetFileName(_fluentCommandLineParser.Object.XmlName);
                }

                var outFile = Path.Combine(_fluentCommandLineParser.Object.XmlDirectory, outName);

                _logger.Warn($"XML output will be saved to '{outFile}'\r\n");

                try
                {
                    _swXml = new StreamWriter(outFile, false, Encoding.UTF8);
                }
                catch (Exception)
                {
                    _logger.Error($"Unable to open '{outFile}'! Is it in use? Exiting!\r\n");
                    Environment.Exit(0);
                }
            }

            if (_fluentCommandLineParser.Object.StartDate.IsNullOrEmpty() == false)
            {
                if (DateTimeOffset.TryParse(_fluentCommandLineParser.Object.StartDate, null, DateTimeStyles.AssumeUniversal, out var dt))
                {
                    _startDate = dt;
                    _logger.Info($"Setting Start date to '{_startDate.Value.ToUniversalTime().ToString(_fluentCommandLineParser.Object.DateTimeFormat)}'");
                }
                else
                {
                    _logger.Warn($"Could not parse '{_fluentCommandLineParser.Object.StartDate}' to a valud datetime! Events will not be filtered by Start date!");
                }
            }
            if (_fluentCommandLineParser.Object.EndDate.IsNullOrEmpty() == false)
            {
                if (DateTimeOffset.TryParse(_fluentCommandLineParser.Object.EndDate, null, DateTimeStyles.AssumeUniversal, out var dt))
                {
                    _endDate = dt;
                    _logger.Info($"Setting End date to '{_endDate.Value.ToUniversalTime().ToString(_fluentCommandLineParser.Object.DateTimeFormat)}'");
                }
                else
                {
                    _logger.Warn($"Could not parse '{_fluentCommandLineParser.Object.EndDate}' to a valud datetime! Events will not be filtered by End date!");
                }
            }

            if (_startDate.HasValue || _endDate.HasValue)
            {
                _logger.Info("");
            }


            if (_fluentCommandLineParser.Object.CsvDirectory.IsNullOrEmpty() == false)
            {
                if (Directory.Exists(_fluentCommandLineParser.Object.CsvDirectory) == false)
                {
                    _logger.Warn(
                        $"Path to '{_fluentCommandLineParser.Object.CsvDirectory}' doesn't exist. Creating...");

                    try
                    {
                        Directory.CreateDirectory(_fluentCommandLineParser.Object.CsvDirectory);
                    }
                    catch (Exception)
                    {
                        _logger.Fatal(
                            $"Unable to create directory '{_fluentCommandLineParser.Object.CsvDirectory}'. Does a file with the same name exist? Exiting");
                        return;
                    }
                }

                var outName = $"{ts:yyyyMMddHHmmss}_EvtxECmd_Output.csv";

                if (_fluentCommandLineParser.Object.CsvName.IsNullOrEmpty() == false)
                {
                    outName = Path.GetFileName(_fluentCommandLineParser.Object.CsvName);
                }

                var outFile = Path.Combine(_fluentCommandLineParser.Object.CsvDirectory, outName);

                _logger.Warn($"CSV output will be saved to '{outFile}'\r\n");

                try
                {
                    _swCsv = new StreamWriter(outFile, false, Encoding.UTF8);

                    _csvWriter = new CsvWriter(_swCsv, CultureInfo.InvariantCulture);
                }
                catch (Exception)
                {
                    _logger.Error($"Unable to open '{outFile}'! Is it in use? Exiting!\r\n");
                    Environment.Exit(0);
                }

                var foo = _csvWriter.Configuration.AutoMap <EventRecord>();

                if (_fluentCommandLineParser.Object.PayloadAsJson == false)
                {
                    foo.Map(t => t.Payload).Ignore();
                }
                else
                {
                    foo.Map(t => t.Payload).Index(22);
                }

                foo.Map(t => t.RecordPosition).Ignore();
                foo.Map(t => t.Size).Ignore();
                foo.Map(t => t.Timestamp).Ignore();

                foo.Map(t => t.RecordNumber).Index(0);
                foo.Map(t => t.EventRecordId).Index(1);
                foo.Map(t => t.TimeCreated).Index(2);
                foo.Map(t => t.TimeCreated).ConvertUsing(t =>
                                                         $"{t.TimeCreated.ToString(_fluentCommandLineParser.Object.DateTimeFormat)}");
                foo.Map(t => t.EventId).Index(3);
                foo.Map(t => t.Level).Index(4);
                foo.Map(t => t.Provider).Index(5);
                foo.Map(t => t.Channel).Index(6);
                foo.Map(t => t.ProcessId).Index(7);
                foo.Map(t => t.ThreadId).Index(8);
                foo.Map(t => t.Computer).Index(9);
                foo.Map(t => t.UserId).Index(10);
                foo.Map(t => t.MapDescription).Index(11);
                foo.Map(t => t.UserName).Index(12);
                foo.Map(t => t.RemoteHost).Index(13);
                foo.Map(t => t.PayloadData1).Index(14);
                foo.Map(t => t.PayloadData2).Index(15);
                foo.Map(t => t.PayloadData3).Index(16);
                foo.Map(t => t.PayloadData4).Index(17);
                foo.Map(t => t.PayloadData5).Index(18);
                foo.Map(t => t.PayloadData6).Index(19);
                foo.Map(t => t.ExecutableInfo).Index(20);
                foo.Map(t => t.HiddenRecord).Index(21);
                foo.Map(t => t.SourceFile).Index(22);
                foo.Map(t => t.Keywords).Index(23);

                _csvWriter.Configuration.RegisterClassMap(foo);
                _csvWriter.WriteHeader <EventRecord>();
                _csvWriter.NextRecord();
            }

            if (Directory.Exists(_fluentCommandLineParser.Object.MapsDirectory) == false)
            {
                _logger.Warn(
                    $"Maps directory '{_fluentCommandLineParser.Object.MapsDirectory}' does not exist! Event ID maps will not be loaded!!");
            }
            else
            {
                _logger.Debug($"Loading maps from '{Path.GetFullPath(_fluentCommandLineParser.Object.MapsDirectory)}'");
                var errors = EventLog.LoadMaps(Path.GetFullPath(_fluentCommandLineParser.Object.MapsDirectory));

                if (errors)
                {
                    return;
                }

                _logger.Info($"Maps loaded: {EventLog.EventLogMaps.Count:N0}");
            }

            _includeIds = new HashSet <int>();
            _excludeIds = new HashSet <int>();

            if (_fluentCommandLineParser.Object.ExcludeIds.IsNullOrEmpty() == false)
            {
                var excSegs = _fluentCommandLineParser.Object.ExcludeIds.Split(',');

                foreach (var incSeg in excSegs)
                {
                    if (int.TryParse(incSeg, out var goodId))
                    {
                        _excludeIds.Add(goodId);
                    }
                }
            }

            if (_fluentCommandLineParser.Object.IncludeIds.IsNullOrEmpty() == false)
            {
                _excludeIds.Clear();
                var incSegs = _fluentCommandLineParser.Object.IncludeIds.Split(',');

                foreach (var incSeg in incSegs)
                {
                    if (int.TryParse(incSeg, out var goodId))
                    {
                        _includeIds.Add(goodId);
                    }
                }
            }

            if (_fluentCommandLineParser.Object.Vss)
            {
                string driveLetter;
                if (_fluentCommandLineParser.Object.File.IsEmpty() == false)
                {
                    driveLetter = Path.GetPathRoot(Path.GetFullPath(_fluentCommandLineParser.Object.File))
                                  .Substring(0, 1);
                }
                else
                {
                    driveLetter = Path.GetPathRoot(Path.GetFullPath(_fluentCommandLineParser.Object.Directory))
                                  .Substring(0, 1);
                }


                Helper.MountVss(driveLetter, VssDir);
                Console.WriteLine();
            }

            EventLog.TimeDiscrepancyThreshold = _fluentCommandLineParser.Object.TimeDiscrepancyThreshold;

            if (_fluentCommandLineParser.Object.File.IsNullOrEmpty() == false)
            {
                if (File.Exists(_fluentCommandLineParser.Object.File) == false)
                {
                    _logger.Warn($"'{_fluentCommandLineParser.Object.File}' does not exist! Exiting");
                    return;
                }

                if (_swXml == null && _swJson == null && _swCsv == null)
                {
                    //no need for maps
                    _logger.Debug("Clearing map collection since no output specified");
                    EventLog.EventLogMaps.Clear();
                }

                _fluentCommandLineParser.Object.Dedupe = false;

                ProcessFile(Path.GetFullPath(_fluentCommandLineParser.Object.File));

                if (_fluentCommandLineParser.Object.Vss)
                {
                    var vssDirs = Directory.GetDirectories(VssDir);

                    var root = Path.GetPathRoot(Path.GetFullPath(_fluentCommandLineParser.Object.File));
                    var stem = Path.GetFullPath(_fluentCommandLineParser.Object.File).Replace(root, "");

                    foreach (var vssDir in vssDirs)
                    {
                        var newPath = Path.Combine(vssDir, stem);
                        if (File.Exists(newPath))
                        {
                            ProcessFile(newPath);
                        }
                    }
                }
            }
            else
            {
                _logger.Info($"Looking for event log files in '{_fluentCommandLineParser.Object.Directory}'");
                _logger.Info("");

                var f = new DirectoryEnumerationFilters
                {
                    InclusionFilter = fsei => fsei.Extension.ToUpperInvariant() == ".EVTX",
                    RecursionFilter = entryInfo => !entryInfo.IsMountPoint && !entryInfo.IsSymbolicLink,
                    ErrorFilter     = (errorCode, errorMessage, pathProcessed) => true
                };

                var dirEnumOptions =
                    DirectoryEnumerationOptions.Files | DirectoryEnumerationOptions.Recursive |
                    DirectoryEnumerationOptions.SkipReparsePoints | DirectoryEnumerationOptions.ContinueOnException |
                    DirectoryEnumerationOptions.BasicSearch;

                var files2 =
                    Directory.EnumerateFileSystemEntries(Path.GetFullPath(_fluentCommandLineParser.Object.Directory), dirEnumOptions, f);

                if (_swXml == null && _swJson == null && _swCsv == null)
                {
                    //no need for maps
                    _logger.Debug("Clearing map collection since no output specified");
                    EventLog.EventLogMaps.Clear();
                }

                foreach (var file in files2)
                {
                    ProcessFile(file);
                }

                if (_fluentCommandLineParser.Object.Vss)
                {
                    var vssDirs = Directory.GetDirectories(VssDir);

                    Console.WriteLine();

                    foreach (var vssDir in vssDirs)
                    {
                        var root = Path.GetPathRoot(Path.GetFullPath(_fluentCommandLineParser.Object.Directory));
                        var stem = Path.GetFullPath(_fluentCommandLineParser.Object.Directory).Replace(root, "");

                        var target = Path.Combine(vssDir, stem);

                        _logger.Fatal($"\r\nSearching 'VSS{target.Replace($"{VssDir}\\","")}' for event logs...");

                        var vssFiles = Helper.GetFilesFromPath(target, true, "*.evtx");

                        foreach (var file in vssFiles)
                        {
                            ProcessFile(file);
                        }
                    }
                }
            }

            try
            {
                _swCsv?.Flush();
                _swCsv?.Close();

                _swJson?.Flush();
                _swJson?.Close();

                _swXml?.Flush();
                _swXml?.Close();
            }
            catch (Exception e)
            {
                _logger.Error($"Error when flushing output files to disk! Error message: {e.Message}");
            }


            sw.Stop();
            _logger.Info("");

            var suff = string.Empty;

            if (_fileCount != 1)
            {
                suff = "s";
            }

            _logger.Error(
                $"Processed {_fileCount:N0} file{suff} in {sw.Elapsed.TotalSeconds:N4} seconds\r\n");

            if (_errorFiles.Count > 0)
            {
                _logger.Info("");
                _logger.Error("Files with errors");
                foreach (var errorFile in _errorFiles)
                {
                    _logger.Info($"'{errorFile.Key}' error count: {errorFile.Value:N0}");
                }

                _logger.Info("");
            }

            if (_fluentCommandLineParser.Object.Vss)
            {
                if (Directory.Exists(VssDir))
                {
                    foreach (var directory in Directory.GetDirectories(VssDir))
                    {
                        Directory.Delete(directory);
                    }
                    Directory.Delete(VssDir, true, true);
                }
            }
        }
Exemplo n.º 8
0
        private static void Main(string[] args)
        {
            ExceptionlessClient.Default.Startup("IudF6lFjzvdMldPtlYyPmSMHnSEL89n2WmYbCHoy");

            SetupNLog();

            _logger = LogManager.GetCurrentClassLogger();

            _fluentCommandLineParser = new FluentCommandLineParser <ApplicationArguments>
            {
                IsCaseSensitive = false
            };

            _fluentCommandLineParser.Setup(arg => arg.File)
            .As('f')
            .WithDescription("File to process. Either this or -d is required");

            _fluentCommandLineParser.Setup(arg => arg.Directory)
            .As('d')
            .WithDescription("Directory to recursively process. Either this or -f is required");

            _fluentCommandLineParser.Setup(arg => arg.CsvDirectory)
            .As("csv")
            .WithDescription(
                "Directory to save CSV formatted results to. Be sure to include the full path in double quotes");

            _fluentCommandLineParser.Setup(arg => arg.CsvName)
            .As("csvf")
            .WithDescription("File name to save CSV formatted results to. When present, overrides default name\r\n");


            _fluentCommandLineParser.Setup(arg => arg.Quiet)
            .As('q')
            .WithDescription(
                "Only show the filename being processed vs all output. Useful to speed up exporting to json and/or csv\r\n")
            .SetDefault(false);

            _fluentCommandLineParser.Setup(arg => arg.DateTimeFormat)
            .As("dt")
            .WithDescription(
                "The custom date/time format to use when displaying time stamps. See https://goo.gl/CNVq0k for options. Default is: yyyy-MM-dd HH:mm:ss\r\n")
            .SetDefault(_preciseTimeFormat);

            _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\r\n").SetDefault(false);

            var header =
                $"RBCmd version {Assembly.GetExecutingAssembly().GetName().Version}" +
                "\r\n\r\nAuthor: Eric Zimmerman ([email protected])" +
                "\r\nhttps://github.com/EricZimmerman/RBCmd";


            var footer = @"Examples: RBCmd.exe -f ""C:\Temp\INFO2""" + "\r\n\t " +
                         @" RBCmd.exe -f ""C:\Temp\$I3VPA17"" --csv ""D:\csvOutput"" " + "\r\n\t " +
                         @" RBCmd.exe -d ""C:\Temp"" --csv ""c:\temp"" " + "\r\n\t " +
                         "\r\n\t" +
                         "  Short options (single letter) are prefixed with a single dash. Long commands are prefixed with two dashes\r\n";

            _fluentCommandLineParser.SetupHelp("?", "help")
            .WithHeader(header)
            .Callback(text => _logger.Info(text + "\r\n" + footer));

            var result = _fluentCommandLineParser.Parse(args);

            if (result.HelpCalled)
            {
                return;
            }

            if (result.HasErrors)
            {
                _logger.Error("");
                _logger.Error(result.ErrorText);

                _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options);

                return;
            }

            if (_fluentCommandLineParser.Object.File.IsNullOrEmpty() &&
                _fluentCommandLineParser.Object.Directory.IsNullOrEmpty())
            {
                _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options);

                _logger.Warn("Either -f or -d is required. Exiting");
                return;
            }

            if (_fluentCommandLineParser.Object.File.IsNullOrEmpty() == false &&
                !File.Exists(_fluentCommandLineParser.Object.File))
            {
                _logger.Warn($"File '{_fluentCommandLineParser.Object.File}' not found. Exiting");
                return;
            }

            if (_fluentCommandLineParser.Object.Directory.IsNullOrEmpty() == false &&
                !Directory.Exists(_fluentCommandLineParser.Object.Directory))
            {
                _logger.Warn($"Directory '{_fluentCommandLineParser.Object.Directory}' not found. Exiting");
                return;
            }

            _logger.Info(header);
            _logger.Info("");
            _logger.Info($"Command line: {string.Join(" ", Environment.GetCommandLineArgs().Skip(1))}\r\n");

            if (IsAdministrator() == false)
            {
                _logger.Fatal("Warning: Administrator privileges not found!\r\n");
            }

            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...");
            }

            _csvOuts     = new List <CsvOut>();
            _failedFiles = new List <string>();

            var files = new List <string>();

            var sw = new Stopwatch();

            sw.Start();

            if (_fluentCommandLineParser.Object.File?.Length > 0)
            {
                files.Add(_fluentCommandLineParser.Object.File);
            }
            else
            {
                if (_fluentCommandLineParser.Object.Quiet)
                {
                    _logger.Info("");
                }

                files = GetRecycleBinFiles(_fluentCommandLineParser.Object.Directory);
            }

            foreach (var file in files)
            {
                ProcessFile(file);
            }

            sw.Stop();

            _logger.Info(
                $"Processed {files.Count - _failedFiles.Count:N0} out of {files.Count:N0} files in {sw.Elapsed.TotalSeconds:N4} seconds\r\n");

            if (_failedFiles.Count > 0)
            {
                _logger.Info("");
                _logger.Warn("Failed files");
                foreach (var failedFile in _failedFiles)
                {
                    _logger.Info($"  {failedFile}");
                }
            }

            if (_fluentCommandLineParser.Object.CsvDirectory.IsNullOrEmpty() == false && files.Count > 0)
            {
                if (Directory.Exists(_fluentCommandLineParser.Object.CsvDirectory) == false)
                {
                    _logger.Warn($"'{_fluentCommandLineParser.Object.CsvDirectory} does not exist. Creating...'");
                    Directory.CreateDirectory(_fluentCommandLineParser.Object.CsvDirectory);
                }

                var outName = $"{DateTimeOffset.Now:yyyyMMddHHmmss}_RBCmd_Output.csv";

                if (_fluentCommandLineParser.Object.CsvName.IsNullOrEmpty() == false)
                {
                    outName = Path.GetFileName(_fluentCommandLineParser.Object.CsvName);
                }

                var outFile = Path.Combine(_fluentCommandLineParser.Object.CsvDirectory, outName);

                _fluentCommandLineParser.Object.CsvDirectory =
                    Path.GetFullPath(outFile);
                _logger.Warn(
                    $"CSV output will be saved to '{Path.GetFullPath(outFile)}'");

                try
                {
                    var sw1 = new StreamWriter(outFile);
                    var csv = new CsvWriter(sw1);

                    csv.WriteHeader(typeof(CsvOut));
                    csv.NextRecord();

                    foreach (var csvOut in _csvOuts)
                    {
                        csv.WriteRecord(csvOut);
                        csv.NextRecord();
                    }

                    sw1.Flush();
                    sw1.Close();
                }
                catch (Exception ex)
                {
                    _logger.Error(
                        $"Unable to open '{outFile}' for writing. CSV export canceled. Error: {ex.Message}");
                }
            }
        }
Exemplo n.º 9
0
 public string PathOfInstalledFile(string mod, string file)
 {
     return(Path.Combine(InstallFolder, "mods", mod, file));
 }
Exemplo n.º 10
0
        public static Func <RawSourceFile, Directive> IncludezEditPatches(Compiler compiler)
        {
            var zEditPath = FindzEditPath(compiler);
            var havezEdit = zEditPath != null;

            Utils.Log(havezEdit ? $"Found zEdit at {zEditPath}" : $"zEdit not detected, disabling zEdit routines");

            if (!havezEdit)
            {
                return source => { return null; }
            }
            ;

            var merges = Directory.EnumerateFiles(Path.Combine(zEditPath, "profiles"),
                                                  DirectoryEnumerationOptions.Files | DirectoryEnumerationOptions.Recursive)
                         .Where(f => f.EndsWith("\\merges.json"))
                         .SelectMany(f => f.FromJSON <List <zEditMerge> >())
                         .GroupBy(f => (f.name, f.filename));

            merges.Where(m => m.Count() > 1)
            .Do(m => {
                Utils.Warning(
                    $"WARNING, you have two patches named {m.Key.name}\\{m.Key.filename} in your zEdit profiles. We'll pick one at random, this probably isn't what you want.");
            });

            var mergesIndexed =
                merges.ToDictionary(
                    m => Path.Combine(compiler.MO2Folder, "mods", m.Key.name, m.Key.filename),
                    m => m.First());



            return(source =>
            {
                if (mergesIndexed.TryGetValue(source.AbsolutePath, out var merge))
                {
                    var result = source.EvolveTo <MergedPatch>();
                    result.Sources = merge.plugins.Select(f =>
                    {
                        var abs_path = Path.Combine(f.dataFolder, f.filename);
                        if (!File.Exists(abs_path))
                        {
                            throw new InvalidDataException(
                                $"File {abs_path} is required to build {merge.filename} but it doesn't exist");
                        }

                        return new SourcePatch
                        {
                            RelativePath = abs_path.RelativeTo(compiler.MO2Folder),
                            Hash = compiler.VFS[abs_path].Hash
                        };
                    }).ToList();

                    var src_data = merge.plugins.Select(f => File.ReadAllBytes(Path.Combine(f.dataFolder, f.filename)))
                                   .ConcatArrays();

                    var dst_data = File.ReadAllBytes(source.AbsolutePath);

                    using (var ms = new MemoryStream())
                    {
                        Utils.CreatePatch(src_data, dst_data, ms);
                        result.Patch = ms.ToArray();
                    }

                    return result;
                }
                return null;
            });
        }
Exemplo n.º 11
0
        public void SetVolumeMountPoint()
        {
            Console.WriteLine("Volume.SetVolumeMountPoint()\n");

            if (!IsAdmin())
            {
                Assert.Fail();
            }

            #region Logical Drives

            int    cnt        = 0;
            string destFolder = Path.Combine(TempFolder, "Volume.SetVolumeMountPoint()-" + Path.GetRandomFileName());
            Directory.CreateDirectory(destFolder);

            string guid = Volume.GetUniqueVolumeNameForPath(SysDrive);

            try
            {
                StopWatcher(true);

                Volume.SetVolumeMountPoint(destFolder, guid);
                Console.WriteLine(
                    "\t#{0:000}\tSystem Drive: [{1}]\tGUID: [{2}]\n\t\tDestination : [{3}]\n\t\tCreated Mount Point.\n\t{4}",
                    ++cnt, SysDrive, guid, destFolder, Reporter(true));

                Console.WriteLine("\n");
                EnumerateVolumeMountPoints();

                Console.WriteLine("\n\nFile.GetLinkTargetInfo()");

                LinkTargetInfo lti = File.GetLinkTargetInfo(destFolder);
                Assert.IsTrue(!string.IsNullOrWhiteSpace(lti.PrintName));
                Assert.IsTrue(!string.IsNullOrWhiteSpace(lti.SubstituteName));
                Assert.IsTrue(Dump(lti, -14), "Unable to dump object.");

                // Cleanup.
                StopWatcher(true);
                bool deleteOk = false;
                try
                {
                    Volume.DeleteVolumeMountPoint(destFolder);
                    deleteOk = true;
                }
                catch (Exception ex)
                {
                    Console.WriteLine("\nCaught Exception: [{0}]\n", ex.Message.Replace(Environment.NewLine, "  "));
                }

                Console.WriteLine("\n\nVolume.DeleteVolumeMountPoint() (Should be True): [{0}]\tFolder: [{1}]\n{2}\n",
                                  deleteOk, destFolder, Reporter());

                Directory.Delete(destFolder, true, true);
                Assert.IsTrue(deleteOk && !Directory.Exists(destFolder));

                EnumerateVolumeMountPoints();
            }
            catch (Exception ex)
            {
                Console.WriteLine("\nCaught Exception: [{0}]\n", ex.Message.Replace(Environment.NewLine, "  "));
                cnt = 0;
            }
            finally
            {
                // Always remove mount point.
                // Experienced: CCleaner deletes through mount points!
                try { Volume.DeleteVolumeMountPoint(destFolder); }
                catch { }
            }

            Assert.IsTrue(cnt > 0, "Nothing was enumerated.");

            #endregion // Logical Drives
        }
Exemplo n.º 12
0
 public string PathOfInstalledFile(string mod, string file)
 {
     return(Path.Combine(InstallFolder, Consts.MO2ModFolderName, mod, file));
 }
Exemplo n.º 13
0
    private static void UpdateFromRepo()
    {
        Console.WriteLine();

        Log.Information("Checking for updated maps at {Url}...", "https://github.com/EricZimmerman/evtx/tree/master/evtx/Maps");
        Console.WriteLine();
        var archivePath = Path.Combine(BaseDirectory, "____master.zip");

        if (File.Exists(archivePath))
        {
            File.Delete(archivePath);
        }
        // using (var client = new WebClient())
        // {
        //     ServicePointManager.Expect100Continue = true;
        //     ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
        //     client.DownloadFile("https://github.com/EricZimmerman/evtx/archive/master.zip", archivePath);
        // }

        "https://github.com/EricZimmerman/evtx/archive/master.zip".DownloadFileTo(archivePath);

        var fff = new FastZip();

        if (Directory.Exists(Path.Combine(BaseDirectory, "Maps")) == false)
        {
            Directory.CreateDirectory(Path.Combine(BaseDirectory, "Maps"));
        }

        var directoryFilter = "Maps";

        // Will prompt to overwrite if target file names already exist
        fff.ExtractZip(archivePath, BaseDirectory, FastZip.Overwrite.Always, null,
                       null, directoryFilter, true);

        if (File.Exists(archivePath))
        {
            File.Delete(archivePath);
        }

        var newMapPath = Path.Combine(BaseDirectory, "evtx-master", "evtx", "Maps");

        var orgMapPath = Path.Combine(BaseDirectory, "Maps");

        var newMaps = Directory.GetFiles(newMapPath);

        var newLocalMaps = new List <string>();

        var updatedLocalMaps = new List <string>();

        if (File.Exists(Path.Combine(orgMapPath, "Security_4624.map")))
        {
            Log.Warning("Old map format found. Zipping to {Old} and cleaning up old maps", "!!oldMaps.zip");
            //old maps found, so zip em first
            var oldZip = Path.Combine(orgMapPath, "!!oldMaps.zip");
            fff.CreateZip(oldZip, orgMapPath, false, @"\.map$");
            foreach (var m in Directory.GetFiles(orgMapPath, "*.map"))
            {
                File.Delete(m);
            }
        }

        if (File.Exists(Path.Combine(orgMapPath, "!!!!README.txt")))
        {
            File.Delete(Path.Combine(orgMapPath, "!!!!README.txt"));
        }

        foreach (var newMap in newMaps)
        {
            var mName = Path.GetFileName(newMap);
            var dest  = Path.Combine(orgMapPath, mName);

            if (File.Exists(dest) == false)
            {
                //new target
                newLocalMaps.Add(mName);
            }
            else
            {
                //current destination file exists, so compare to new

                var s1     = new StreamReader(newMap);
                var newSha = Helper.GetSha1FromStream(s1.BaseStream, 0);

                var s2 = new StreamReader(dest);

                var destSha = Helper.GetSha1FromStream(s2.BaseStream, 0);

                s2.Close();
                s1.Close();

                if (newSha != destSha)
                {
                    //updated file
                    updatedLocalMaps.Add(mName);
                }
            }

#if !NET6_0
            File.Copy(newMap, dest, CopyOptions.None);
#else
            File.Copy(newMap, dest, true);
#endif
        }

        if (newLocalMaps.Count > 0 || updatedLocalMaps.Count > 0)
        {
            Log.Information("Updates found!");
            Console.WriteLine();

            if (newLocalMaps.Count > 0)
            {
                Log.Information("New maps");
                foreach (var newLocalMap in newLocalMaps)
                {
                    Log.Information("{File}", Path.GetFileNameWithoutExtension(newLocalMap));
                }

                Console.WriteLine();
            }

            if (updatedLocalMaps.Count > 0)
            {
                Log.Information("Updated maps");
                foreach (var um in updatedLocalMaps)
                {
                    Log.Information("{File}", Path.GetFileNameWithoutExtension(um));
                }

                Console.WriteLine();
            }

            Console.WriteLine();
        }
        else
        {
            Console.WriteLine();
            Log.Information("No new maps available");
            Console.WriteLine();
        }

        Directory.Delete(Path.Combine(BaseDirectory, "evtx-master"), true);
    }
Exemplo n.º 14
0
    private static void DoWork(string f, string d, string csv, string csvf, string json, string jsonf, string xml, string xmlf, string dt, string inc, string exc, string sd, string ed, bool fj, int tdt, bool met, string maps, bool vss, bool dedupe, bool sync, bool debug, bool trace)
    {
        var levelSwitch = new LoggingLevelSwitch();

        _activeDateTimeFormat = dt;

        var formatter =
            new DateTimeOffsetFormatter(CultureInfo.CurrentCulture);

        var template = "{Message:lj}{NewLine}{Exception}";

        if (debug)
        {
            levelSwitch.MinimumLevel = LogEventLevel.Debug;
            template = "[{Timestamp:HH:mm:ss.fff} {Level:u3}] {Message:lj}{NewLine}{Exception}";
        }

        if (trace)
        {
            levelSwitch.MinimumLevel = LogEventLevel.Verbose;
            template = "[{Timestamp:HH:mm:ss.fff} {Level:u3}] {Message:lj}{NewLine}{Exception}";
        }

        var conf = new LoggerConfiguration()
                   .WriteTo.Console(outputTemplate: template, formatProvider: formatter)
                   .MinimumLevel.ControlledBy(levelSwitch);

        Log.Logger = conf.CreateLogger();

        if (sync)
        {
            try
            {
                Log.Information("{Header}", Header);
                UpdateFromRepo();
            }
            catch (Exception e)
            {
                Log.Error(e, "There was an error checking for updates: {Message}", e.Message);
            }

            Environment.Exit(0);
        }

        if (f.IsNullOrEmpty() &&
            d.IsNullOrEmpty())
        {
            var helpBld = new HelpBuilder(LocalizationResources.Instance, Console.WindowWidth);
            var hc      = new HelpContext(helpBld, _rootCommand, Console.Out);

            helpBld.Write(hc);

            Log.Warning("-f or -d is required. Exiting");
            Console.WriteLine();
            return;
        }

        Log.Information("{Header}", Header);
        Console.WriteLine();
        Log.Information("Command line: {Args}", string.Join(" ", Environment.GetCommandLineArgs().Skip(1)));
        Console.WriteLine();

        if (IsAdministrator() == false)
        {
            Log.Warning("Warning: Administrator privileges not found!");
            Console.WriteLine();
        }

        if (vss & !RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            vss = false;
            Log.Warning("{Vss} not supported on non-Windows platforms. Disabling...", "--vss");
            Console.WriteLine();
        }

        if (vss & (IsAdministrator() == false))
        {
            Log.Error("{Vss} is present, but administrator rights not found. Exiting", "--vss");
            Console.WriteLine();
            return;
        }

        var sw = new Stopwatch();

        sw.Start();

        var ts = DateTimeOffset.UtcNow;

        _errorFiles = new Dictionary <string, int>();

        if (json.IsNullOrEmpty() == false)
        {
            if (Directory.Exists(json) == false)
            {
                Log.Information("Path to {Json} doesn't exist. Creating...", json);

                try
                {
                    Directory.CreateDirectory(json);
                }
                catch (Exception ex)
                {
                    Log.Fatal(ex,
                              "Unable to create directory {Json}. Does a file with the same name exist? Exiting", json);
                    Console.WriteLine();
                    return;
                }
            }

            var outName = $"{ts:yyyyMMddHHmmss}_EvtxECmd_Output.json";

            if (jsonf.IsNullOrEmpty() == false)
            {
                outName = Path.GetFileName(jsonf);
            }

            var outFile = Path.Combine(json, outName);

            Log.Information("json output will be saved to {OutFile}", outFile);
            Console.WriteLine();

            try
            {
                _swJson = new StreamWriter(outFile, false, Encoding.UTF8);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Unable to open {OutFile}! Is it in use? Exiting!", outFile);
                Console.WriteLine();
                Environment.Exit(0);
            }

            JsConfig.DateHandler = DateHandler.ISO8601;
        }

        if (xml.IsNullOrEmpty() == false)
        {
            if (Directory.Exists(xml) == false)
            {
                Log.Information("Path to {Xml} doesn't exist. Creating...", xml);

                try
                {
                    Directory.CreateDirectory(xml);
                }
                catch (Exception ex)
                {
                    Log.Fatal(ex,
                              "Unable to create directory {Xml}. Does a file with the same name exist? Exiting", xml);
                    return;
                }
            }

            var outName = $"{ts:yyyyMMddHHmmss}_EvtxECmd_Output.xml";

            if (xmlf.IsNullOrEmpty() == false)
            {
                outName = Path.GetFileName(xmlf);
            }

            var outFile = Path.Combine(xml, outName);

            Log.Information("XML output will be saved to {OutFile}", outFile);
            Console.WriteLine();

            try
            {
                _swXml = new StreamWriter(outFile, false, Encoding.UTF8);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Unable to open {OutFile}! Is it in use? Exiting!", outFile);
                Console.WriteLine();
                Environment.Exit(0);
            }
        }

        if (sd.IsNullOrEmpty() == false)
        {
            if (DateTimeOffset.TryParse(sd, null, DateTimeStyles.AssumeUniversal, out var dateTimeOffset))
            {
                _startDate = dateTimeOffset;
                Log.Information("Setting Start date to {StartDate}", _startDate.Value);
            }
            else
            {
                Log.Warning("Could not parse {Sd} to a valid datetime! Events will not be filtered by Start date!", sd);
            }
        }

        if (ed.IsNullOrEmpty() == false)
        {
            if (DateTimeOffset.TryParse(ed, null, DateTimeStyles.AssumeUniversal, out var dateTimeOffset))
            {
                _endDate = dateTimeOffset;
                Log.Information("Setting End date to {EndDate}", _endDate.Value);
            }
            else
            {
                Log.Warning("Could not parse {Ed} to a valid datetime! Events will not be filtered by End date!", ed);
            }
        }

        if (_startDate.HasValue || _endDate.HasValue)
        {
            Console.WriteLine();
        }


        if (csv.IsNullOrEmpty() == false)
        {
            if (Directory.Exists(csv) == false)
            {
                Log.Information(
                    "Path to {Csv} doesn't exist. Creating...", csv);

                try
                {
                    Directory.CreateDirectory(csv);
                }
                catch (Exception ex)
                {
                    Log.Fatal(ex,
                              "Unable to create directory {Csv}. Does a file with the same name exist? Exiting", csv);
                    return;
                }
            }

            var outName = $"{ts:yyyyMMddHHmmss}_EvtxECmd_Output.csv";

            if (csvf.IsNullOrEmpty() == false)
            {
                outName = Path.GetFileName(csvf);
            }

            var outFile = Path.Combine(csv, outName);

            Log.Information("CSV output will be saved to {OutFile}", outFile);
            Console.WriteLine();

            try
            {
                _swCsv = new StreamWriter(outFile, false, Encoding.UTF8);

                var opt = new CsvConfiguration(CultureInfo.InvariantCulture)
                {
                    ShouldUseConstructorParameters = _ => false
                };

                _csvWriter = new CsvWriter(_swCsv, opt);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Unable to open {OutFile}! Is it in use? Exiting!", outFile);
                Console.WriteLine();
                Environment.Exit(0);
            }


            var foo = _csvWriter.Context.AutoMap <EventRecord>();

            foo.Map(t => t.RecordPosition).Ignore();
            foo.Map(t => t.Size).Ignore();
            foo.Map(t => t.Timestamp).Ignore();

            foo.Map(t => t.RecordNumber).Index(0);
            foo.Map(t => t.EventRecordId).Index(1);
            foo.Map(t => t.TimeCreated).Index(2);
            foo.Map(t => t.TimeCreated).Convert(t =>
                                                $"{t.Value.TimeCreated.ToString(dt)}");
            foo.Map(t => t.EventId).Index(3);
            foo.Map(t => t.Level).Index(4);
            foo.Map(t => t.Provider).Index(5);
            foo.Map(t => t.Channel).Index(6);
            foo.Map(t => t.ProcessId).Index(7);
            foo.Map(t => t.ThreadId).Index(8);
            foo.Map(t => t.Computer).Index(9);
            foo.Map(t => t.UserId).Index(10);
            foo.Map(t => t.MapDescription).Index(11);
            foo.Map(t => t.UserName).Index(12);
            foo.Map(t => t.RemoteHost).Index(13);
            foo.Map(t => t.PayloadData1).Index(14);
            foo.Map(t => t.PayloadData2).Index(15);
            foo.Map(t => t.PayloadData3).Index(16);
            foo.Map(t => t.PayloadData4).Index(17);
            foo.Map(t => t.PayloadData5).Index(18);
            foo.Map(t => t.PayloadData6).Index(19);
            foo.Map(t => t.ExecutableInfo).Index(20);
            foo.Map(t => t.HiddenRecord).Index(21);
            foo.Map(t => t.SourceFile).Index(22);
            foo.Map(t => t.Keywords).Index(23);
            foo.Map(t => t.Payload).Index(24);

            _csvWriter.Context.RegisterClassMap(foo);
            _csvWriter.WriteHeader <EventRecord>();
            _csvWriter.NextRecord();
        }

        if (Directory.Exists(maps) == false)
        {
            Log.Warning("Maps directory {Maps} does not exist! Event ID maps will not be loaded!!", maps);
        }
        else
        {
            Log.Debug("Loading maps from {Path}", Path.GetFullPath(maps));
            var errors = EventLog.LoadMaps(Path.GetFullPath(maps));

            if (errors)
            {
                return;
            }

            Log.Information("Maps loaded: {Count:N0}", EventLog.EventLogMaps.Count);
        }

        _includeIds = new HashSet <int>();
        _excludeIds = new HashSet <int>();

        if (exc.IsNullOrEmpty() == false)
        {
            var excSegs = exc.Split(',');

            foreach (var incSeg in excSegs)
            {
                if (int.TryParse(incSeg, out var goodId))
                {
                    _excludeIds.Add(goodId);
                }
            }
        }

        if (inc.IsNullOrEmpty() == false)
        {
            _excludeIds.Clear();
            var incSegs = inc.Split(',');

            foreach (var incSeg in incSegs)
            {
                if (int.TryParse(incSeg, out var goodId))
                {
                    _includeIds.Add(goodId);
                }
            }
        }

        if (vss)
        {
            string driveLetter;
            if (f.IsEmpty() == false)
            {
                driveLetter = Path.GetPathRoot(Path.GetFullPath(f))
                              .Substring(0, 1);
            }
            else
            {
                driveLetter = Path.GetPathRoot(Path.GetFullPath(d))
                              .Substring(0, 1);
            }


            Helper.MountVss(driveLetter, VssDir);
            Console.WriteLine();
        }

        EventLog.TimeDiscrepancyThreshold = tdt;

        if (f.IsNullOrEmpty() == false)
        {
            if (File.Exists(f) == false)
            {
                Log.Warning("\t{F} does not exist! Exiting", f);
                Console.WriteLine();
                return;
            }

            if (_swXml == null && _swJson == null && _swCsv == null)
            {
                //no need for maps
                Log.Debug("Clearing map collection since no output specified");
                EventLog.EventLogMaps.Clear();
            }

            dedupe = false;

            ProcessFile(Path.GetFullPath(f), dedupe, fj, met);

            if (vss)
            {
                var vssDirs = Directory.GetDirectories(VssDir);

                var root = Path.GetPathRoot(Path.GetFullPath(f));
                var stem = Path.GetFullPath(f).Replace(root, "");

                foreach (var vssDir in vssDirs)
                {
                    var newPath = Path.Combine(vssDir, stem);
                    if (File.Exists(newPath))
                    {
                        ProcessFile(newPath, dedupe, fj, met);
                    }
                }
            }
        }
        else
        {
            if (Directory.Exists(d) == false)
            {
                Log.Warning("\t{D} does not exist! Exiting", d);
                Console.WriteLine();
                return;
            }

            Log.Information("Looking for event log files in {D}", d);
            Console.WriteLine();

#if !NET6_0
            var directoryEnumerationFilters = new DirectoryEnumerationFilters
            {
                InclusionFilter = fsei => fsei.Extension.ToUpperInvariant() == ".EVTX",
                RecursionFilter = entryInfo => !entryInfo.IsMountPoint && !entryInfo.IsSymbolicLink,
                ErrorFilter     = (errorCode, errorMessage, pathProcessed) => true
            };

            var dirEnumOptions =
                DirectoryEnumerationOptions.Files | DirectoryEnumerationOptions.Recursive |
                DirectoryEnumerationOptions.SkipReparsePoints | DirectoryEnumerationOptions.ContinueOnException |
                DirectoryEnumerationOptions.BasicSearch;

            var files2 =
                Directory.EnumerateFileSystemEntries(Path.GetFullPath(d), dirEnumOptions, directoryEnumerationFilters);
#else
            var enumerationOptions = new EnumerationOptions
            {
                IgnoreInaccessible    = true,
                MatchCasing           = MatchCasing.CaseInsensitive,
                RecurseSubdirectories = true,
                AttributesToSkip      = 0
            };

            var files2 =
                Directory.EnumerateFileSystemEntries(d, "*.evtx", enumerationOptions);
#endif

            if (_swXml == null && _swJson == null && _swCsv == null)
            {
                //no need for maps
                Log.Debug("Clearing map collection since no output specified");
                EventLog.EventLogMaps.Clear();
            }

            foreach (var file in files2)
            {
                ProcessFile(file, dedupe, fj, met);
            }

            if (vss)
            {
                var vssDirs = Directory.GetDirectories(VssDir);

                Console.WriteLine();

                foreach (var vssDir in vssDirs)
                {
                    var root = Path.GetPathRoot(Path.GetFullPath(d));
                    var stem = Path.GetFullPath(d).Replace(root, "");

                    var target = Path.Combine(vssDir, stem);

                    Console.WriteLine();
                    Log.Information("Searching {Vss} for event logs...", $"VSS{target.Replace($"{VssDir}\\", "")}");

                    var vssFiles = Helper.GetFilesFromPath(target, "*.evtx", true);

                    foreach (var file in vssFiles)
                    {
                        ProcessFile(file, dedupe, fj, met);
                    }
                }
            }
        }

        try
        {
            _swCsv?.Flush();
            _swCsv?.Close();

            _swJson?.Flush();
            _swJson?.Close();

            _swXml?.Flush();
            _swXml?.Close();
        }
        catch (Exception e)
        {
            Log.Error(e, "Error when flushing output files to disk! Error message: {Message}", e.Message);
        }

        sw.Stop();
        Console.WriteLine();

        if (_fileCount == 1)
        {
            Log.Information("Processed {FileCount:N0} file in {TotalSeconds:N4} seconds", _fileCount, sw.Elapsed.TotalSeconds);
        }
        else
        {
            Log.Information("Processed {FileCount:N0} files in {TotalSeconds:N4} seconds", _fileCount, sw.Elapsed.TotalSeconds);
        }

        Console.WriteLine();

        if (_errorFiles.Count > 0)
        {
            Console.WriteLine();
            Log.Information("Files with errors");
            foreach (var errorFile in _errorFiles)
            {
                Log.Information("{Key} error count: {Value:N0}", errorFile.Key, errorFile.Value);
            }

            Console.WriteLine();
        }

        if (vss)
        {
            if (Directory.Exists(VssDir))
            {
                foreach (var directory in Directory.GetDirectories(VssDir))
                {
                    Directory.Delete(directory);
                }

#if !NET6_0
                Directory.Delete(VssDir, true, true);
#else
                Directory.Delete(VssDir, true);
#endif
            }
        }
    }
Exemplo n.º 15
0
        private static void Main(string[] args)
        {
            SetupNLog();

            _logger = LogManager.GetLogger("EvtxECmd");

            _fluentCommandLineParser = new FluentCommandLineParser <ApplicationArguments>
            {
                IsCaseSensitive = false
            };

            _fluentCommandLineParser.Setup(arg => arg.File)
            .As('f')
            .WithDescription("File to process. This or -d is required\r\n");
            _fluentCommandLineParser.Setup(arg => arg.Directory)
            .As('d')
            .WithDescription("Directory to process that contains evtx files. This or -f is required");

            _fluentCommandLineParser.Setup(arg => arg.CsvDirectory)
            .As("csv")
            .WithDescription(
                "Directory to save CSV formatted results to.");     // This, --json, or --xml required

            _fluentCommandLineParser.Setup(arg => arg.DateTimeFormat)
            .As("dt")
            .WithDescription(
                "The custom date/time format to use when displaying time stamps. Default is: yyyy-MM-dd HH:mm:ss.fffffff")
            .SetDefault("yyyy-MM-dd HH:mm:ss.fffffff");

            _fluentCommandLineParser.Setup(arg => arg.From)
            .As("from")
            .WithDescription(
                "The timestamp 'from' to include")
            .SetDefault("");

            _fluentCommandLineParser.Setup(arg => arg.To)
            .As("to")
            .WithDescription(
                "The timestamp up 'to' to include")
            .SetDefault("");

            _fluentCommandLineParser.Setup(arg => arg.IncludeIds)
            .As("inc")
            .WithDescription(
                "List of event IDs to process. All others are ignored. Overrides --exc Format is 4624,4625,5410")
            .SetDefault(string.Empty);

            _fluentCommandLineParser.Setup(arg => arg.ExcludeIds)
            .As("exc")
            .WithDescription(
                "List of event IDs to IGNORE. All others are included. Format is 4624,4625,5410")
            .SetDefault(string.Empty);

            _fluentCommandLineParser.Setup(arg => arg.Metrics)
            .As("met")
            .WithDescription(
                "When true, show metrics about processed event log. 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\r\n").SetDefault(false);

            var header =
                $"\r\nsimple-evtx version {Assembly.GetExecutingAssembly().GetName().Version}" +
                "\r\n\r\nAuthor: Eric Zimmerman ([email protected])" +
                "\r\nAuthor: Mark Woan ([email protected])" +
                "\r\n\r\nhttps://github.com/EricZimmerman/evtx" +
                "\r\nhttps://github.com/woanware/simple-evtx";

            var footer =
                @"Examples: simple-evtx.exe -f ""C:\Temp\Application.evtx"" --csv ""c:\temp\out""" +
                "\r\n\t" +
                "  Short options (single letter) are prefixed with a single dash. Long commands are prefixed with two dashes\r\n";

            _fluentCommandLineParser.SetupHelp("?", "help")
            .WithHeader(header)
            .Callback(text => _logger.Info(text + "\r\n" + footer));

            var result = _fluentCommandLineParser.Parse(args);

            if (result.HelpCalled)
            {
                return;
            }

            if (result.HasErrors)
            {
                _logger.Error("");
                _logger.Error(result.ErrorText);

                _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options);

                return;
            }

            if (_fluentCommandLineParser.Object.File.IsNullOrEmpty() &&
                _fluentCommandLineParser.Object.Directory.IsNullOrEmpty())
            {
                _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options);

                _logger.Warn("-f or -d is required. Exiting");
                return;
            }

            _logger.Info(header);
            _logger.Info("");
            _logger.Info($"Command line: {string.Join(" ", Environment.GetCommandLineArgs().Skip(1))}\r\n");

            if (IsAdministrator() == false)
            {
                _logger.Fatal("Warning: Administrator privileges not found!\r\n");
            }

            if (_fluentCommandLineParser.Object.Debug)
            {
                LogManager.Configuration.LoggingRules.First().EnableLoggingForLevel(LogLevel.Debug);
            }

            if (_fluentCommandLineParser.Object.Trace)
            {
                LogManager.Configuration.LoggingRules.First().EnableLoggingForLevel(LogLevel.Trace);
            }

            LogManager.ReconfigExistingLoggers();

            var sw = new Stopwatch();

            sw.Start();

            var ts = DateTimeOffset.UtcNow;

            _errorFiles = new Dictionary <string, int>();

            if (_fluentCommandLineParser.Object.CsvDirectory.IsNullOrEmpty() == false)
            {
                if (Directory.Exists(_fluentCommandLineParser.Object.CsvDirectory) == false)
                {
                    _logger.Warn(
                        $"Path to '{_fluentCommandLineParser.Object.CsvDirectory}' doesn't exist. Creating...");

                    try
                    {
                        Directory.CreateDirectory(_fluentCommandLineParser.Object.CsvDirectory);
                    }
                    catch (Exception)
                    {
                        _logger.Fatal(
                            $"Unable to create directory '{_fluentCommandLineParser.Object.CsvDirectory}'. Does a file with the same name exist? Exiting");
                        return;
                    }
                }

                var outName = $"{ts:yyyyMMddHHmmss}-simple-evtx.csv";

                if (_fluentCommandLineParser.Object.CsvName.IsNullOrEmpty() == false)
                {
                    outName = Path.GetFileName(_fluentCommandLineParser.Object.CsvName);
                }

                var outFile = Path.Combine(_fluentCommandLineParser.Object.CsvDirectory, outName);

                _logger.Warn($"CSV output will be saved to '{outFile}'\r\n");

                try
                {
                    _swCsv     = new StreamWriter(outFile, false, Encoding.UTF8);
                    _csvWriter = new CsvWriter(_swCsv);
                }
                catch (Exception)
                {
                    _logger.Error($"Unable to open '{outFile}'! Is it in use? Exiting!\r\n");
                    Environment.Exit(0);
                }

                var foo = _csvWriter.Configuration.AutoMap <EventRecord>();
                //foo.Map(t => t.RecordPosition).Ignore();
                // foo.Map(t => t.Size).Ignore();
                //  foo.Map(t => t.Timestamp).Ignore();
                foo.Map(t => t.TimeCreated).Index(1);
                foo.Map(t => t.TimeCreated).ConvertUsing(t =>
                                                         $"{t.TimeCreated.ToString(_fluentCommandLineParser.Object.DateTimeFormat)}");
                foo.Map(t => t.EventId).Index(2);
                foo.Map(t => t.Provider).Index(3);
                foo.Map(t => t.Channel).Index(4);
                foo.Map(t => t.Computer).Index(5);
                foo.Map(t => t.Payload).Index(6);
                foo.Map(t => t.SourceFile).Index(7);

                _csvWriter.Configuration.RegisterClassMap(foo);
                _csvWriter.WriteHeader <EventRecord>();
                _csvWriter.NextRecord();
            }

            _includeIds = new HashSet <int>();
            _excludeIds = new HashSet <int>();

            if (_fluentCommandLineParser.Object.From.IsNullOrEmpty() == false)
            {
                try
                {
                    _from = DateTime.ParseExact(_fluentCommandLineParser.Object.From, "yyyy/MM/dd HH:mm", CultureInfo.InvariantCulture);
                }
                catch (Exception)
                {
                    _logger.Error($"Invalid 'from' '{_fluentCommandLineParser.Object.From}' value! Exiting!\r\n");
                    Environment.Exit(0);
                }
            }

            if (_fluentCommandLineParser.Object.To.IsNullOrEmpty() == false)
            {
                try
                {
                    _to = DateTime.ParseExact(_fluentCommandLineParser.Object.To, "yyyy/MM/dd HH:mm", CultureInfo.InvariantCulture);
                }
                catch (Exception)
                {
                    _logger.Error($"Invalid 'to' '{_fluentCommandLineParser.Object.From}' value! Exiting!\r\n");
                }
            }

            if (_fluentCommandLineParser.Object.ExcludeIds.IsNullOrEmpty() == false)
            {
                var excSegs = _fluentCommandLineParser.Object.ExcludeIds.Split(',');

                foreach (var incSeg in excSegs)
                {
                    if (int.TryParse(incSeg, out var goodId))
                    {
                        _excludeIds.Add(goodId);
                    }
                }
            }

            if (_fluentCommandLineParser.Object.IncludeIds.IsNullOrEmpty() == false)
            {
                _excludeIds.Clear();
                var incSegs = _fluentCommandLineParser.Object.IncludeIds.Split(',');

                foreach (var incSeg in incSegs)
                {
                    if (int.TryParse(incSeg, out var goodId))
                    {
                        _includeIds.Add(goodId);
                    }
                }
            }

            if (_fluentCommandLineParser.Object.File.IsNullOrEmpty() == false)
            {
                if (File.Exists(_fluentCommandLineParser.Object.File) == false)
                {
                    _logger.Warn($"'{_fluentCommandLineParser.Object.File}' does not exist! Exiting");
                    return;
                }

                ProcessFile(_fluentCommandLineParser.Object.File);
            }
            else
            {
                _logger.Info($"Looking for event log files in '{_fluentCommandLineParser.Object.Directory}'");
                _logger.Info("");

                var f = new DirectoryEnumerationFilters();
                f.InclusionFilter = fsei => fsei.Extension.ToUpperInvariant() == ".EVTX";
                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;

                var files2 =
                    Directory.EnumerateFileSystemEntries(Path.GetFullPath(_fluentCommandLineParser.Object.Directory), dirEnumOptions, f);

                foreach (var file in files2)
                {
                    ProcessFile(file);
                }
            }
            _swCsv?.Close();

            sw.Stop();
            _logger.Info("");

            var suff = string.Empty;

            if (_fileCount != 1)
            {
                suff = "s";
            }

            _logger.Error(
                $"Processed {_fileCount:N0} file{suff} in {sw.Elapsed.TotalSeconds:N4} seconds\r\n");

            if (_errorFiles.Count > 0)
            {
                _logger.Info("");
                _logger.Error("Files with errors");
                foreach (var errorFile in _errorFiles)
                {
                    _logger.Info($"'{errorFile.Key}' error count: {errorFile.Value:N0}");
                }

                _logger.Info("");
            }
        }
Exemplo n.º 16
0
        private static void ProcessFile(string fileName)
        {
            _logger.Debug($"Checking if '{fileName}' is a SQLite file");
            if (SQLiteFile.IsSQLiteFile(fileName) == false)
            {
                if (_fluentCommandLineParser.Object.Hunt == false)
                {
                    _logger.Error($"\t'{fileName}' is not a SQLite file! Skipping...");
                }
                else
                {
                    _logger.Debug($"\t'{fileName}' is not a SQLite file! Skipping...");
                }

                return;
            }

            _logger.Debug($"'{fileName}' is a SQLite file!");

            if (_fluentCommandLineParser.Object.Dedupe)
            {
                var sha = File.GetHash(fileName, HashType.SHA1);

                if (SeenHashes.Contains(sha))
                {
                    _logger.Error($"Skipping '{fileName}' as a file with SHA-1 '{sha}' has already been processed");
                    Console.WriteLine();
                    return;
                }

                _logger.Debug($"Adding '{fileName}' SHA-1 '{sha}' to seen hashes collection");
                SeenHashes.Add(sha);
            }

            _logger.Warn($"Processing '{fileName}'...");

            ProcessedFiles.Add(fileName);

            var maps = new List <MapFile>();

            if (_fluentCommandLineParser.Object.Hunt)
            {
                maps = SQLMap.MapFiles.Values.ToList();
            }
            else
            {
                //only find maps tht match the db filename
                maps = SQLMap.MapFiles.Values.Where(t => string.Equals(t.FileName, Path.GetFileName(fileName),
                                                                       StringComparison.InvariantCultureIgnoreCase)).ToList();
            }

            var foundMap = false;

            //need to run thru each map and see if we get any IdentityQuery matches
            //process each one that matches
            foreach (var map in maps)
            {
                _logger.Debug($"Processing map '{map.Description}' with Id '{map.Id}'");

                var dbFactory = new OrmLiteConnectionFactory($"{fileName}", SqliteDialect.Provider);

                var baseTime = DateTimeOffset.UtcNow;

                using (var db = dbFactory.Open())
                {
                    _logger.Debug($"\tVerifying database via '{map.IdentifyQuery}'");

                    var id = db.ExecuteScalar <string>(map.IdentifyQuery);

                    if (string.Equals(id, map.IdentifyValue, StringComparison.InvariantCultureIgnoreCase) == false)
                    {
                        _logger.Error($"\tFor map w/ description '{map.Description}', got value '{id}' from IdentityQuery, but expected '{map.IdentifyValue}'. Queries will not be processed!");
                        continue;
                    }

                    //if we find any matches, its not unmatched anymore
                    foundMap = true;

                    _logger.Error($"\tMap queries found: {map.Queries.Count:N0}. Processing queries...");
                    foreach (var queryInfo in map.Queries)
                    {
                        _logger.Debug($"Processing query '{queryInfo.Name}'");

                        try
                        {
                            var results = db.Query <dynamic>(queryInfo.Query).ToList();

                            var outName =
                                $"{baseTime:yyyyMMddHHmmssffffff}_{map.CSVPrefix}_{queryInfo.BaseFileName}_{map.Id}.csv";

                            var fullOutName = Path.Combine(_fluentCommandLineParser.Object.CsvDirectory, outName);

                            if (results.Any() == false)
                            {
                                _logger.Warn($"\t '{queryInfo.Name}' did not return any results. CSV will not be saved.");
                                continue;
                            }

                            _logger.Info($"\tDumping '{queryInfo.Name}' to '{fullOutName}'");

                            using (var writer = new StreamWriter(new FileStream(fullOutName, FileMode.CreateNew)))
                            {
                                using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
                                {
                                    //   csv.WriteRecords(results);

                                    foreach (var result in results)
                                    {
                                        result.SourceFile = fileName;
                                        csv.WriteRecord(result);
                                        csv.NextRecord();
                                    }

                                    // csv.WriteComment("");
                                    // csv.NextRecord();
                                    // csv.WriteComment($"SourceFile: {fileName}");
                                    // csv.NextRecord();
                                    csv.Flush();
                                    writer.Flush();
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            _logger.Fatal($"Error processing map '{map.Description}' with Id '{map.Id}' for query '{queryInfo.Name}':");
                            _logger.Error($"\t{e.Message.Replace("\r\n","\r\n\t")}");
                        }
                    }
                }
            }

            if (foundMap == false)
            {
                _logger.Info($"\tNo maps found for '{fileName}'. Adding to unmatched database list");
                UnmatchedDbs.Add(fileName);
            }

            Console.WriteLine();
        }
Exemplo n.º 17
0
        public static IList <string> GetGitignoreDirectories(string path, bool recursive)
        {
            if (File.Exists(Path.Combine(path, ".gitignore")))
            {
                return new List <string> {
                           path
                }
            }
            ;

            var fileOptions = baseFileOptions;

            if (recursive)
            {
                fileOptions |= DirectoryEnumerationOptions.Recursive;
            }

            List <string> dontRecurseBelow = new List <string>();

            DirectoryEnumerationFilters fileFilters = new DirectoryEnumerationFilters
            {
                ErrorFilter = (errorCode, errorMessage, pathProcessed) =>
                {
                    logger.Error($"Find file error {errorCode}: {errorMessage} on {pathProcessed}");
                    return(true);
                },
                RecursionFilter = fsei =>
                {
                    if (fsei.IsDirectory && dontRecurseBelow.Any(p => fsei.FullPath.StartsWith(p, StringComparison.CurrentCulture)))
                    {
                        return(false);
                    }
                    return(true);
                },
                InclusionFilter = fsei =>
                {
                    if (fsei.FileName == ".gitignore")
                    {
                        dontRecurseBelow.Add(Path.GetDirectoryName(fsei.FullPath));
                        return(true);
                    }
                    return(false);
                }
            };

            var list = Directory.EnumerateFiles(path, fileOptions, fileFilters, PathFormat.FullPath)
                       .Select(s => Path.GetDirectoryName(s)).ToList();

            if (list.Count == 0)
            {
                DirectoryInfo di = new DirectoryInfo(path);
                while (di.Parent != null)
                {
                    if (File.Exists(Path.Combine(di.Parent.FullName, ".gitignore")))
                    {
                        list.Add(path);
                        break;
                    }

                    di = di.Parent;
                }
            }

            return(list);
        }
Exemplo n.º 18
0
        static void Main(string[] args)
        {
            ExceptionlessClient.Default.Startup("DyZCm8aZbNXf2iZ6BV00wY2UoR3U2tymh3cftNZs");

            SetupNLog();

            _logger = LogManager.GetLogger("EvtxECmd");

            _fluentCommandLineParser = new FluentCommandLineParser <ApplicationArguments>
            {
                IsCaseSensitive = false
            };

            _fluentCommandLineParser.Setup(arg => arg.File)
            .As('f')
            .WithDescription("File to process. This or -d is required\r\n");
            _fluentCommandLineParser.Setup(arg => arg.Directory)
            .As('d')
            .WithDescription("Directory to process that contains SQLite files. This or -f is required");

            _fluentCommandLineParser.Setup(arg => arg.CsvDirectory)
            .As("csv")
            .WithDescription(
                "Directory to save CSV formatted results to.");     // This, --json, or --xml required

            _fluentCommandLineParser.Setup(arg => arg.JsonDirectory)
            .As("json")
            .WithDescription(
                "Directory to save JSON formatted results to.\r\n");     // This, --csv, or --xml required

            _fluentCommandLineParser.Setup(arg => arg.Dedupe)
            .As("dedupe")
            .WithDescription(
                "Deduplicate -f or -d files based on SHA-1. First file found wins. Default is TRUE")
            .SetDefault(true);

            _fluentCommandLineParser.Setup(arg => arg.Hunt)
            .As("hunt")
            .WithDescription(
                "When true, all files are looked at regardless of name and file header is used to identify SQLite files, else filename in map is used to find databases. Default is FALSE\r\n  ")
            .SetDefault(false);

            _fluentCommandLineParser.Setup(arg => arg.MapsDirectory)
            .As("maps")
            .WithDescription(
                "The path where event maps are located. Defaults to 'Maps' folder where program was executed\r\n  ")
            .SetDefault(Path.Combine(BaseDirectory, "Maps"));

            _fluentCommandLineParser.Setup(arg => arg.Sync)
            .As("sync")
            .WithDescription(
                "If true, the latest maps from https://github.com/EricZimmerman/SQLECmd/tree/master/SQLMap/Maps are downloaded and local maps updated. Default is FALSE\r\n")
            .SetDefault(false);

            _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\r\n").SetDefault(false);

            var header =
                $"SQLECmd version {Assembly.GetExecutingAssembly().GetName().Version}" +
                "\r\n\r\nAuthor: Eric Zimmerman ([email protected])" +
                "\r\nhttps://github.com/EricZimmerman/SQLECmd";

            var footer =
                @"Examples: SQLECmd.exe -f ""C:\Temp\someFile.db"" --csv ""c:\temp\out"" " +
                "\r\n\t " +
                @" SQLECmd.exe -d ""C:\Temp\"" --csv ""c:\temp\out""" + "\r\n\t " +
                @" SQLECmd.exe -d ""C:\Temp\"" --hunt --csv ""c:\temp\out""" + "\r\n\t " +
                "\r\n\t" +
                "  Short options (single letter) are prefixed with a single dash. Long commands are prefixed with two dashes\r\n";

            _fluentCommandLineParser.SetupHelp("?", "help")
            .WithHeader(header)
            .Callback(text => _logger.Info(text + "\r\n" + footer));

            var result = _fluentCommandLineParser.Parse(args);

            if (result.HelpCalled)
            {
                return;
            }

            if (result.HasErrors)
            {
                _logger.Error("");
                _logger.Error(result.ErrorText);

                _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options);

                return;
            }

            if (_fluentCommandLineParser.Object.Sync)
            {
                try
                {
                    _logger.Info(header);
                    UpdateFromRepo();
                }
                catch (Exception e)
                {
                    _logger.Error(e, $"There was an error checking for updates: {e.Message}");
                }

                Environment.Exit(0);
            }

            if (_fluentCommandLineParser.Object.File.IsNullOrEmpty() &&
                _fluentCommandLineParser.Object.Directory.IsNullOrEmpty())
            {
                _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options);

                _logger.Warn("-f or -d is required. Exiting");
                return;
            }

            if (_fluentCommandLineParser.Object.CsvDirectory.IsNullOrEmpty())
            {
                _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options);

                _logger.Warn("--csv is required. Exiting");
                return;
            }

            _logger.Info(header);
            _logger.Info("");
            _logger.Info($"Command line: {string.Join(" ", Environment.GetCommandLineArgs().Skip(1))}\r\n");

            if (_fluentCommandLineParser.Object.Debug)
            {
                LogManager.Configuration.LoggingRules.First().EnableLoggingForLevel(LogLevel.Debug);
            }

            if (_fluentCommandLineParser.Object.Trace)
            {
                LogManager.Configuration.LoggingRules.First().EnableLoggingForLevel(LogLevel.Trace);
            }

            LogManager.ReconfigExistingLoggers();

            DumpSqliteDll();

            var sw = new Stopwatch();

            sw.Start();

            var ts = DateTimeOffset.UtcNow;

            if (Directory.Exists(_fluentCommandLineParser.Object.MapsDirectory) == false)
            {
                _logger.Warn(
                    $"Maps directory '{_fluentCommandLineParser.Object.MapsDirectory}' does not exist! Database maps will not be loaded!!");
            }
            else
            {
                _logger.Debug($"Loading maps from '{Path.GetFullPath(_fluentCommandLineParser.Object.MapsDirectory)}'");
                var errors = SQLMap.LoadMaps(Path.GetFullPath(_fluentCommandLineParser.Object.MapsDirectory));

                if (errors)
                {
                    return;
                }

                _logger.Info($"Maps loaded: {SQLMap.MapFiles.Count:N0}");
            }

            if (Directory.Exists(_fluentCommandLineParser.Object.CsvDirectory) == false)
            {
                _logger.Warn(
                    $"Path to '{_fluentCommandLineParser.Object.CsvDirectory}' doesn't exist. Creating...");

                try
                {
                    Directory.CreateDirectory(_fluentCommandLineParser.Object.CsvDirectory);
                }
                catch (Exception)
                {
                    _logger.Fatal(
                        $"Unable to create directory '{_fluentCommandLineParser.Object.CsvDirectory}'. Does a file with the same name exist? Exiting");
                    return;
                }
            }

            if (_fluentCommandLineParser.Object.File.IsNullOrEmpty() == false)
            {
                if (File.Exists(_fluentCommandLineParser.Object.File) == false)
                {
                    _logger.Warn($"'{_fluentCommandLineParser.Object.File}' does not exist! Exiting");
                    return;
                }

                ProcessFile(Path.GetFullPath(_fluentCommandLineParser.Object.File));
            }
            else
            {
                //Directories
                _logger.Info($"Looking for files in '{_fluentCommandLineParser.Object.Directory}'");
                _logger.Info("");

                Privilege[] privs = { Privilege.EnableDelegation, Privilege.Impersonate, Privilege.Tcb };
                using (new PrivilegeEnabler(Privilege.Backup, privs))
                {
                    var dirEnumOptions =
                        DirectoryEnumerationOptions.Files | DirectoryEnumerationOptions.Recursive |
                        DirectoryEnumerationOptions.SkipReparsePoints | DirectoryEnumerationOptions.ContinueOnException |
                        DirectoryEnumerationOptions.BasicSearch;

                    var f = new DirectoryEnumerationFilters
                    {
                        RecursionFilter = entryInfo => !entryInfo.IsMountPoint && !entryInfo.IsSymbolicLink,
                        ErrorFilter     = (errorCode, errorMessage, pathProcessed) => true
                    };

                    var dbNames = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase);

                    if (_fluentCommandLineParser.Object.Hunt)
                    {
                        f.InclusionFilter = fsei => true;
                    }
                    else
                    {
                        foreach (var mapFile in SQLMap.MapFiles)
                        {
                            dbNames.Add(mapFile.Value.FileName);
                        }

                        f.InclusionFilter = fsei => dbNames.Contains(fsei.FileName);
                    }

                    var files2 =
                        Directory.EnumerateFileSystemEntries(Path.GetFullPath(_fluentCommandLineParser.Object.Directory), dirEnumOptions, f);

                    foreach (var file in files2)
                    {
                        try
                        {
                            ProcessFile(file);
                        }
                        catch (Exception e)
                        {
                            _logger.Error($"Error processing '{file}': {e.Message}");
                        }
                    }
                }
            }

            sw.Stop();

            if (UnmatchedDbs.Any())
            {
                Console.WriteLine();
                _logger.Fatal($"At least one database was found with no corresponding map (Use --debug for more details about discovery process)");

                foreach (var unmatchedDb in UnmatchedDbs)
                {
                    DumpUnmatched(unmatchedDb);
                }
            }

            var extra = string.Empty;

            if (ProcessedFiles.Count > 1)
            {
                extra = "s";
            }

            _logger.Info($"\r\nProcessed {ProcessedFiles.Count:N0} file{extra} in {sw.Elapsed.TotalSeconds:N4} seconds\r\n");

            if (!File.Exists("SQLite.Interop.dll"))
            {
                return;
            }

            try
            {
                File.Delete("SQLite.Interop.dll");
            }
            catch (Exception)
            {
                _logger.Warn("Unable to delete 'SQLite.Interop.dll'. Delete manually if needed.\r\n");
            }
        }
Exemplo n.º 19
0
        public static IList <string> GetGitignoreDirectories(string path, bool recursive, bool followSymlinks)
        {
            if (File.Exists(Path.Combine(path, ".gitignore")))
            {
                return new List <string> {
                           path
                }
            }
            ;

            var fileOptions = baseFileOptions;

            if (recursive)
            {
                fileOptions |= DirectoryEnumerationOptions.Recursive;
            }
            if (followSymlinks)
            {
                fileOptions &= ~DirectoryEnumerationOptions.SkipReparsePoints;
            }

            List <string> dontRecurseBelow = new List <string>();

            dontRecurseBelow.Add(@"C:\$Recycle.Bin");
            foreach (var sf in new[]
            {
                Environment.SpecialFolder.Windows,
                Environment.SpecialFolder.ProgramFiles,
                Environment.SpecialFolder.ProgramFilesX86,
            })
            {
                string p = Environment.GetFolderPath(sf);
                if (!string.IsNullOrEmpty(p))
                {
                    dontRecurseBelow.Add(p);
                }
            }

            DirectoryEnumerationFilters fileFilters = new DirectoryEnumerationFilters
            {
                ErrorFilter = (errorCode, errorMessage, pathProcessed) =>
                {
                    logger.Error($"Find file error {errorCode}: {errorMessage} on {pathProcessed}");
                    return(true);
                },
                RecursionFilter = fsei =>
                {
                    if (Utils.CancelSearch)
                    {
                        throw new OperationCanceledException();
                    }

                    if (fsei.IsDirectory && dontRecurseBelow.Any(p => fsei.FullPath.StartsWith(p, true, CultureInfo.CurrentCulture)))
                    {
                        return(false);
                    }
                    return(true);
                },
                InclusionFilter = fsei =>
                {
                    if (Utils.CancelSearch)
                    {
                        throw new OperationCanceledException();
                    }

                    if (fsei.FileName == ".gitignore")
                    {
                        dontRecurseBelow.Add(Path.GetDirectoryName(fsei.FullPath));
                        return(true);
                    }
                    return(false);
                }
            };

            try
            {
                // search down subdirectories
                var list = Directory.EnumerateFiles(path, fileOptions, fileFilters, PathFormat.FullPath)
                           .Select(s => Path.GetDirectoryName(s)).ToList();

                if (list.Count == 0)
                {
                    // not found, search up the tree
                    DirectoryInfo di = new DirectoryInfo(path);
                    while (di.Parent != null)
                    {
                        if (File.Exists(Path.Combine(di.Parent.FullName, ".gitignore")))
                        {
                            list.Add(path);
                            break;
                        }

                        di = di.Parent;
                    }
                }

                return(list);
            }
            catch (OperationCanceledException)
            {
                return(new List <string>());
            }
        }
Exemplo n.º 20
0
        private void DumpGetSetAttributes(bool isLocal)
        {
            Console.WriteLine("\n=== TEST {0} ===", isLocal ? UnitTestConstants.Local : UnitTestConstants.Network);
            var tmp      = Path.Combine(Path.GetTempPath(), "File.SetAttributes()-" + Path.GetRandomFileName());
            var tempPath = isLocal ? tmp : Path.LocalToUnc(tmp);
            var sys32    = isLocal ? UnitTestConstants.SysRoot32 : Path.LocalToUnc(UnitTestConstants.SysRoot32);

            Console.WriteLine("\nInput Path: [{0}]", sys32);

            // Just enumerate and compare attributes in folder: C:\Windows\System32
            foreach (var file in Directory.EnumerateFiles(sys32))
            {
                var actual   = File.GetAttributes(file);
                var expected = System.IO.File.GetAttributes(file);

                Assert.AreEqual(expected, actual, "AlphaFS != System.IO");
            }


            Console.WriteLine("\nInput Path: [{0}]", tempPath);

            // Create some folders and files.
            UnitTestConstants.CreateDirectoriesAndFiles(tempPath, 10, true);

            var apply = FileAttributes.Hidden | FileAttributes.Archive | FileAttributes.System | FileAttributes.ReadOnly;

            Console.WriteLine("\nSetAttributes(): [{0}]", apply);

            var allOk = true;
            var cnt   = 0;

            UnitTestConstants.StopWatcher(true);
            foreach (var file in Directory.EnumerateFiles(tempPath))
            {
                try
                {
                    File.SetAttributes(file, apply);

                    var actual   = File.GetAttributes(file);
                    var expected = System.IO.File.GetAttributes(file);

                    Console.WriteLine("\n\t#{0:000}\tFile     : [{1}]\n\t\tAlphaFS  : [{2}]\n\t\tSystem.IO: [{3}]", ++cnt, file, expected, actual);

                    if (cnt == 0)
                    {
                        Assert.Inconclusive("Nothing was enumerated, but it was expected.");
                    }

                    Assert.AreEqual(expected, actual, "AlphaFS != System.IO");
                }
                catch (Exception ex)
                {
                    allOk = false;
                    Console.WriteLine("\n\tCaught (unexpected) {0}: [{1}]", ex.GetType().FullName, ex.Message.Replace(Environment.NewLine, "  "));
                }
            }
            Console.WriteLine();
            Console.WriteLine(UnitTestConstants.Reporter());
            Assert.IsTrue(allOk);


            apply = FileAttributes.Normal;
            Console.WriteLine("\nSetAttributes(): [{0}]", apply);

            allOk = true;
            cnt   = 0;
            UnitTestConstants.StopWatcher(true);
            foreach (var file in Directory.EnumerateFiles(tempPath))
            {
                try
                {
                    File.SetAttributes(file, apply);

                    var actual   = File.GetAttributes(file);
                    var expected = System.IO.File.GetAttributes(file);

                    Console.WriteLine("\n\t#{0:000}\tFile     : [{1}]\n\t\tAlphaFS  : [{2}]\n\t\tSystem.IO: [{3}]", ++cnt, file, expected, actual);

                    if (cnt == 0)
                    {
                        Assert.Inconclusive("Nothing was enumerated, but it was expected.");
                    }

                    Assert.AreEqual(expected, actual, "AlphaFS != System.IO");
                }
                catch (Exception ex)
                {
                    allOk = false;
                    Console.WriteLine("\n\tCaught (unexpected) {0}: [{1}]", ex.GetType().FullName, ex.Message.Replace(Environment.NewLine, "  "));
                }
            }
            Console.WriteLine();
            Console.WriteLine(UnitTestConstants.Reporter());


            Directory.Delete(tempPath, true);
            Assert.IsFalse(Directory.Exists(tempPath), "Cleanup failed: Directory should have been removed.");
            Assert.IsTrue(allOk);
            Console.WriteLine();
        }
Exemplo n.º 21
0
        private static void UpdateFromRepo()
        {
            Console.WriteLine();

            _logger.Info(
                "Checking for updated maps at https://github.com/EricZimmerman/evtx/tree/master/evtx/Maps...");
            Console.WriteLine();
            var archivePath = Path.Combine(BaseDirectory, "____master.zip");

            if (File.Exists(archivePath))
            {
                File.Delete(archivePath);
            }

            using (var client = new WebClient())
            {
                ServicePointManager.Expect100Continue = true;
                ServicePointManager.SecurityProtocol  = SecurityProtocolType.Tls12;
                client.DownloadFile("https://github.com/EricZimmerman/evtx/archive/master.zip", archivePath);
            }

            var fff = new FastZip();

            var directoryFilter = "Maps";

            // Will prompt to overwrite if target file names already exist
            fff.ExtractZip(archivePath, BaseDirectory, FastZip.Overwrite.Always, null,
                           null, directoryFilter, true);

            if (File.Exists(archivePath))
            {
                File.Delete(archivePath);
            }

            var newMapPath = Path.Combine(BaseDirectory, "evtx-master", "evtx", "Maps");

            var orgMapMath = Path.Combine(BaseDirectory, "Maps");

            var newMaps = Directory.GetFiles(newMapPath);

            var newlocalMaps = new List <string>();

            var updatedlocalMaps = new List <string>();

            foreach (var newMap in newMaps)
            {
                var mName = Path.GetFileName(newMap);
                var dest  = Path.Combine(orgMapMath, mName);

                if (File.Exists(dest) == false)
                {
                    //new target
                    newlocalMaps.Add(mName);
                }
                else
                {
                    //current destination file exists, so compare to new
                    var fiNew = new FileInfo(newMap);
                    var fi    = new FileInfo(dest);

                    if (fiNew.GetHash(HashType.SHA1) != fi.GetHash(HashType.SHA1))
                    {
                        //updated file
                        updatedlocalMaps.Add(mName);
                    }
                }

                File.Copy(newMap, dest, CopyOptions.None);
            }



            if (newlocalMaps.Count > 0 || updatedlocalMaps.Count > 0)
            {
                _logger.Fatal("Updates found!");
                Console.WriteLine();

                if (newlocalMaps.Count > 0)
                {
                    _logger.Error("New maps");
                    foreach (var newLocalMap in newlocalMaps)
                    {
                        _logger.Info(Path.GetFileNameWithoutExtension(newLocalMap));
                    }

                    Console.WriteLine();
                }

                if (updatedlocalMaps.Count > 0)
                {
                    _logger.Error("Updated maps");
                    foreach (var um in updatedlocalMaps)
                    {
                        _logger.Info(Path.GetFileNameWithoutExtension(um));
                    }

                    Console.WriteLine();
                }

                Console.WriteLine();
            }
            else
            {
                Console.WriteLine();
                _logger.Info("No new maps available");
                Console.WriteLine();
            }

            Directory.Delete(Path.Combine(BaseDirectory, "evtx-master"), true);
        }
Exemplo n.º 22
0
        private void DumpAppendAllLines(bool isLocal)
        {
            #region Setup

            Console.WriteLine("\n=== TEST {0} ===", isLocal ? UnitTestConstants.Local : UnitTestConstants.Network);
            var tempFolder = Path.GetTempPath();
            var tempPath   = Path.Combine(tempFolder, "File.Delete-" + Path.GetRandomFileName());
            if (!isLocal)
            {
                tempPath = Path.LocalToUnc(tempPath);
            }

            // Create file and append text.
            var tempFile = Path.GetTempFileName();
            if (!isLocal)
            {
                tempFile = Path.LocalToUnc(tempFile);
            }

            IEnumerable <string> allLines = new[] { UnitTestConstants.TenNumbers, UnitTestConstants.TextHelloWorld, UnitTestConstants.TextGoodbyeWorld, UnitTestConstants.TextUnicode };

            #endregion // Setup

            try
            {
                #region AppendAllLines

                Console.WriteLine("\nDefault AlphaFS Encoding: [{0}]", NativeMethods.DefaultFileEncoding.EncodingName);

                // Create real UTF-8 file.
                File.AppendAllLines(tempFile, allLines, NativeMethods.DefaultFileEncoding);

                // Read filestream contents.
                using (var streamRead = File.OpenText(tempFile))
                {
                    var line = streamRead.ReadToEnd();

                    Console.WriteLine("\nCreated: [{0}] filestream: [{1}]\n\n\tAppendAllLines content:\n{2}", streamRead.CurrentEncoding.EncodingName, tempFile, line);

                    foreach (var line2 in allLines)
                    {
                        Assert.IsTrue(line.Contains(line2));
                    }
                }

                // Append
                File.AppendAllLines(tempFile, new[] { "Append 1" });
                File.AppendAllLines(tempFile, allLines);
                File.AppendAllLines(tempFile, new[] { "Append 2" });
                File.AppendAllLines(tempFile, allLines);

                // Read filestream contents.
                using (var streamRead = File.OpenText(tempFile))
                {
                    var line = streamRead.ReadToEnd();

                    Console.WriteLine("AppendAllLines content:\n{0}", line);

                    foreach (var line2 in allLines)
                    {
                        Assert.IsTrue(line.Contains(line2));
                    }
                }

                #endregion // AppendAllLines
            }
            finally
            {
                File.Delete(tempFile, true);
                Assert.IsFalse(File.Exists(tempFile), "Cleanup failed: File should have been removed.");
            }

            Console.WriteLine();
        }
Exemplo n.º 23
0
        /// <summary>
        /// The user may already have some files in the OutputFolder. If so we can go through these and
        /// figure out which need to be updated, deleted, or left alone
        /// </summary>
        public async Task OptimizeModlist()
        {
            Utils.Log("Optimizing ModList directives");

            // Clone the ModList so our changes don't modify the original data
            ModList = ModList.Clone();

            var indexed = ModList.Directives.ToDictionary(d => d.To);

            UpdateTracker.NextStep("Looking for files to delete");
            await Directory.EnumerateFiles(OutputFolder, "*", DirectoryEnumerationOptions.Recursive)
            .PMap(Queue, UpdateTracker, f =>
            {
                var relative_to = f.RelativeTo(OutputFolder);
                Utils.Status($"Checking if ModList file {relative_to}");
                if (indexed.ContainsKey(relative_to) || f.IsInPath(DownloadFolder))
                {
                    return;
                }

                Utils.Log($"Deleting {relative_to} it's not part of this ModList");
                File.Delete(f);
            });

            Utils.Log("Cleaning empty folders");
            var expectedFolders = indexed.Keys
                                  // We ignore the last part of the path, so we need a dummy file name
                                  .Append(Path.Combine(DownloadFolder, "_"))
                                  .SelectMany(path =>
            {
                // Get all the folders and all the folder parents
                // so for foo\bar\baz\qux.txt this emits ["foo", "foo\\bar", "foo\\bar\\baz"]
                var split = path.Split('\\');
                return(Enumerable.Range(1, split.Length - 1).Select(t => string.Join("\\", split.Take(t))));
            })
                                  .Distinct()
                                  .Select(p => Path.Combine(OutputFolder, p))
                                  .ToHashSet();

            try
            {
                Directory.EnumerateDirectories(OutputFolder, DirectoryEnumerationOptions.Recursive)
                .Where(p => !expectedFolders.Contains(p))
                .OrderByDescending(p => p.Length)
                .Do(Utils.DeleteDirectory);
            }
            catch (Exception)
            {
                // ignored because it's not worth throwing a fit over
                Utils.Log("Error when trying to clean empty folders. This doesn't really matter.");
            }

            UpdateTracker.NextStep("Looking for unmodified files");
            (await indexed.Values.PMap(Queue, UpdateTracker, d =>
            {
                // Bit backwards, but we want to return null for
                // all files we *want* installed. We return the files
                // to remove from the install list.
                Status($"Optimizing {d.To}");
                var path = Path.Combine(OutputFolder, d.To);
                if (!File.Exists(path))
                {
                    return(null);
                }

                var fi = new FileInfo(path);
                if (fi.Length != d.Size)
                {
                    return(null);
                }

                return(path.FileHash() == d.Hash ? d : null);
            }))
            .Where(d => d != null)
            .Do(d => indexed.Remove(d.To));

            UpdateTracker.NextStep("Updating ModList");
            Utils.Log($"Optimized {ModList.Directives.Count} directives to {indexed.Count} required");
            var requiredArchives = indexed.Values.OfType <FromArchive>()
                                   .GroupBy(d => d.ArchiveHashPath[0])
                                   .Select(d => d.Key)
                                   .ToHashSet();

            ModList.Archives   = ModList.Archives.Where(a => requiredArchives.Contains(a.Hash)).ToList();
            ModList.Directives = indexed.Values.ToList();
        }
Exemplo n.º 24
0
        private void DumpEnableDisableEncryption(bool isLocal)
        {
            Console.WriteLine("\n=== TEST {0} ===", isLocal ? UnitTestConstants.Local : UnitTestConstants.Network);
            var tempPath = Path.Combine(Path.GetTempPath(), "Directory.EnableDisableEncryption()-" + Path.GetRandomFileName());

            if (!isLocal)
            {
                tempPath = Path.LocalToUnc(tempPath);
            }

            Console.WriteLine("\nInput Directory Path: [{0}]", tempPath);

            const string disabled    = "Disable=0";
            const string enabled     = "Disable=1";
            var          lineDisable = string.Empty;
            var          deskTopIni  = Path.Combine(tempPath, "Desktop.ini");

            Directory.CreateDirectory(tempPath);
            var actual = File.GetAttributes(tempPath);


            var report = string.Empty;
            var action = false;

            try
            {
                UnitTestConstants.StopWatcher(true);
                Directory.EnableEncryption(tempPath);
                report = UnitTestConstants.Reporter(true);
                action = true;
            }
            catch (Exception ex)
            {
                Console.WriteLine("\n\tCaught (UNEXPECTED) {0}: [{1}]", ex.GetType().FullName, ex.Message.Replace(Environment.NewLine, "  "));
            }
            Assert.IsTrue(action, "Encryption should be True");


            // Read filestream contents, get the last line.
            using (var streamRead = File.OpenText(deskTopIni))
            {
                string line;
                while ((line = streamRead.ReadLine()) != null)
                {
                    lineDisable = line;
                }
            }
            action = lineDisable.Equals(disabled);
            Console.WriteLine("\nEnableEncryption() (Should be True): [{0}]", action);
            Console.WriteLine("File Desktop.ini contents: [{0}]\t{1}", lineDisable, report);
            Assert.IsTrue(action, "Encryption should be True");
            Assert.IsTrue(File.Exists(deskTopIni), "Desktop.ini should Exist");


            action = false;
            try
            {
                UnitTestConstants.StopWatcher(true);
                Directory.DisableEncryption(tempPath);
                report = UnitTestConstants.Reporter(true);
                action = true;
            }
            catch (Exception ex)
            {
                Console.WriteLine("\n\tCaught (UNEXPECTED) {0}: [{1}]", ex.GetType().FullName, ex.Message.Replace(Environment.NewLine, "  "));
            }
            Assert.IsTrue(action, "Encryption should be True");


            // Read filestream contents, get the last line.
            using (var streamRead = File.OpenText(deskTopIni))
            {
                string line;
                while ((line = streamRead.ReadLine()) != null)
                {
                    lineDisable = line;
                }
            }
            action = lineDisable.Equals(enabled);
            Console.WriteLine("\nDisableEncryption() (Should be True): [{0}]", action);
            Console.WriteLine("File Desktop.ini contents: [{0}]\t{1}", lineDisable, report);
            Assert.IsTrue(action, "Encryption should be True");
            Assert.IsTrue(File.Exists(deskTopIni), "Desktop.ini should Exist");


            Directory.Delete(tempPath, true);
            Assert.IsFalse(Directory.Exists(tempPath), "Cleanup failed: Directory should have been removed.");
            Console.WriteLine();
        }
Exemplo n.º 25
0
        public void AlphaFS_Volume_SetVolumeMountPoint()
        {
            Console.WriteLine("Volume.SetVolumeMountPoint()");

            if (!UnitTestConstants.IsAdmin())
            {
                Assert.Inconclusive();
            }

            #region Logical Drives

            var cnt        = 0;
            var destFolder = Path.Combine(TempFolder, "Volume.SetVolumeMountPoint()-" + Path.GetRandomFileName());
            Directory.CreateDirectory(destFolder);

            var guid = Volume.GetUniqueVolumeNameForPath(UnitTestConstants.SysDrive);

            try
            {
                UnitTestConstants.StopWatcher(true);

                Volume.SetVolumeMountPoint(destFolder, guid);
                Console.WriteLine(
                    "\t#{0:000}\tSystem Drive: [{1}]\tGUID: [{2}]\n\t\tDestination : [{3}]\n\t\tCreated Mount Point.\n\t{4}",
                    ++cnt, UnitTestConstants.SysDrive, guid, destFolder, UnitTestConstants.Reporter(true));

                Console.WriteLine("\n");
                AlphaFS_Volume_EnumerateVolumeMountPoints();

                Console.WriteLine("\n\nFile.GetLinkTargetInfo()");

                var lti = File.GetLinkTargetInfo(destFolder);
                Assert.IsTrue(!string.IsNullOrWhiteSpace(lti.PrintName));
                Assert.IsTrue(!string.IsNullOrWhiteSpace(lti.SubstituteName));
                Assert.IsTrue(UnitTestConstants.Dump(lti, -14), "Unable to dump object.");

                // Cleanup.
                UnitTestConstants.StopWatcher(true);
                var deleteOk = false;
                try
                {
                    Volume.DeleteVolumeMountPoint(destFolder);
                    deleteOk = true;
                }
                catch (Exception ex)
                {
                    Console.WriteLine("\nCaught (unexpected) {0}: [{1}]", ex.GetType().FullName, ex.Message.Replace(Environment.NewLine, "  "));
                }

                Console.WriteLine("\n\nVolume.DeleteVolumeMountPoint() (Should be True): [{0}]\tFolder: [{1}]\n{2}\n",
                                  deleteOk, destFolder, UnitTestConstants.Reporter());

                Directory.Delete(destFolder, true, true);
                Assert.IsTrue(deleteOk && !Directory.Exists(destFolder));

                AlphaFS_Volume_EnumerateVolumeMountPoints();
            }
            catch (Exception ex)
            {
                cnt = 0;

                Console.WriteLine("\nCaught (unexpected) {0}: [{1}]", ex.GetType().FullName, ex.Message.Replace(Environment.NewLine, "  "));
            }
            finally
            {
                // Always remove mount point.
                // Experienced: CCleaner deletes through mount points!
                try { Volume.DeleteVolumeMountPoint(destFolder); }
                catch { }
            }

            if (cnt == 0)
            {
                Assert.Inconclusive("Nothing was enumerated, but it was expected.");
            }

            #endregion // Logical Drives
        }
Exemplo n.º 26
0
        private static void Main(string[] args)
        {
            ExceptionlessClient.Default.Startup("x3MPpeQSBUUsXl3DjekRQ9kYjyN3cr5JuwdoOBpZ");

            SetupNLog();

            _keywords = new HashSet <string> {
                "temp", "tmp"
            };

            _logger = LogManager.GetCurrentClassLogger();



            _fluentCommandLineParser = new FluentCommandLineParser <ApplicationArguments>
            {
                IsCaseSensitive = false
            };

            _fluentCommandLineParser.Setup(arg => arg.File)
            .As('f')
            .WithDescription("File to process. Either this or -d is required");

            _fluentCommandLineParser.Setup(arg => arg.Directory)
            .As('d')
            .WithDescription("Directory to recursively process. Either this or -f is required");

            _fluentCommandLineParser.Setup(arg => arg.Keywords)
            .As('k')
            .WithDescription(
                "Comma separated list of keywords to highlight in output. By default, 'temp' and 'tmp' are highlighted. Any additional keywords will be added to these.");

            _fluentCommandLineParser.Setup(arg => arg.OutFile)
            .As('o')
            .WithDescription(
                "When specified, save prefetch file bytes to the given path. Useful to look at decompressed Win10 files");

            _fluentCommandLineParser.Setup(arg => arg.Quiet)
            .As('q')
            .WithDescription(
                "Do not dump full details about each file processed. Speeds up processing when using --json or --csv. Default is FALSE\r\n")
            .SetDefault(false);

            _fluentCommandLineParser.Setup(arg => arg.JsonDirectory)
            .As("json")
            .WithDescription(
                "Directory to save json representation to. Use --pretty for a more human readable layout");

            _fluentCommandLineParser.Setup(arg => arg.CsvDirectory)
            .As("csv")
            .WithDescription(
                "Directory to save CSV results to. Be sure to include the full path in double quotes");
            _fluentCommandLineParser.Setup(arg => arg.CsvName)
            .As("csvf")
            .WithDescription("File name to save CSV formatted results to. When present, overrides default name");


            _fluentCommandLineParser.Setup(arg => arg.xHtmlDirectory)
            .As("html")
            .WithDescription(
                "Directory to save xhtml formatted results to. Be sure to include the full path in double quotes");

            _fluentCommandLineParser.Setup(arg => arg.JsonPretty)
            .As("pretty")
            .WithDescription(
                "When exporting to json, use a more human readable layout. Default is FALSE\r\n").SetDefault(false);



            _fluentCommandLineParser.Setup(arg => arg.DateTimeFormat)
            .As("dt")
            .WithDescription(
                "The custom date/time format to use when displaying timestamps. See https://goo.gl/CNVq0k for options. Default is: yyyy-MM-dd HH:mm:ss")
            .SetDefault("yyyy-MM-dd HH:mm:ss");

            _fluentCommandLineParser.Setup(arg => arg.PreciseTimestamps)
            .As("mp")
            .WithDescription(
                "When true, display higher precision for timestamps. Default is FALSE").SetDefault(false);


            var header =
                $"PECmd version {Assembly.GetExecutingAssembly().GetName().Version}" +
                "\r\n\r\nAuthor: Eric Zimmerman ([email protected])" +
                "\r\nhttps://github.com/EricZimmerman/PECmd";

            var footer = @"Examples: PECmd.exe -f ""C:\Temp\CALC.EXE-3FBEF7FD.pf""" + "\r\n\t " +
                         @" PECmd.exe -f ""C:\Temp\CALC.EXE-3FBEF7FD.pf"" --json ""D:\jsonOutput"" --jsonpretty" +
                         "\r\n\t " +
                         @" PECmd.exe -d ""C:\Temp"" -k ""system32, fonts""" + "\r\n\t " +
                         @" PECmd.exe -d ""C:\Temp"" --csv ""c:\temp"" --csvf foo.csv --json c:\temp\json" +
                         "\r\n\t " +
                         @" PECmd.exe -d ""C:\Windows\Prefetch""" + "\r\n\t " +
                         "\r\n\t" +
                         "  Short options (single letter) are prefixed with a single dash. Long commands are prefixed with two dashes\r\n";

            _fluentCommandLineParser.SetupHelp("?", "help")
            .WithHeader(header)
            .Callback(text => _logger.Info(text + "\r\n" + footer));

            var result = _fluentCommandLineParser.Parse(args);

            if (result.HelpCalled)
            {
                return;
            }

            if (result.HasErrors)
            {
                _logger.Error("");
                _logger.Error(result.ErrorText);

                _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options);

                return;
            }

            if (UsefulExtension.IsNullOrEmpty(_fluentCommandLineParser.Object.File) &&
                UsefulExtension.IsNullOrEmpty(_fluentCommandLineParser.Object.Directory))
            {
                _fluentCommandLineParser.HelpOption.ShowHelp(_fluentCommandLineParser.Options);

                _logger.Warn("Either -f or -d is required. Exiting");
                return;
            }

            if (UsefulExtension.IsNullOrEmpty(_fluentCommandLineParser.Object.File) == false &&
                !File.Exists(_fluentCommandLineParser.Object.File))
            {
                _logger.Warn($"File '{_fluentCommandLineParser.Object.File}' not found. Exiting");
                return;
            }

            if (UsefulExtension.IsNullOrEmpty(_fluentCommandLineParser.Object.Directory) == false &&
                !Directory.Exists(_fluentCommandLineParser.Object.Directory))
            {
                _logger.Warn($"Directory '{_fluentCommandLineParser.Object.Directory}' not found. Exiting");
                return;
            }

            if (_fluentCommandLineParser.Object.Keywords?.Length > 0)
            {
                var kws = _fluentCommandLineParser.Object.Keywords.ToLowerInvariant().Split(new[] { ',' },
                                                                                            StringSplitOptions.RemoveEmptyEntries);

                foreach (var kw in kws)
                {
                    _keywords.Add(kw.Trim());
                }
            }


            _logger.Info(header);
            _logger.Info("");
            _logger.Info($"Command line: {string.Join(" ", Environment.GetCommandLineArgs().Skip(1))}");

            if (IsAdministrator() == false)
            {
                _logger.Fatal("\r\nWarning: Administrator privileges not found!");
            }

            _logger.Info("");
            _logger.Info($"Keywords: {string.Join(", ", _keywords)}");
            _logger.Info("");

            if (_fluentCommandLineParser.Object.PreciseTimestamps)
            {
                _fluentCommandLineParser.Object.DateTimeFormat = _preciseTimeFormat;
            }

            _processedFiles = new List <IPrefetch>();

            _failedFiles = new List <string>();

            if (_fluentCommandLineParser.Object.File?.Length > 0)
            {
                IPrefetch pf = null;

                try
                {
                    pf = LoadFile(_fluentCommandLineParser.Object.File);

                    if (pf != null)
                    {
                        if (_fluentCommandLineParser.Object.OutFile.IsNullOrEmpty() == false)
                        {
                            try
                            {
                                if (Directory.Exists(Path.GetDirectoryName(_fluentCommandLineParser.Object.OutFile)) ==
                                    false)
                                {
                                    Directory.CreateDirectory(
                                        Path.GetDirectoryName(_fluentCommandLineParser.Object.OutFile));
                                }

                                PrefetchFile.SavePrefetch(_fluentCommandLineParser.Object.OutFile, pf);
                                _logger.Info($"Saved prefetch bytes to '{_fluentCommandLineParser.Object.OutFile}'");
                            }
                            catch (Exception e)
                            {
                                _logger.Error($"Unable to save prefetch file. Error: {e.Message}");
                            }
                        }


                        _processedFiles.Add(pf);
                    }
                }
                catch (UnauthorizedAccessException ex)
                {
                    _logger.Error(
                        $"Unable to access '{_fluentCommandLineParser.Object.File}'. Are you running as an administrator? Error: {ex.Message}");
                }
                catch (Exception ex)
                {
                    _logger.Error(
                        $"Error getting prefetch files in '{_fluentCommandLineParser.Object.Directory}'. Error: {ex.Message}");
                }
            }
            else
            {
                _logger.Info($"Looking for prefetch files in '{_fluentCommandLineParser.Object.Directory}'");
                _logger.Info("");

                string[] pfFiles = null;


                var f = new DirectoryEnumerationFilters();
                f.InclusionFilter = fsei =>
                {
                    if (fsei.Extension.ToUpperInvariant() == ".PF")
                    {
                        return(true);
                    }

                    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;

                var files2 =
                    Alphaleonis.Win32.Filesystem.Directory.EnumerateFileSystemEntries(_fluentCommandLineParser.Object.Directory, dirEnumOptions, f);



                try
                {
                    pfFiles = files2.ToArray(); //Directory.GetFiles(_fluentCommandLineParser.Object.Directory, "*.pf",                        SearchOption.AllDirectories);
                }
                catch (UnauthorizedAccessException ua)
                {
                    _logger.Error(
                        $"Unable to access '{_fluentCommandLineParser.Object.Directory}'. Are you running as an administrator? Error: {ua.Message}");
                    return;
                }
                catch (Exception ex)
                {
                    _logger.Error(
                        $"Error getting prefetch files in '{_fluentCommandLineParser.Object.Directory}'. Error: {ex.Message}");
                    return;
                }

                _logger.Info($"Found {pfFiles.Length:N0} Prefetch files");
                _logger.Info("");

                var sw = new Stopwatch();
                sw.Start();

                foreach (var file in pfFiles)
                {
                    var pf = LoadFile(file);

                    if (pf != null)
                    {
                        _processedFiles.Add(pf);
                    }
                }

                sw.Stop();

                if (_fluentCommandLineParser.Object.Quiet)
                {
                    _logger.Info("");
                }

                _logger.Info(
                    $"Processed {pfFiles.Length - _failedFiles.Count:N0} out of {pfFiles.Length:N0} files in {sw.Elapsed.TotalSeconds:N4} seconds");

                if (_failedFiles.Count > 0)
                {
                    _logger.Info("");
                    _logger.Warn("Failed files");
                    foreach (var failedFile in _failedFiles)
                    {
                        _logger.Info($"  {failedFile}");
                    }
                }
            }

            if (_processedFiles.Count > 0)
            {
                _logger.Info("");

                try
                {
                    CsvWriter    csv          = null;
                    StreamWriter streamWriter = null;

                    CsvWriter    csvTl          = null;
                    StreamWriter streamWriterTl = null;


                    if (_fluentCommandLineParser.Object.CsvDirectory?.Length > 0)
                    {
                        var outName = $"{DateTimeOffset.Now:yyyyMMddHHmmss}_PECmd_Output.csv";

                        if (_fluentCommandLineParser.Object.CsvName.IsNullOrEmpty() == false)
                        {
                            outName = Path.GetFileName(_fluentCommandLineParser.Object.CsvName);
                        }

                        var outNameTl = $"{DateTimeOffset.Now:yyyyMMddHHmmss}_PECmd_Output_Timeline.csv";
                        if (_fluentCommandLineParser.Object.CsvName.IsNullOrEmpty() == false)
                        {
                            outNameTl =
                                $"{Path.GetFileNameWithoutExtension(_fluentCommandLineParser.Object.CsvName)}_Timeline{Path.GetExtension(_fluentCommandLineParser.Object.CsvName)}";
                        }


                        var outFile   = Path.Combine(_fluentCommandLineParser.Object.CsvDirectory, outName);
                        var outFileTl = Path.Combine(_fluentCommandLineParser.Object.CsvDirectory, outNameTl);


                        if (Directory.Exists(_fluentCommandLineParser.Object.CsvDirectory) == false)
                        {
                            _logger.Warn(
                                $"Path to '{_fluentCommandLineParser.Object.CsvDirectory}' does not exist. Creating...");
                            Directory.CreateDirectory(_fluentCommandLineParser.Object.CsvDirectory);
                        }

                        _logger.Warn($"CSV output will be saved to '{outFile}'");
                        _logger.Warn($"CSV time line output will be saved to '{outFileTl}'");

                        try
                        {
                            streamWriter = new StreamWriter(outFile);
                            csv          = new CsvWriter(streamWriter);


                            csv.WriteHeader(typeof(CsvOut));
                            csv.NextRecord();

                            streamWriterTl = new StreamWriter(outFileTl);
                            csvTl          = new CsvWriter(streamWriterTl);

                            csvTl.WriteHeader(typeof(CsvOutTl));
                            csvTl.NextRecord();
                        }
                        catch (Exception ex)
                        {
                            _logger.Error(
                                $"Unable to open '{outFile}' for writing. CSV export canceled. Error: {ex.Message}");
                        }
                    }

                    if (_fluentCommandLineParser.Object.JsonDirectory?.Length > 0)
                    {
                        if (Directory.Exists(_fluentCommandLineParser.Object.JsonDirectory) == false)
                        {
                            _logger.Warn(
                                $"'{_fluentCommandLineParser.Object.JsonDirectory} does not exist. Creating...'");
                            Directory.CreateDirectory(_fluentCommandLineParser.Object.JsonDirectory);
                        }

                        _logger.Warn($"Saving json output to '{_fluentCommandLineParser.Object.JsonDirectory}'");
                    }

                    XmlTextWriter xml = null;

                    if (_fluentCommandLineParser.Object.xHtmlDirectory?.Length > 0)
                    {
                        if (Directory.Exists(_fluentCommandLineParser.Object.xHtmlDirectory) == false)
                        {
                            _logger.Warn(
                                $"'{_fluentCommandLineParser.Object.xHtmlDirectory} does not exist. Creating...'");
                            Directory.CreateDirectory(_fluentCommandLineParser.Object.xHtmlDirectory);
                        }

                        var outDir = Path.Combine(_fluentCommandLineParser.Object.xHtmlDirectory,
                                                  $"{DateTimeOffset.UtcNow:yyyyMMddHHmmss}_PECmd_Output_for_{_fluentCommandLineParser.Object.xHtmlDirectory.Replace(@":\", "_").Replace(@"\", "_")}");

                        if (Directory.Exists(outDir) == false)
                        {
                            Directory.CreateDirectory(outDir);
                        }

                        var styleDir = Path.Combine(outDir, "styles");
                        if (Directory.Exists(styleDir) == false)
                        {
                            Directory.CreateDirectory(styleDir);
                        }

                        File.WriteAllText(Path.Combine(styleDir, "normalize.css"), Resources.normalize);
                        File.WriteAllText(Path.Combine(styleDir, "style.css"), Resources.style);

                        Resources.directories.Save(Path.Combine(styleDir, "directories.png"));
                        Resources.filesloaded.Save(Path.Combine(styleDir, "filesloaded.png"));

                        var outFile = Path.Combine(_fluentCommandLineParser.Object.xHtmlDirectory, outDir,
                                                   "index.xhtml");

                        _logger.Warn($"Saving HTML output to '{outFile}'");

                        xml = new XmlTextWriter(outFile, Encoding.UTF8)
                        {
                            Formatting  = Formatting.Indented,
                            Indentation = 4
                        };

                        xml.WriteStartDocument();

                        xml.WriteProcessingInstruction("xml-stylesheet", "href=\"styles/normalize.css\"");
                        xml.WriteProcessingInstruction("xml-stylesheet", "href=\"styles/style.css\"");

                        xml.WriteStartElement("document");
                    }

                    if (_fluentCommandLineParser.Object.CsvDirectory.IsNullOrEmpty() == false ||
                        _fluentCommandLineParser.Object.JsonDirectory.IsNullOrEmpty() == false ||
                        _fluentCommandLineParser.Object.xHtmlDirectory.IsNullOrEmpty() == false)
                    {
                        foreach (var processedFile in _processedFiles)
                        {
                            var o = GetCsvFormat(processedFile);

                            try
                            {
                                foreach (var dateTimeOffset in processedFile.LastRunTimes)
                                {
                                    var t = new CsvOutTl();

                                    var exePath =
                                        processedFile.Filenames.FirstOrDefault(
                                            y => y.EndsWith(processedFile.Header.ExecutableFilename));

                                    if (exePath == null)
                                    {
                                        exePath = processedFile.Header.ExecutableFilename;
                                    }

                                    t.ExecutableName = exePath;
                                    t.RunTime        = dateTimeOffset.ToString(_fluentCommandLineParser.Object.DateTimeFormat);

                                    csvTl?.WriteRecord(t);
                                    csvTl?.NextRecord();
                                }
                            }
                            catch (Exception ex)
                            {
                                _logger.Error(
                                    $"Error getting time line record for '{processedFile.SourceFilename}' to '{_fluentCommandLineParser.Object.CsvDirectory}'. Error: {ex.Message}");
                            }

                            try
                            {
                                csv?.WriteRecord(o);
                                csv?.NextRecord();
                            }
                            catch (Exception ex)
                            {
                                _logger.Error(
                                    $"Error writing CSV record for '{processedFile.SourceFilename}' to '{_fluentCommandLineParser.Object.CsvDirectory}'. Error: {ex.Message}");
                            }

                            if (_fluentCommandLineParser.Object.JsonDirectory?.Length > 0)
                            {
                                SaveJson(processedFile, _fluentCommandLineParser.Object.JsonPretty,
                                         _fluentCommandLineParser.Object.JsonDirectory);
                            }

                            //XHTML
                            xml?.WriteStartElement("Container");
                            xml?.WriteElementString("SourceFile", o.SourceFilename);
                            xml?.WriteElementString("SourceCreated", o.SourceCreated);
                            xml?.WriteElementString("SourceModified", o.SourceModified);
                            xml?.WriteElementString("SourceAccessed", o.SourceAccessed);

                            xml?.WriteElementString("LastRun", o.LastRun);

                            xml?.WriteElementString("PreviousRun0", $"{o.PreviousRun0}");
                            xml?.WriteElementString("PreviousRun1", $"{o.PreviousRun1}");
                            xml?.WriteElementString("PreviousRun2", $"{o.PreviousRun2}");
                            xml?.WriteElementString("PreviousRun3", $"{o.PreviousRun3}");
                            xml?.WriteElementString("PreviousRun4", $"{o.PreviousRun4}");
                            xml?.WriteElementString("PreviousRun5", $"{o.PreviousRun5}");
                            xml?.WriteElementString("PreviousRun6", $"{o.PreviousRun6}");

                            xml?.WriteStartElement("ExecutableName");
                            xml?.WriteAttributeString("title",
                                                      "Note: The name of the executable tracked by the pf file");
                            xml?.WriteString(o.ExecutableName);
                            xml?.WriteEndElement();

                            xml?.WriteElementString("RunCount", $"{o.RunCount}");

                            xml?.WriteStartElement("Size");
                            xml?.WriteAttributeString("title", "Note: The size of the executable in bytes");
                            xml?.WriteString(o.Size);
                            xml?.WriteEndElement();

                            xml?.WriteStartElement("Hash");
                            xml?.WriteAttributeString("title",
                                                      "Note: The calculated hash for the pf file that should match the hash in the source file name");
                            xml?.WriteString(o.Hash);
                            xml?.WriteEndElement();

                            xml?.WriteStartElement("Version");
                            xml?.WriteAttributeString("title",
                                                      "Note: The operating system that generated the prefetch file");
                            xml?.WriteString(o.Version);
                            xml?.WriteEndElement();

                            xml?.WriteElementString("Note", o.Note);

                            xml?.WriteElementString("Volume0Name", o.Volume0Name);
                            xml?.WriteElementString("Volume0Serial", o.Volume0Serial);
                            xml?.WriteElementString("Volume0Created", o.Volume0Created);

                            xml?.WriteElementString("Volume1Name", o.Volume1Name);
                            xml?.WriteElementString("Volume1Serial", o.Volume1Serial);
                            xml?.WriteElementString("Volume1Created", o.Volume1Created);


                            xml?.WriteStartElement("Directories");
                            xml?.WriteAttributeString("title",
                                                      "A comma separated list of all directories accessed by the executable");
                            xml?.WriteString(o.Directories);
                            xml?.WriteEndElement();

                            xml?.WriteStartElement("FilesLoaded");
                            xml?.WriteAttributeString("title",
                                                      "A comma separated list of all files that were loaded by the executable");
                            xml?.WriteString(o.FilesLoaded);
                            xml?.WriteEndElement();

                            xml?.WriteEndElement();
                        }


                        //Close CSV stuff
                        streamWriter?.Flush();
                        streamWriter?.Close();

                        streamWriterTl?.Flush();
                        streamWriterTl?.Close();

                        //Close XML
                        xml?.WriteEndElement();
                        xml?.WriteEndDocument();
                        xml?.Flush();
                    }
                }
                catch (Exception ex)
                {
                    _logger.Error($"Error exporting data! Error: {ex.Message}");
                }
            }
        }
Exemplo n.º 27
0
        protected override async Task <int> Run()
        {
            if (!File.Exists(Modlist))
            {
                Log($"The file {Modlist} does not exist!");
                return(-1);
            }

            if (!Directory.Exists(Input))
            {
                Log($"The input directory {Input} does not exist!");
                return(-1);
            }

            if (!Directory.Exists(Output))
            {
                Log($"The output directory {Output} does not exist, it will be created.");
                Directory.CreateDirectory(Output);
            }

            if (!Modlist.EndsWith(Consts.ModListExtension) && !Modlist.EndsWith("modlist.txt"))
            {
                Log($"The file {Modlist} is not a valid modlist file!");
                return(-1);
            }

            if (Copy && Move)
            {
                Log("You can't set both copy and move flags!");
                return(-1);
            }

            var isModlist = Modlist.EndsWith(Consts.ModListExtension);

            var list = new List <TransferFile>();

            if (isModlist)
            {
                ModList modlist;

                try
                {
                    modlist = AInstaller.LoadFromFile(Modlist);
                }
                catch (Exception e)
                {
                    Log($"Error while loading the Modlist!\n{e}");
                    return(1);
                }

                if (modlist == null)
                {
                    Log("The Modlist could not be loaded!");
                    return(1);
                }

                Log($"Modlist contains {modlist.Archives.Count} archives.");

                modlist.Archives.Do(a =>
                {
                    var inputPath  = Path.Combine(Input, a.Name);
                    var outputPath = Path.Combine(Output, a.Name);

                    if (!File.Exists(inputPath))
                    {
                        Log($"File {inputPath} does not exist, skipping.");
                        return;
                    }

                    Log($"Adding {inputPath} to the transfer list.");
                    list.Add(new TransferFile(inputPath, outputPath));

                    var metaInputPath  = Path.Combine(inputPath, ".meta");
                    var metaOutputPath = Path.Combine(outputPath, ".meta");

                    if (File.Exists(metaInputPath))
                    {
                        Log($"Found meta file {metaInputPath}");
                        if (IncludeMeta)
                        {
                            Log($"Adding {metaInputPath} to the transfer list.");
                            list.Add(new TransferFile(metaInputPath, metaOutputPath));
                        }
                        else
                        {
                            Log($"Meta file {metaInputPath} will be ignored.");
                        }
                    }
                    else
                    {
                        Log($"Found no meta file for {inputPath}");
                        if (IncludeMeta)
                        {
                            if (string.IsNullOrWhiteSpace(a.Meta))
                            {
                                Log($"Meta for {a.Name} is empty, this should not be possible but whatever.");
                                return;
                            }

                            Log("Adding meta from archive info the transfer list");
                            list.Add(new TransferFile(a.Meta, metaOutputPath, true));
                        }
                        else
                        {
                            Log($"Meta will be ignored for {a.Name}");
                        }
                    }
                });
            }
            else
            {
                if (!Directory.Exists(Mods))
                {
                    Log($"Mods directory {Mods} does not exist!");
                    return(-1);
                }

                Log($"Reading modlist.txt from {Modlist}");
                string[] modlist = File.ReadAllLines(Modlist);

                if (modlist == null || modlist.Length == 0)
                {
                    Log($"Provided modlist.txt file at {Modlist} is empty or could not be read!");
                    return(-1);
                }

                var mods = modlist.Where(s => s.StartsWith("+")).Select(s => s.Substring(1)).ToHashSet();
                if (mods.Count == 0)
                {
                    Log("Counted mods from modlist.txt are 0!");
                    return(-1);
                }

                Log($"Found {mods.Count} mods in modlist.txt");

                var downloads = new HashSet <string>();

                Directory.EnumerateDirectories(Mods, "*", SearchOption.TopDirectoryOnly)
                .Where(d => mods.Contains(Path.GetRelativePath(Path.GetDirectoryName(d), d)))
                .Do(d =>
                {
                    var meta = Path.Combine(d, "meta.ini");
                    if (!File.Exists(meta))
                    {
                        Log($"Mod meta file {meta} does not exist, skipping");
                        return;
                    }

                    string[] ini = File.ReadAllLines(meta);
                    if (ini == null || ini.Length == 0)
                    {
                        Log($"Mod meta file {meta} could not be read or is empty!");
                        return;
                    }

                    ini.Where(i => !string.IsNullOrWhiteSpace(i) && i.StartsWith("installationFile="))
                    .Select(i => i.Replace("installationFile=", ""))
                    .Do(i =>
                    {
                        Log($"Found installationFile {i}");
                        downloads.Add(i);
                    });
                });

                Log($"Found {downloads.Count} installationFiles from mod metas.");

                Directory.EnumerateFiles(Input, "*", SearchOption.TopDirectoryOnly)
                .Where(f => downloads.Contains(Path.GetFileNameWithoutExtension(f)))
                .Do(f =>
                {
                    Log($"Found archive {f}");

                    var outputPath = Path.Combine(Output, Path.GetFileName(f));

                    Log($"Adding {f} to the transfer list");
                    list.Add(new TransferFile(f, outputPath));

                    var metaInputPath = Path.Combine(f, ".meta");
                    if (File.Exists(metaInputPath))
                    {
                        Log($"Found meta file for {f} at {metaInputPath}");
                        if (IncludeMeta)
                        {
                            var metaOutputPath = Path.Combine(outputPath, ".meta");
                            Log($"Adding {metaInputPath} to the transfer list.");
                            list.Add(new TransferFile(metaInputPath, metaOutputPath));
                        }
                        else
                        {
                            Log("Meta file will be ignored");
                        }
                    }
                    else
                    {
                        Log($"Found no meta file for {f}");
                    }
                });
            }

            Log($"Transfer list contains {list.Count} items");
            var success = 0;
            var failed  = 0;
            var skipped = 0;

            list.Do(f =>
            {
                if (File.Exists(f.Output))
                {
                    if (Overwrite)
                    {
                        Log($"Output file {f.Output} already exists, it will be overwritten");
                        if (f.IsMeta || Move)
                        {
                            Log($"Deleting file at {f.Output}");
                            try
                            {
                                File.Delete(f.Output);
                            }
                            catch (Exception e)
                            {
                                Log($"Could not delete file {f.Output}!\n{e}");
                                failed++;
                            }
                        }
                    }
                    else
                    {
                        Log($"Output file {f.Output} already exists, skipping");
                        skipped++;
                        return;
                    }
                }

                if (f.IsMeta)
                {
                    Log($"Writing meta data to {f.Output}");
                    try
                    {
                        File.WriteAllText(f.Output, f.Input, Encoding.UTF8);
                        success++;
                    }
                    catch (Exception e)
                    {
                        Log($"Error while writing meta data to {f.Output}!\n{e}");
                        failed++;
                    }
                }
                else
                {
                    if (Copy)
                    {
                        Log($"Copying file {f.Input} to {f.Output}");
                        try
                        {
                            File.Copy(f.Input, f.Output, Overwrite ? CopyOptions.None : CopyOptions.FailIfExists, CopyMoveProgressHandler, null);
                            success++;
                        }
                        catch (Exception e)
                        {
                            Log($"Error while copying file {f.Input} to {f.Output}!\n{e}");
                            failed++;
                        }
                    }
                    else if (Move)
                    {
                        Log($"Moving file {f.Input} to {f.Output}");
                        try
                        {
                            File.Move(f.Input, f.Output, Overwrite ? MoveOptions.ReplaceExisting : MoveOptions.None, CopyMoveProgressHandler, null);
                            success++;
                        }
                        catch (Exception e)
                        {
                            Log($"Error while moving file {f.Input} to {f.Output}!\n{e}");
                            failed++;
                        }
                    }
                }
            });

            Log($"Skipped transfers: {skipped}");
            Log($"Failed transfers: {failed}");
            Log($"Successful transfers: {success}");

            return(0);
        }
Exemplo n.º 28
0
        protected override async Task <bool> _Begin(CancellationToken cancel)
        {
            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            var metric = Metrics.Send("begin_install", ModList.Name);

            ConfigureProcessor(18, await RecommendQueueSize());
            var game = ModList.GameType.MetaData();

            if (GameFolder == null)
            {
                GameFolder = game.GameLocation();
            }

            if (GameFolder == null)
            {
                MessageBox.Show(
                    $"In order to do a proper install Wabbajack needs to know where your {game.MO2Name} folder resides. We tried looking the" +
                    "game location up in the windows registry but were unable to find it, please make sure you launch the game once before running this installer. ",
                    "Could not find game location", MessageBoxButton.OK);
                Utils.Log("Exiting because we couldn't find the game folder.");
                return(false);
            }

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Validating Game ESMs");
            ValidateGameESMs();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Validating Modlist");
            await ValidateModlist.RunValidation(Queue, ModList);

            Directory.CreateDirectory(OutputFolder);
            Directory.CreateDirectory(DownloadFolder);

            if (Directory.Exists(Path.Combine(OutputFolder, "mods")) && WarnOnOverwrite)
            {
                if ((await Utils.Log(new ConfirmUpdateOfExistingInstall {
                    ModListName = ModList.Name, OutputFolder = OutputFolder
                }).Task) == ConfirmUpdateOfExistingInstall.Choice.Abort)
                {
                    Utils.Log("Existing installation at the request of the user, existing mods folder found.");
                    return(false);
                }
            }

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Optimizing Modlist");
            await OptimizeModlist();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Hashing Archives");
            await HashArchives();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Downloading Missing Archives");
            await DownloadArchives();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Hashing Remaining Archives");
            await HashArchives();

            var missing = ModList.Archives.Where(a => !HashedArchives.ContainsKey(a.Hash)).ToList();

            if (missing.Count > 0)
            {
                foreach (var a in missing)
                {
                    Info($"Unable to download {a.Name}");
                }
                if (IgnoreMissingFiles)
                {
                    Info("Missing some archives, but continuing anyways at the request of the user");
                }
                else
                {
                    Error("Cannot continue, was unable to download one or more archives");
                }
            }

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Priming VFS");
            await PrimeVFS();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Building Folder Structure");
            BuildFolderStructure();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Installing Archives");
            await InstallArchives();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Installing Included files");
            await InstallIncludedFiles();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Installing Archive Metas");
            await InstallIncludedDownloadMetas();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Building BSAs");
            await BuildBSAs();

            if (cancel.IsCancellationRequested)
            {
                return(false);
            }
            UpdateTracker.NextStep("Generating Merges");
            await zEditIntegration.GenerateMerges(this);

            UpdateTracker.NextStep("Updating System-specific ini settings");
            SetScreenSizeInPrefs();

            UpdateTracker.NextStep("Installation complete! You may exit the program.");
            var metric2 = Metrics.Send("finish_install", ModList.Name);

            return(true);
        }
Exemplo n.º 29
0
        private void DumpGetSuffixedDirectoryNameWithoutRoot(bool isLocal)
        {
            Console.WriteLine("\n=== TEST {0} ===", isLocal ? UnitTestConstants.Local : UnitTestConstants.Network);

            var neDir = "Non-Existing Directory";
            var sys32 = (UnitTestConstants.SysRoot + Path.DirectorySeparator + "system32" + Path.DirectorySeparator).Replace(UnitTestConstants.SysDrive + Path.DirectorySeparator, "");

            var fullPath = Path.Combine(UnitTestConstants.SysRoot + Path.DirectorySeparator + "system32" + Path.DirectorySeparator, neDir);

            if (!isLocal)
            {
                fullPath = Path.LocalToUnc(fullPath);
            }

            UnitTestConstants.StopWatcher(true);
            var suffixedDirectoryNameWithoutRoot = Path.GetSuffixedDirectoryNameWithoutRoot(fullPath);

            Console.WriteLine("\nInput Path: [{0}]\n\tGetSuffixedDirectoryName() (Should be: [{1}]): [{2}]\n{3}", fullPath, sys32, suffixedDirectoryNameWithoutRoot, UnitTestConstants.Reporter());
            Assert.IsTrue(suffixedDirectoryNameWithoutRoot.Equals(sys32, StringComparison.OrdinalIgnoreCase), "Path mismatch.");



            fullPath = Path.Combine(fullPath, "Non-Existing file.txt");
            neDir    = (Path.Combine(Environment.SystemDirectory, neDir) + Path.DirectorySeparator).Replace(UnitTestConstants.SysDrive + Path.DirectorySeparator, "");
            if (!isLocal)
            {
                fullPath = Path.LocalToUnc(fullPath);
            }

            UnitTestConstants.StopWatcher(true);
            suffixedDirectoryNameWithoutRoot = Path.GetSuffixedDirectoryNameWithoutRoot(fullPath);
            Console.WriteLine("\nInput Path: [{0}]\n\tGetSuffixedDirectoryName() (Should be: [{1}]): [{2}]\n{3}", fullPath, neDir, suffixedDirectoryNameWithoutRoot, UnitTestConstants.Reporter());
            Assert.IsTrue(suffixedDirectoryNameWithoutRoot.Equals(neDir, StringComparison.OrdinalIgnoreCase), "Path mismatch.");



            fullPath = UnitTestConstants.SysRoot;
            if (!isLocal)
            {
                fullPath = Path.LocalToUnc(fullPath);
            }

            UnitTestConstants.StopWatcher(true);
            suffixedDirectoryNameWithoutRoot = Path.GetSuffixedDirectoryNameWithoutRoot(fullPath);
            Console.WriteLine("\nInput Path: [{0}]\n\tGetSuffixedDirectoryName() (Should be: [null]): [{1}]\n{2}", fullPath, suffixedDirectoryNameWithoutRoot ?? "null", UnitTestConstants.Reporter());
            Assert.AreEqual(null, suffixedDirectoryNameWithoutRoot, "Path mismatch.");



            fullPath = UnitTestConstants.SysDrive + Path.DirectorySeparator;
            if (!isLocal)
            {
                fullPath = Path.LocalToUnc(fullPath);
            }

            UnitTestConstants.StopWatcher(true);
            suffixedDirectoryNameWithoutRoot = Path.GetSuffixedDirectoryNameWithoutRoot(fullPath);
            Console.WriteLine("\nInput Path: [{0}]\n\tGetSuffixedDirectoryName() (Should be: [null]): [{1}]\n{2}", fullPath, suffixedDirectoryNameWithoutRoot ?? "null", UnitTestConstants.Reporter());
            Assert.AreEqual(null, suffixedDirectoryNameWithoutRoot, "Path mismatch.");

            Console.WriteLine("\n");
        }
Exemplo n.º 30
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("");
        }