Exemplo n.º 1
0
        public void TestWin10DevEnvPfProperties()
        {
            var file = Path.Combine(TestPrefetchMain.Win10Path, @"DEVENV.EXE-854D7862.pf");
            var pf   = PrefetchFile.Open(file);

            //PrefetchFile.DumpToJson(pf, true, @"D:\temp\DEVENV.json");

            pf.Header.ExecutableFilename.Should().Be("DEVENV.EXE");
            pf.Header.Hash.Should().Be("854D7862");
            pf.Header.FileSize.Should().Be(380690);
            pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-13T09: 50:34.6578416-07:00,"));
            pf.RunCount.Should().Be(54);

            pf.VolumeCount.Should().Be(1);
            pf.VolumeInformation[0].DeviceName.Should().Be(@"\VOLUME{01d1217a9c4c6779-8c9f49ec}");
            pf.VolumeInformation[0].SerialNumber.Should().Be("8C9F49EC");
            pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2015-11-17T13:57:46.2434681-07:00"));

            pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(516);
            pf.VolumeInformation[0].DirectoryNames[3].Should()
            .Be(@"\VOLUME{01d1217a9c4c6779-8c9f49ec}\PROGRAM FILES (X86)\COMMON FILES\MICROSOFT SHARED\MSENV");

            pf.VolumeInformation[0].FileReferences.Count.Should().Be(681);

            pf.Filenames.Count.Should().Be(403);
            pf.Filenames[3].Should()
            .Be(
                @"\VOLUME{01d1217a9c4c6779-8c9f49ec}\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 14.0\COMMON7\IDE\MICROSOFT.VISUALSTUDIO.ACTIVITIES.DLL");

            pf.VolumeInformation[0].FileReferences[6].MFTEntryNumber.Should().Be((ulong)148922);
            pf.VolumeInformation[0].FileReferences[6].MFTSequenceNumber.Should().Be(1);

            pf.VolumeInformation[0].FileReferences[8].MFTEntryNumber.Should().Be((ulong)219686);
            pf.VolumeInformation[0].FileReferences[8].MFTSequenceNumber.Should().Be(2);
        }
Exemplo n.º 2
0
        public void TestWin2012R2RegEditPfProperties()
        {
            var file = Path.Combine(TestPrefetchMain.Win2012R2Path, @"NOTEPAD.EXE-D8414F97.pf");
            var pf   = PrefetchFile.Open(file);

            // PrefetchFile.DumpToJson(pf, true, @"D:\temp\out.json");

            pf.Header.ExecutableFilename.Should().Be("NOTEPAD.EXE");
            pf.Header.Hash.Should().Be("D8414F97");
            pf.Header.FileSize.Should().Be(15320);
            pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-16T14: 40:31.2944718-07:00"));
            pf.RunCount.Should().Be(2);

            pf.VolumeCount.Should().Be(1);
            pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME2");
            pf.VolumeInformation[0].SerialNumber.Should().Be("7450B65F");
            pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-16T15:21:57.7889266-07:00"));

            pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(7);
            pf.VolumeInformation[0].DirectoryNames[3].Should()
            .Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\GLOBALIZATION\SORTING");

            pf.VolumeInformation[0].FileReferences.Count.Should().Be(35);

            pf.Filenames.Count.Should().Be(26);
            pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\SYSTEM32\ADVAPI32.DLL");

            //For whatever reason the sequence # is 1 for both of these when looking at the entry # in the MFT using X-Ways
            pf.VolumeInformation[0].FileReferences[5].MFTEntryNumber.Should().Be((ulong)0);
            pf.VolumeInformation[0].FileReferences[5].MFTSequenceNumber.Should().Be(null);

            pf.VolumeInformation[0].FileReferences[1].MFTEntryNumber.Should().Be((ulong)18972);
            pf.VolumeInformation[0].FileReferences[1].MFTSequenceNumber.Should().Be(null);
        }
Exemplo n.º 3
0
        public void TestWin10ChromePfProperties()
        {
            var file = Path.Combine(TestPrefetchMain.Win10Path, @"CHROME.EXE-B3BA7868.pf");
            var pf   = PrefetchFile.Open(file);

            pf.Header.ExecutableFilename.Should().Be("CHROME.EXE");
            pf.Header.Hash.Should().Be("B3BA7868");
            pf.Header.FileSize.Should().Be(116042);
            pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-13T11: 06:55.3344577-07:00"));
            pf.RunCount.Should().Be(20);

            pf.VolumeCount.Should().Be(1);
            pf.VolumeInformation[0].DeviceName.Should().Be(@"\VOLUME{01d1217a9c4c6779-8c9f49ec}");
            pf.VolumeInformation[0].SerialNumber.Should().Be("8C9F49EC");
            pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2015-11-17T13:57:46.2434681-07:00"));

            pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(23);
            pf.VolumeInformation[0].DirectoryNames[3].Should()
            .Be(@"\VOLUME{01d1217a9c4c6779-8c9f49ec}\PROGRAM FILES (X86)\GOOGLE\CHROME\APPLICATION");

            pf.VolumeInformation[0].FileReferences.Count.Should().Be(284);

            pf.LastRunTimes.Count.Should().Be(8);

            pf.Filenames.Count.Should().Be(282);
            pf.Filenames[3].Should().Be(@"\VOLUME{01d1217a9c4c6779-8c9f49ec}\WINDOWS\SYSTEM32\KERNEL32.DLL");

            pf.VolumeInformation[0].FileReferences[5].MFTEntryNumber.Should().Be((ulong)55125);
            pf.VolumeInformation[0].FileReferences[5].MFTSequenceNumber.Should().Be(1);

            pf.VolumeInformation[0].FileReferences[9].MFTEntryNumber.Should().Be((ulong)117682);
            pf.VolumeInformation[0].FileReferences[9].MFTSequenceNumber.Should().Be(2);
        }
Exemplo n.º 4
0
        public void TestWin8ChromePfProperties()
        {
            var file = Path.Combine(TestPrefetchMain.Win8xPath, @"CALC.EXE-77FDF17F.pf");
            var pf   = PrefetchFile.Open(file);

            pf.Header.ExecutableFilename.Should().Be("CALC.EXE");
            pf.Header.Hash.Should().Be("77FDF17F");
            pf.Header.FileSize.Should().Be(22048);
            pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-16T14: 10:26.0583417-07:00"));
            pf.RunCount.Should().Be(2);

            pf.VolumeCount.Should().Be(1);
            pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME2");
            pf.VolumeInformation[0].SerialNumber.Should().Be("C6EE7444");
            pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-16T15:04:54.3519546-07:00"));

            pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(7);
            pf.VolumeInformation[0].DirectoryNames[3].Should()
            .Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\GLOBALIZATION\SORTING");

            pf.VolumeInformation[0].FileReferences.Count.Should().Be(46);

            pf.Filenames.Count.Should().Be(37);
            pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\SYSTEM32\KERNELBASE.DLL");

            pf.VolumeInformation[0].FileReferences[5].MFTEntryNumber.Should().Be((ulong)43858);
            pf.VolumeInformation[0].FileReferences[5].MFTSequenceNumber.Should().Be(1);

            pf.VolumeInformation[0].FileReferences[9].MFTEntryNumber.Should().Be((ulong)46917);
            pf.VolumeInformation[0].FileReferences[9].MFTSequenceNumber.Should().Be(1);
        }
Exemplo n.º 5
0
        public void TestXPCalcPfProperties()
        {
            var file = Path.Combine(TestPrefetchMain.WinXpPath, @"CALC.EXE-02CD573A.pf");
            var pf   = PrefetchFile.Open(file);

//            PrefetchFile.DumpToJson(pf,true,@"D:\temp\out.json");

            pf.Header.ExecutableFilename.Should().Be("CALC.EXE");
            pf.Header.Hash.Should().Be("2CD573A");
            pf.Header.FileSize.Should().Be(11332);
            pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-13T15: 05:51.2812500-07:00"));
            pf.RunCount.Should().Be(3);

            pf.VolumeCount.Should().Be(1);
            pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME1");
            pf.VolumeInformation[0].SerialNumber.Should().Be("E0F7E847");
            pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-13T04:17:18.7187500-07:00"));

            pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(6);
            pf.VolumeInformation[0].DirectoryNames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME1\WINDOWS\SYSTEM32\");

            pf.VolumeInformation[0].FileReferences.Count.Should().Be(36);

            pf.Filenames.Count.Should().Be(30);
            pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME1\WINDOWS\SYSTEM32\LOCALE.NLS");

            pf.VolumeInformation[0].FileReferences[34].MFTEntryNumber.Should().Be((ulong)126);
            pf.VolumeInformation[0].FileReferences[34].MFTSequenceNumber.Should().Be(1);
        }
Exemplo n.º 6
0
        public void Test2k3CmdPfProperties()
        {
            var file = Path.Combine(TestPrefetchMain.Win2k3Path, @"CMD.EXE-087B4001.pf");
            var pf   = PrefetchFile.Open(file);

            pf.Header.ExecutableFilename.Should().Be("CMD.EXE");
            pf.Header.Hash.Should().Be("87B4001");
            pf.Header.FileSize.Should().Be(6002);
            pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-15T16: 01:40.8750000-07:00"));
            pf.RunCount.Should().Be(3);

            pf.VolumeCount.Should().Be(1);
            pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME1");
            pf.VolumeInformation[0].SerialNumber.Should().Be("64BB3469");
            pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-15T08:45:15.8906250-07:00"));

            pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(4);
            pf.VolumeInformation[0].DirectoryNames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME1\WINDOWS\SYSTEM32\");

            pf.VolumeInformation[0].FileReferences.Count.Should().Be(20);

            pf.Filenames.Count.Should().Be(16);
            pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME1\WINDOWS\SYSTEM32\LOCALE.NLS");

            pf.VolumeInformation[0].FileReferences[5].MFTEntryNumber.Should().Be((ulong)250);
            pf.VolumeInformation[0].FileReferences[5].MFTSequenceNumber.Should().Be(1);
        }
Exemplo n.º 7
0
        public void TestWin7CalcPfProperties()
        {
            var file = Path.Combine(TestPrefetchMain.Win7Path, @"CALC.EXE-77FDF17F.pf");
            var pf   = PrefetchFile.Open(file);

            //PrefetchFile.DumpToJson(pf, true, @"D:\temp\win7calc.json");

            pf.Header.ExecutableFilename.Should().Be("CALC.EXE");
            pf.Header.Hash.Should().Be("77FDF17F");
            pf.Header.FileSize.Should().Be(23538);
            pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-16T13: 27:01.1967500-07:00"));
            pf.RunCount.Should().Be(2);

            pf.VolumeCount.Should().Be(1);
            pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME2");
            pf.VolumeInformation[0].SerialNumber.Should().Be("88008C2F");
            pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-16T14:15:18.1093750-07:00"));

            pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(8);
            pf.VolumeInformation[0].DirectoryNames[3].Should()
            .Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\GLOBALIZATION\SORTING");

            pf.VolumeInformation[0].FileReferences.Count.Should().Be(45);

            pf.Filenames.Count.Should().Be(37);
            pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\SYSTEM32\KERNELBASE.DLL");

            pf.VolumeInformation[0].FileReferences[2].MFTEntryNumber.Should().Be((ulong)25654);
            pf.VolumeInformation[0].FileReferences[2].MFTSequenceNumber.Should().Be(1);
        }
Exemplo n.º 8
0
        public void InvalidFileShouldThrowException()
        {
            var    badFile = Path.Combine(BadPath, "notAPrefetch.pf");
            Action action  = () => PrefetchFile.Open(badFile);

            action.ShouldThrow <Exception>().WithMessage("Invalid signature! Should be 'SCCA'");
        }
Exemplo n.º 9
0
        public void TestVistaExplorerPfProperties()
        {
            var file = Path.Combine(TestPrefetchMain.WinVistaPath, @"EXPLORER.EXE-7A3328DA.pf");
            var pf   = PrefetchFile.Open(file);

            pf.Header.ExecutableFilename.Should().Be("EXPLORER.EXE");
            pf.Header.Hash.Should().Be("7A3328DA");
            pf.Header.FileSize.Should().Be(38470);
            pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-16T13: 02:00.8326765-07:00"));
            pf.RunCount.Should().Be(1);

            pf.VolumeCount.Should().Be(1);
            pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME1");
            pf.VolumeInformation[0].SerialNumber.Should().Be("E8EAB8B5");
            pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-16T13:53:13.1093750-07:00"));

            pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(13);
            pf.VolumeInformation[0].DirectoryNames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME1\USERS\PUBLIC");

            pf.VolumeInformation[0].FileReferences.Count.Should().Be(84);

            pf.Filenames.Count.Should().Be(66);
            pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME1\WINDOWS\SYSTEM32\ADVAPI32.DLL");

            pf.VolumeInformation[0].FileReferences[1].MFTEntryNumber.Should().Be((ulong)352);
            pf.VolumeInformation[0].FileReferences[1].MFTSequenceNumber.Should().Be(null);
        }
Exemplo n.º 10
0
        public void TestWin2012RegEditPfProperties()
        {
            var file = Path.Combine(TestPrefetchMain.Win2012Path, @"REGEDIT.EXE-90FEEA06.pf");
            var pf   = PrefetchFile.Open(file);

            pf.Header.ExecutableFilename.Should().Be("REGEDIT.EXE");
            pf.Header.Hash.Should().Be("90FEEA06");
            pf.Header.FileSize.Should().Be(22982);
            pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-16T14: 36:18.7186980-07:00"));
            pf.RunCount.Should().Be(1);

            pf.VolumeCount.Should().Be(1);
            pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME2");
            pf.VolumeInformation[0].SerialNumber.Should().Be("2E25F20A");
            pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-16T15:20:46.1666157-07:00"));

            pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(12);
            pf.VolumeInformation[0].DirectoryNames[3].Should()
            .Be(@"\DEVICE\HARDDISKVOLUME2\USERS\ADMINISTRATOR\APPDATA\LOCAL");

            pf.VolumeInformation[0].FileReferences.Count.Should().Be(62);

            pf.Filenames.Count.Should().Be(42);

            //For whatever reason the sequence # is 1 for both of these when looking at the entry #
            pf.VolumeInformation[0].FileReferences[5].MFTEntryNumber.Should().Be((ulong)27324);
            pf.VolumeInformation[0].FileReferences[5].MFTSequenceNumber.Should().Be(null);

            pf.VolumeInformation[0].FileReferences[9].MFTEntryNumber.Should().Be((ulong)29316);
            pf.VolumeInformation[0].FileReferences[9].MFTSequenceNumber.Should().Be(null);
        }
Exemplo n.º 11
0
        public void TestWin8CmdPfProperties()
        {
            var file = Path.Combine(TestPrefetchMain.Win8xPath, @"_CMD.EXE-4A81B364.pf");
            var pf   = PrefetchFile.Open(file);

            pf.Header.ExecutableFilename.Should().Be("CMD.EXE");
            pf.Header.Hash.Should().Be("4A81B364");
            pf.Header.FileSize.Should().Be(8590);
            pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-16T14: 25:41.5341178-07:00"));
            pf.RunCount.Should().Be(2);

            pf.VolumeCount.Should().Be(1);
            pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME2");
            pf.VolumeInformation[0].SerialNumber.Should().Be("A26E529A");
            pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-16T15:15:38.2977678-07:00"));

            pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(8);
            pf.VolumeInformation[0].DirectoryNames[3].Should()
            .Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\BRANDING\BASEBRD\EN-US");

            pf.VolumeInformation[0].FileReferences.Count.Should().Be(20);

            pf.Filenames.Count.Should().Be(12);
            pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\SYSTEM32\KERNELBASE.DLL");

            pf.VolumeInformation[0].FileReferences[1].MFTEntryNumber.Should().Be((ulong)44760);
            pf.VolumeInformation[0].FileReferences[1].MFTSequenceNumber.Should().Be(null);
        }
Exemplo n.º 12
0
        public void OneOff()
        {
            var f = @"C:\Temp\outLW\vss010\Windows\prefetch\SETUP.EXE-C52DC467.pf";

            var pf = PrefetchFile.Open(f);

            //   pf.Should().NotBe(null);
        }
Exemplo n.º 13
0
        public void Windows2k3ShouldHaveVersionNumber17()
        {
            foreach (var file in Directory.GetFiles(TestPrefetchMain.Win2k3Path, "*.pf"))
            {
                var pf = PrefetchFile.Open(file);

                pf.SourceFilename.Should().Be(file);
                pf.Header.Version.Should().Be(Version.WinXpOrWin2K3);
            }
        }
Exemplo n.º 14
0
        public void OneOff()
        {
            var f = @"C:\temp\fsout.bin";

            var ms = new FileStream(f, FileMode.Open);

            var pf = PrefetchFile.Open(ms, "foo");

            pf.RunCount.Should().BeGreaterThan(0);
            pf.RunCount.Should().Be(3);

            //   pf.Should().NotBe(null);
        }
Exemplo n.º 15
0
        public void OneOff()
        {
            var f = @"C:\Temp\500sru\POWERSHELL.EXE-767FB1AE.pf";

            var ms = new FileStream(f, FileMode.Open, FileAccess.Read);

            var pf = PrefetchFile.Open(ms, "foo");


            var aa = PrefetchFile.Open(f);


            pf.RunCount.Should().BeGreaterThan(0);
            pf.RunCount.Should().Be(3);

            //   pf.Should().NotBe(null);
        }
Exemplo n.º 16
0
        public void SignatureShouldBeSCCA()
        {
            foreach (var allPath in _allPaths)
            {
                foreach (var file in Directory.GetFiles(allPath, "*.pf"))
                {
                    var pf = PrefetchFile.Open(file);

                    pf.Should().NotBe(null);

                    pf.Filenames.Count.Should().Be(pf.FileMetricsCount);

                    pf.VolumeCount.Should().Be(pf.VolumeInformation.Count);

                    pf.Header.Signature.Should().Be("SCCA");
                }
            }
        }
Exemplo n.º 17
0
        public void Windows2012ShouldHaveVersionNumber26()
        {
            foreach (var file in Directory.GetFiles(TestPrefetchMain.Win2012Path, "*.pf"))
            {
                var pf = PrefetchFile.Open(file);

                pf.SourceFilename.Should().Be(file);
                pf.Header.Version.Should().Be(Version.Win8xOrWin2012x);
            }

            foreach (var file in Directory.GetFiles(TestPrefetchMain.Win2012R2Path, "*.pf"))
            {
                var pf = PrefetchFile.Open(file);

                pf.SourceFilename.Should().Be(file);
                pf.Header.Version.Should().Be(Version.Win8xOrWin2012x);
            }
        }
Exemplo n.º 18
0
        public void Windows8xShouldHaveVersionNumber26()
        {
            foreach (var file in Directory.GetFiles(TestPrefetchMain.Win8xPath, "*.pf"))
            {
                var pf = PrefetchFile.Open(file);

                var totalDirs = 0;
                foreach (var volumeInfo in pf.VolumeInformation)
                {
                    totalDirs += volumeInfo.DirectoryNames.Count;
                }

                pf.TotalDirectoryCount.Should().Be(totalDirs);

                pf.SourceFilename.Should().Be(file);
                pf.Header.Version.Should().Be(Version.Win8xOrWin2012x);
            }
        }
Exemplo n.º 19
0
        public void TestWin10DcodeDecodePfProperties()
        {
            var file = Path.Combine(TestPrefetchMain.Win10Path, @"DCODEDCODEDCODEDCODEDCODEDCOD-E65B9FE8.pf");
            var pf   = PrefetchFile.Open(file);

            //PrefetchFile.DumpToJson(pf, true, @"D:\temp\DCODEDCODEDCODEDCODEDCODEDCOD.json");

            pf.Header.ExecutableFilename.Should().Be("DCODEDCODEDCODEDCODEDCODEDCOD");
            pf.Header.Hash.Should().Be("E65B9FE8");
            pf.Header.FileSize.Should().Be(33606);
            pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-13T15: 47:25.7480759-07:00"));
            pf.RunCount.Should().Be(2);

            pf.VolumeCount.Should().Be(2);
            pf.VolumeInformation[0].DeviceName.Should().Be(@"\VOLUME{01d12173f395296c-66f451bc}");
            pf.VolumeInformation[0].SerialNumber.Should().Be("66F451BC");
            pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2015-11-17T13:10:06.2049644-07:00"));

            pf.VolumeInformation[1].DeviceName.Should().Be(@"\VOLUME{01d1217a9c4c6779-8c9f49ec}");
            pf.VolumeInformation[1].SerialNumber.Should().Be("8C9F49EC");
            pf.VolumeInformation[1].CreationTime.Should().Be(DateTimeOffset.Parse("2015-11-17T13:57:46.2434681-07:00"));


            pf.VolumeInformation[1].DirectoryNames.Count.Should().Be(19);

            pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(1);
            pf.VolumeInformation[0].DirectoryNames[0].Should()
            .Be(@"\VOLUME{01d12173f395296c-66f451bc}\TEMP");

            pf.VolumeInformation[0].FileReferences.Count.Should().Be(2);
            pf.VolumeInformation[1].FileReferences.Count.Should().Be(85);


            pf.Filenames.Count.Should().Be(57);
            pf.Filenames[3].Should().Be(@"\VOLUME{01d1217a9c4c6779-8c9f49ec}\WINDOWS\SYSTEM32\KERNEL32.DLL");

            pf.VolumeInformation[1].FileReferences[12].MFTEntryNumber.Should().Be((ulong)357876);
            pf.VolumeInformation[1].FileReferences[12].MFTSequenceNumber.Should().Be(1);

            pf.VolumeInformation[0].FileReferences[1].MFTEntryNumber.Should().Be((ulong)305846);
            pf.VolumeInformation[0].FileReferences[1].MFTSequenceNumber.Should().Be(2);
        }
Exemplo n.º 20
0
        public void TestWin7DCodePfProperties()
        {
            var file = Path.Combine(TestPrefetchMain.Win7Path, @"DCODEDCODEDCODEDCODEDCODEDCOD-9054DA3F.pf");
            var pf   = PrefetchFile.Open(file);

            // PrefetchFile.DumpToJson(pf, true, @"D:\temp\win7DCODEDCODEDCODEDCODEDCODEDCOD.json");

            pf.Header.ExecutableFilename.Should().Be("DCODEDCODEDCODEDCODEDCODEDCOD");
            pf.Header.Hash.Should().Be("9054DA3F");
            pf.Header.FileSize.Should().Be(29746);
            pf.LastRunTimes[0].Should().Be(DateTimeOffset.Parse("2016-01-22T09: 23:16.3416250-07:00"));
            pf.RunCount.Should().Be(5);

            pf.VolumeCount.Should().Be(2);
            pf.VolumeInformation[0].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME2");
            pf.VolumeInformation[0].SerialNumber.Should().Be("88008C2F");
            pf.VolumeInformation[0].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-16T14:15:18.1093750-07:00"));

            pf.VolumeInformation[0].DirectoryNames.Count.Should().Be(14);
            pf.VolumeInformation[0].DirectoryNames[3].Should()
            .Be(@"\DEVICE\HARDDISKVOLUME2\USERS\E\APPDATA\LOCAL");

            pf.VolumeInformation[0].FileReferences.Count.Should().Be(63);

            pf.VolumeInformation[1].DeviceName.Should().Be(@"\DEVICE\HARDDISKVOLUME3");
            pf.VolumeInformation[1].SerialNumber.Should().Be("E892367F");
            pf.VolumeInformation[1].CreationTime.Should().Be(DateTimeOffset.Parse("2016-01-22T09:11:36.5781250-07:00"));

            pf.VolumeInformation[1].DirectoryNames.Count.Should().Be(2);
            pf.VolumeInformation[1].DirectoryNames[1].Should()
            .Be(@"\DEVICE\HARDDISKVOLUME3\TEMP\222");

            pf.VolumeInformation[1].FileReferences.Count.Should().Be(3);

            pf.Filenames.Count.Should().Be(50);
            pf.Filenames[3].Should().Be(@"\DEVICE\HARDDISKVOLUME2\WINDOWS\SYSTEM32\WOW64CPU.DLL");

            pf.VolumeInformation[1].FileReferences[1].MFTEntryNumber.Should().Be((ulong)37);
            pf.VolumeInformation[1].FileReferences[1].MFTSequenceNumber.Should().Be(1);
        }
Exemplo n.º 21
0
        private static IPrefetch LoadFile(string pfFile)
        {
            if (_fluentCommandLineParser.Object.Quiet == false)
            {
                _logger.Warn($"Processing '{pfFile}'");
                _logger.Info("");
            }


            var sw = new Stopwatch();

            sw.Start();

            try
            {
                var pf = PrefetchFile.Open(pfFile);

                if (pf.ParsingError)
                {
                    _failedFiles.Add($"'{pfFile}' is corrupt and did not parse completely!");
                    _logger.Fatal($"'{pfFile}' FILE DID NOT PARSE COMPLETELY!\r\n");
                }

                if (_fluentCommandLineParser.Object.Quiet == false)
                {
                    if (pf.ParsingError)
                    {
                        _logger.Fatal("PARTIAL OUTPUT SHOWN BELOW\r\n");
                    }


                    var created = _fluentCommandLineParser.Object.LocalTime
                        ? pf.SourceCreatedOn.ToLocalTime()
                        : pf.SourceCreatedOn;
                    var modified = _fluentCommandLineParser.Object.LocalTime
                        ? pf.SourceModifiedOn.ToLocalTime()
                        : pf.SourceModifiedOn;
                    var accessed = _fluentCommandLineParser.Object.LocalTime
                        ? pf.SourceAccessedOn.ToLocalTime()
                        : pf.SourceAccessedOn;

                    _logger.Info($"Created on: {created.ToString(_fluentCommandLineParser.Object.DateTimeFormat)}");
                    _logger.Info($"Modified on: {modified.ToString(_fluentCommandLineParser.Object.DateTimeFormat)}");
                    _logger.Info(
                        $"Last accessed on: {accessed.ToString(_fluentCommandLineParser.Object.DateTimeFormat)}");
                    _logger.Info("");

                    var dirString = pf.TotalDirectoryCount.ToString(CultureInfo.InvariantCulture);
                    var dd        = new string('0', dirString.Length);
                    var dirFormat = $"{dd}.##";

                    var fString    = pf.FileMetricsCount.ToString(CultureInfo.InvariantCulture);
                    var ff         = new string('0', fString.Length);
                    var fileFormat = $"{ff}.##";

                    _logger.Info($"Executable name: {pf.Header.ExecutableFilename}");
                    _logger.Info($"Hash: {pf.Header.Hash}");
                    _logger.Info($"File size (bytes): {pf.Header.FileSize:N0}");
                    _logger.Info($"Version: {GetDescriptionFromEnumValue(pf.Header.Version)}");
                    _logger.Info("");

                    _logger.Info($"Run count: {pf.RunCount:N0}");

                    var lastRun = pf.LastRunTimes.First();
                    if (_fluentCommandLineParser.Object.LocalTime)
                    {
                        lastRun = lastRun.ToLocalTime();
                    }

                    _logger.Warn($"Last run: {lastRun.ToString(_fluentCommandLineParser.Object.DateTimeFormat)}");

                    if (pf.LastRunTimes.Count > 1)
                    {
                        var lastRuns = pf.LastRunTimes.Skip(1).ToList();

                        if (_fluentCommandLineParser.Object.LocalTime)
                        {
                            for (var i = 0; i < lastRuns.Count; i++)
                            {
                                lastRuns[i] = lastRuns[i].ToLocalTime();
                            }
                        }


                        var otherRunTimes = string.Join(", ",
                                                        lastRuns.Select(t => t.ToString(_fluentCommandLineParser.Object.DateTimeFormat)));

                        _logger.Info($"Other run times: {otherRunTimes}");
                    }

//
//                if (_fluentCommandLineParser.Object.Quiet == false)
//                {
                    _logger.Info("");
                    _logger.Info("Volume information:");
                    _logger.Info("");
                    var volnum = 0;

                    foreach (var volumeInfo in pf.VolumeInformation)
                    {
                        var localCreate = volumeInfo.CreationTime;
                        if (_fluentCommandLineParser.Object.LocalTime)
                        {
                            localCreate = localCreate.ToLocalTime();
                        }

                        _logger.Info(
                            $"#{volnum}: Name: {volumeInfo.DeviceName} Serial: {volumeInfo.SerialNumber} Created: {localCreate.ToString(_fluentCommandLineParser.Object.DateTimeFormat)} Directories: {volumeInfo.DirectoryNames.Count:N0} File references: {volumeInfo.FileReferences.Count:N0}");
                        volnum += 1;
                    }

                    _logger.Info("");

                    var totalDirs = pf.TotalDirectoryCount;
                    if (pf.Header.Version == Version.WinXpOrWin2K3)
                    {
                        totalDirs = 0;
                        //this has -1 for total directories, so we have to calculate it
                        foreach (var volumeInfo in pf.VolumeInformation)
                        {
                            totalDirs += volumeInfo.DirectoryNames.Count;
                        }
                    }

                    _logger.Info($"Directories referenced: {totalDirs:N0}");
                    _logger.Info("");
                    var dirIndex = 0;
                    foreach (var volumeInfo in pf.VolumeInformation)
                    {
                        foreach (var directoryName in volumeInfo.DirectoryNames)
                        {
                            var found = false;
                            foreach (var keyword in _keywords)
                            {
                                if (directoryName.ToLower().Contains(keyword))
                                {
                                    _logger.Fatal($"{dirIndex.ToString(dirFormat)}: {directoryName}");
                                    found = true;
                                    break;
                                }
                            }

                            if (!found)
                            {
                                _logger.Info($"{dirIndex.ToString(dirFormat)}: {directoryName}");
                            }

                            dirIndex += 1;
                        }
                    }

                    _logger.Info("");

                    _logger.Info($"Files referenced: {pf.Filenames.Count:N0}");
                    _logger.Info("");
                    var fileIndex = 0;

                    foreach (var filename in pf.Filenames)
                    {
                        if (filename.Contains(pf.Header.ExecutableFilename))
                        {
                            _logger.Error($"{fileIndex.ToString(fileFormat)}: {filename}");
                        }
                        else
                        {
                            var found = false;
                            foreach (var keyword in _keywords)
                            {
                                if (filename.ToLower().Contains(keyword))
                                {
                                    _logger.Fatal($"{fileIndex.ToString(fileFormat)}: {filename}");
                                    found = true;
                                    break;
                                }
                            }

                            if (!found)
                            {
                                _logger.Info($"{fileIndex.ToString(fileFormat)}: {filename}");
                            }
                        }

                        fileIndex += 1;
                    }
                }

                sw.Stop();

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

                _logger.Info(
                    $"---------- Processed '{pf.SourceFilename}' in {sw.Elapsed.TotalSeconds:N8} seconds ----------");

                if (_fluentCommandLineParser.Object.Quiet == false)
                {
                    _logger.Info("\r\n");
                }

                return(pf);
            }
            catch (ArgumentNullException an)
            {
                _logger.Error(
                    $"Error opening '{pfFile}'.\r\n\r\nThis appears to be a Windows 10 prefetch file. You must be running Windows 8 or higher to decompress Windows 10 prefetch files");
                _logger.Info("");
                _failedFiles.Add(
                    $"{pfFile} ==> ({an.Message} (This appears to be a Windows 10 prefetch file. You must be running Windows 8 or higher to decompress Windows 10 prefetch files))");
            }
            catch (Exception ex)
            {
                _logger.Error($"Error opening '{pfFile}'. Message: {ex.Message}");
                _logger.Info("");

                _failedFiles.Add($"{pfFile} ==> ({ex.Message})");
            }

            return(null);
        }
Exemplo n.º 22
0
        private static void Main(string[] args)
        {
            ExceptionlessClient.Default.Startup("x3MPpeQSBUUsXl3DjekRQ9kYjyN3cr5JuwdoOBpZ");

            SetupNLog();

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

            _logger = LogManager.GetCurrentClassLogger();

            if (!CheckForDotnet46())
            {
                _logger.Warn(".net 4.6 not detected. Please install .net 4.6 and try again.");
                return;
            }

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

            _fluentCommandLineParser.Setup(arg => arg.CsvSeparator)
            .As("cs")
            .WithDescription(
                "When true, use comma instead of tab for field separator. Default is true").SetDefault(true);

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

            if (_fluentCommandLineParser.Object.CsvSeparator)
            {
                _exportExt = "csv";
            }

            _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;

                try
                {
                    pfFiles = 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.{_exportExt}";
                        var outNameTl = $"{DateTimeOffset.Now:yyyyMMddHHmmss}_PECmd_Output_Timeline.{_exportExt}";
                        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);
                            if (_fluentCommandLineParser.Object.CsvSeparator == false)
                            {
                                csv.Configuration.Delimiter = "\t";
                            }

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

                            streamWriterTl = new StreamWriter(outFileTl);
                            csvTl          = new CsvWriter(streamWriterTl);
                            if (_fluentCommandLineParser.Object.CsvSeparator == false)
                            {
                                csvTl.Configuration.Delimiter = "\t";
                            }

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