Ejemplo n.º 1
0
        public void ShouldExportHiveWithRootValues()
        {
            var samRootValue = new RegistryHive(@"..\..\..\Hives\SAM_RootValue");

            samRootValue.FlushRecordListsAfterParse = false;
            samRootValue.ParseHive();

            samRootValue.ExportDataToCommonFormat(@"SamRootValueNoDeletedStuff.txt", false);
        }
Ejemplo n.º 2
0
        public void ShouldExportFileAllRecords()
        {
            var usrclassDeleted = new RegistryHive(@"..\..\..\Hives\UsrClassDeletedBags.dat");

            usrclassDeleted.RecoverDeleted             = true;
            usrclassDeleted.FlushRecordListsAfterParse = false;
            usrclassDeleted.ParseHive();

            usrclassDeleted.ExportDataToCommonFormat(@"UsrclassDeletedNoDeletedStuff.txt", false);

            Check.That(usrclassDeleted.Header.Length).IsEqualTo(usrclassDeleted.HBinRecordTotalSize);
        }
Ejemplo n.º 3
0
        public void ExportUsrClassToCommonFormatWithDeleted()
        {
            var UsrclassDeleted = new RegistryHive(@"..\..\Hives\UsrClassDeletedBags.dat");

            UsrclassDeleted.RecoverDeleted             = true;
            UsrclassDeleted.FlushRecordListsAfterParse = false;
            UsrclassDeleted.ParseHive();

            UsrclassDeleted.ExportDataToCommonFormat("UsrClassDeletedExport.txt", true);

            UsrclassDeleted = new RegistryHive(@"..\..\Hives\UsrClassDeletedBags.dat");
            UsrclassDeleted.FlushRecordListsAfterParse = true;
            UsrclassDeleted.ParseHive();

            UsrclassDeleted.ExportDataToCommonFormat("UsrClassDeletedWithFlushExport.txt", true);
        }
Ejemplo n.º 4
0
        private static void Main(string[] args)
        {
            var testFiles = new List<string>();

            var result = Parser.Default.ParseArguments<Options>(args);

            if (!result.Errors.Any())
            {
                if (result.Value.HiveName == null && result.Value.DirectoryName == null)
                {
                    Console.WriteLine(result.Value.GetUsage());
                    Environment.Exit(1);
                }

                if (!string.IsNullOrEmpty(result.Value.HiveName))
                {
                    if (!string.IsNullOrEmpty(result.Value.DirectoryName))
                    {
                        Console.WriteLine("Must specify either -d or -f, but not both");
                        Environment.Exit(1);
                    }
                }

                if (!string.IsNullOrEmpty(result.Value.DirectoryName))
                {
                    if (!string.IsNullOrEmpty(result.Value.HiveName))
                    {
                        Console.WriteLine("Must specify either -d or -f, but not both");
                        Environment.Exit(1);
                    }
                }

                if (!string.IsNullOrEmpty(result.Value.HiveName))
                {
                    testFiles.Add(result.Value.HiveName);
                }
                else
                {
                    if (Directory.Exists(result.Value.DirectoryName))
                    {
                        foreach (var file in Directory.GetFiles(result.Value.DirectoryName))
                        {
                            testFiles.Add(file);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Directory '{0}' does not exist!", result.Value.DirectoryName);
                        Environment.Exit(1);
                    }
                }
            }
            else
            {
                Console.WriteLine(result.Value.GetUsage());
                Environment.Exit(1);
            }

            var verboseLevel = result.Value.VerboseLevel;
            if (verboseLevel < 0)
            {
                verboseLevel = 0;
            }

            if (verboseLevel > 2)
            {
                verboseLevel = 2;
            }

            var config = GetNlogConfig(verboseLevel, Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
            LogManager.Configuration = config;

            var logger = LogManager.GetCurrentClassLogger();

            foreach (var testFile in testFiles)
            {
                if (File.Exists(testFile) == false)
                {
                    logger.Error("'{0}' does not exist!", testFile);
                    continue;
                }

                logger.Info("Processing '{0}'", testFile);
                Console.Title = $"Processing '{testFile}'";

                var sw = new Stopwatch();
                try
                {
                    var registryHive = new RegistryHive(testFile);
                    if (registryHive.Header.HasValidateCheckSum() == false)
                    {
                        logger.Warn("CheckSum mismatch!");
                    }

                    if (registryHive.Header.PrimarySequenceNumber != registryHive.Header.SecondarySequenceNumber)
                    {
                        logger.Warn("Sequence mismatch!");
                    }

                    sw.Start();

                    registryHive.RecoverDeleted = result.Value.RecoverDeleted;

                    registryHive.FlushRecordListsAfterParse = !result.Value.DontFlushLists;

                    registryHive.ParseHive();

                    logger.Info("Finished processing '{0}'", testFile);

                    Console.Title = $"Finished processing '{testFile}'";

                    sw.Stop();

                    var freeCells = registryHive.CellRecords.Where(t => t.Value.IsFree);
                    var referencedCells = registryHive.CellRecords.Where(t => t.Value.IsReferenced);

                    var nkFree = freeCells.Count(t => t.Value is NkCellRecord);
                    var vkFree = freeCells.Count(t => t.Value is VkCellRecord);
                    var skFree = freeCells.Count(t => t.Value is SkCellRecord);
                    var lkFree = freeCells.Count(t => t.Value is LkCellRecord);

                    var freeLists = registryHive.ListRecords.Where(t => t.Value.IsFree);
                    var referencedList = registryHive.ListRecords.Where(t => t.Value.IsReferenced);

                    var goofyCellsShouldBeUsed = registryHive.CellRecords.Where(t => t.Value.IsFree == false && t.Value.IsReferenced == false);

                    var goofyListsShouldBeUsed = registryHive.ListRecords.Where(t => t.Value.IsFree == false && t.Value.IsReferenced == false);

                    var sb = new StringBuilder();

                    sb.AppendLine("Results:");
                    sb.AppendLine();

                    sb.AppendLine($"Found {registryHive.HBinRecordCount:N0} hbin records. Total size of seen hbin records: 0x{registryHive.HBinRecordTotalSize:X}, Header hive size: 0x{registryHive.Header.Length:X}");

                    if (registryHive.FlushRecordListsAfterParse == false)
                    {
                        sb.AppendLine($"Found {registryHive.CellRecords.Count:N0} Cell records (nk: {registryHive.CellRecords.Count(w => w.Value is NkCellRecord):N0}, vk: {registryHive.CellRecords.Count(w => w.Value is VkCellRecord):N0}, sk: {registryHive.CellRecords.Count(w => w.Value is SkCellRecord):N0}, lk: {registryHive.CellRecords.Count(w => w.Value is LkCellRecord):N0})");
                        sb.AppendLine($"Found {registryHive.ListRecords.Count:N0} List records");
                        sb.AppendLine();
                        sb.AppendLine(string.Format($"Header CheckSums match: {registryHive.Header.HasValidateCheckSum()}"));
                        sb.AppendLine(string.Format($"Header sequence 1: {registryHive.Header.PrimarySequenceNumber}, Header sequence 2: {registryHive.Header.SecondarySequenceNumber}"));

                        sb.AppendLine();

                        sb.AppendLine($"There are {referencedCells.Count():N0} cell records marked as being referenced ({referencedCells.Count() / (double)registryHive.CellRecords.Count:P})");
                        sb.AppendLine($"There are {referencedList.Count():N0} list records marked as being referenced ({referencedList.Count() / (double)registryHive.ListRecords.Count:P})");

                        if (result.Value.RecoverDeleted)
                        {
                            sb.AppendLine();
                            sb.AppendLine("Free record info");
                            sb.AppendLine($"{freeCells.Count():N0} free Cell records (nk: {nkFree:N0}, vk: {vkFree:N0}, sk: {skFree:N0}, lk: {lkFree:N0})");
                            sb.AppendLine($"{freeLists.Count():N0} free List records");
                        }

                        sb.AppendLine();
                        sb.AppendLine($"Cells: Free + referenced + marked as in use but not referenced == Total? {registryHive.CellRecords.Count == freeCells.Count() + referencedCells.Count() + goofyCellsShouldBeUsed.Count()}");
                        sb.AppendLine($"Lists: Free + referenced + marked as in use but not referenced == Total? {registryHive.ListRecords.Count == freeLists.Count() + referencedList.Count() + goofyListsShouldBeUsed.Count()}");
                    }

                    sb.AppendLine();
                    sb.AppendLine($"There were {registryHive.HardParsingErrors:N0} hard parsing errors (a record marked 'in use' that didn't parse correctly.)");
                    sb.AppendLine($"There were {registryHive.SoftParsingErrors:N0} soft parsing errors (a record marked 'free' that didn't parse correctly.)");

                    logger.Info(sb.ToString());

                    //                    foreach (var cellTemplate in fName1Test.ListRecords)
                    //                    {
                    //                        Console.WriteLine(cellTemplate.ToString());
                    //                    }

                    if (result.Value.ExportHiveData)
                    {
                        Console.WriteLine();

                        var baseDir = Path.Combine(Path.GetDirectoryName(testFile), "out");

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

                        var baseFname = Path.GetFileName(testFile);

                        var myName = string.Empty;

                        var deletedOnly = result.Value.ExportDeletedOnly;

                        if (deletedOnly)
                        {
                            myName = "_EricZ_recovered.txt";
                        }
                        else
                        {
                            myName = "_EricZ_all.txt";
                        }

                        var outfile = Path.Combine(baseDir, $"{baseFname}{myName}");

                        logger.Info("Exporting hive data to '{0}'", outfile);

                        registryHive.ExportDataToCommonFormat(outfile, deletedOnly);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("There was an error: {0}", ex.Message);
                }

                logger.Info("Processing took {0:N4} seconds\r\n", sw.Elapsed.TotalSeconds);

                Console.WriteLine();
                Console.WriteLine();

                if (result.Value.PauseAfterEachFile)
                {
                    Console.WriteLine("Press any key to continue to next file");
                    Console.ReadKey();

                    Console.WriteLine();
                    Console.WriteLine();
                }
            }
        }
Ejemplo n.º 5
0
        public void ExportUsrClassToCommonFormatWithDeleted()
        {
            var UsrclassDeleted = new RegistryHive(@"..\..\Hives\UsrClassDeletedBags.dat");
            UsrclassDeleted.RecoverDeleted = true;
            UsrclassDeleted.FlushRecordListsAfterParse = false;
            UsrclassDeleted.ParseHive();

            UsrclassDeleted.ExportDataToCommonFormat("UsrClassDeletedExport.txt", true);

            UsrclassDeleted = new RegistryHive(@"..\..\Hives\UsrClassDeletedBags.dat");
            UsrclassDeleted.FlushRecordListsAfterParse = true;
            UsrclassDeleted.ParseHive();

            UsrclassDeleted.ExportDataToCommonFormat("UsrClassDeletedWithFlushExport.txt", true);
        }
Ejemplo n.º 6
0
        private static void ProcessFile(string arg)
        {
            FileInfo fi = new FileInfo(arg);

            if (fi.Length < 4 || !IsRegistryFile(arg))
            {
                return;
            }

            byte[]       raw = File.ReadAllBytes(arg);
            RegistryHive reg = new RegistryHive(raw, arg)
            {
                RecoverDeleted             = true,
                FlushRecordListsAfterParse = false
            };

            string name;

            using (FileStream fs = new FileStream(arg, FileMode.Open, FileAccess.Read))
            {
                name = Hashes.CalculateMD5FromStream(fs);
            }
            string path = $"regdrop/{name}";

            Directory.CreateDirectory(path);

            File.WriteAllText($"{path}/info.txt", reg.Header.ToString());

            if (!reg.Header.ValidateCheckSum())
            {
                Console.Error.WriteLine("Checksum validation error. Exiting.");
                return;
            }

            if (reg.Header.PrimarySequenceNumber != reg.Header.SecondarySequenceNumber)
            {
                string filePath = Path.GetDirectoryName(arg);
                string fileName = Path.GetFileNameWithoutExtension(arg);
                var    logFiles = Directory.GetFiles(filePath, $"{fileName}.LOG?");

                if (logFiles.Length == 0)
                {
                    Console.Error.WriteLine($"[{arg}] Transaction logs missing. Exiting.");
                    return;
                }
                else
                {
                    reg.ProcessTransactionLogs(logFiles.ToList(), true);
                }
            }

            reg.ParseHive();

            string dumpFilePathTmp = $"{path}/dump.tmp";

            reg.ExportDataToCommonFormat(dumpFilePathTmp, false);

            string dumpFilePathCsv  = $"{path}/dump.csv";
            string dumpFilePathJson = $"{path}/dump.json";

            using (DataTable dt = new DataTable())
            {
                dt.Columns.Add("type", typeof(string));
                dt.Columns.Add("active", typeof(string));
                dt.Columns.Add("offset", typeof(decimal));
                dt.Columns.Add("path", typeof(string));
                dt.Columns.Add("name", typeof(string));
                dt.Columns.Add("dataType", typeof(decimal));
                dt.Columns.Add("value", typeof(string));
                dt.Columns.Add("lastWriteTime", typeof(string));

                using (var fs = new FileStream(dumpFilePathTmp, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    dt.FromCsv(fs, false);
                }

                DataColumn type = dt.Columns["type"];
                foreach (var dr in dt.Rows
                         .OfType <DataRow>()
                         .Where(x => (string)x[type] == "value"))
                {
                    DataColumn dataType    = dt.Columns["dataType"];
                    DataColumn value       = dt.Columns["value"];
                    byte[]     data        = ConvertToBytes((string)dr[value]);
                    decimal    dataTypeVal = (decimal)dr[dataType];

                    if (dataTypeVal == 0x2)
                    {
                        string txt = Encoding.Unicode.GetString(data).TrimEnd('\0');
                        dr[value] = txt;
                    }
                    else if (dataTypeVal == 0x4 && data.Length == 4)
                    {
                        int val = BitConverter.ToInt32(data);
                        dr[value] = val.ToString();
                    }
                    else if (dataTypeVal == 0x5 && data.Length == 4)
                    {
                        int val = BitConverter.ToInt32(data.Reverse().ToArray());
                        dr[value] = val.ToString();
                    }
                    else if (dataTypeVal == 0x7)
                    {
                        string   txtlist = Encoding.Unicode.GetString(data).TrimEnd('\0');
                        string[] split   = txtlist.Split('\0', StringSplitOptions.RemoveEmptyEntries);
                        dr[value] = string.Join("\n", split);
                    }
                    else if (dataTypeVal == 0xb && data.Length == 8)
                    {
                        long val = BitConverter.ToInt64(data);
                        dr[value] = val.ToString();
                    }
                    else
                    {
                        dr[value] = Convert.ToBase64String(data);
                    }
                }

                using (var fs = new FileStream(dumpFilePathCsv, FileMode.Create, FileAccess.Write, FileShare.Read))
                {
                    dt.ToCsv(fs);
                }

                JsonDocument jdoc;
                dt.ToJson(out jdoc);
                using (var fs = new FileStream(dumpFilePathJson, FileMode.Create, FileAccess.Write, FileShare.Read))
                {
                    Utf8JsonWriter writer = new Utf8JsonWriter(fs);
                    jdoc.WriteTo(writer);
                    writer.Flush();
                }
            }

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