public AmcacheOld(string hive, bool recoverDeleted, bool noLogs) { _logger = LogManager.GetLogger("AmcacheOld"); RegistryHive reg; var dirname = Path.GetDirectoryName(hive); var hiveBase = Path.GetFileName(hive); List <RawCopy.RawCopyReturn> rawFiles = null; try { reg = new RegistryHive(hive) { RecoverDeleted = true }; } catch (IOException) { //file is in use if (RawCopy.Helper.IsAdministrator() == false) { throw new UnauthorizedAccessException("Administrator privileges not found!"); } _logger.Warn($"'{hive}' is in use. Rerouting...\r\n"); var files = new List <string>(); files.Add(hive); var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?"); foreach (var logFile in logFiles) { files.Add(logFile); } rawFiles = RawCopy.Helper.GetFiles(files); var b = new byte[rawFiles.First().FileStream.Length]; rawFiles.First().FileStream.Read(b, 0, (int)rawFiles.First().FileStream.Length); reg = new RegistryHive(b, rawFiles.First().InputFilename); } if (reg.Header.PrimarySequenceNumber != reg.Header.SecondarySequenceNumber) { if (string.IsNullOrEmpty(dirname)) { dirname = "."; } var logFiles = Directory.GetFiles(dirname, $"{hiveBase}.LOG?"); var log = LogManager.GetCurrentClassLogger(); if (logFiles.Length == 0) { if (noLogs == false) { log.Warn("Registry hive is dirty and no transaction logs were found in the same directory! LOGs should have same base name as the hive. Aborting!!"); throw new Exception("Sequence numbers do not match and transaction logs were not found in the same directory as the hive. Aborting"); } else { log.Warn("Registry hive is dirty and no transaction logs were found in the same directory. Data may be missing! Continuing anyways..."); } } else { if (noLogs == false) { if (rawFiles != null) { var lt = new List <TransactionLogFileInfo>(); foreach (var rawCopyReturn in rawFiles.Skip(1).ToList()) { var b = new byte[rawCopyReturn.FileStream.Length]; rawCopyReturn.FileStream.Read(b, 0, (int)rawCopyReturn.FileStream.Length); var tt = new TransactionLogFileInfo(rawCopyReturn.InputFilename, b); lt.Add(tt); } reg.ProcessTransactionLogs(lt, true); } else { reg.ProcessTransactionLogs(logFiles.ToList(), true); } } else { log.Warn("Registry hive is dirty and transaction logs were found in the same directory, but --nl was provided. Data may be missing! Continuing anyways..."); } } } reg.ParseHive(); var fileKey = reg.GetKey(@"Root\File"); var programsKey = reg.GetKey(@"Root\Programs"); UnassociatedFileEntries = new List <FileEntryOld>(); ProgramsEntries = new List <ProgramsEntryOld>(); if (fileKey == null || programsKey == null) { _logger.Error("Hive does not contain a File and/or Programs key. Processing cannot continue"); return; } //First, we get data for all the Program entries under Programs key _logger.Debug("Getting Programs data"); foreach (var registryKey in programsKey.SubKeys) { var ProgramName0 = ""; var ProgramVersion1 = ""; var Guid10 = ""; var UninstallGuid11 = ""; var Guid12 = ""; var Dword13 = 0; var Dword14 = 0; var Dword15 = 0; var UnknownBytes = new byte[0]; long Qword17 = 0; var Dword18 = 0; var VenderName2 = ""; var LocaleID3 = ""; var Dword5 = 0; var InstallSource6 = ""; var UninstallKey7 = ""; DateTimeOffset?EpochA = null; DateTimeOffset?EpochB = null; var PathListd = ""; var Guidf = ""; var RawFiles = ""; try { foreach (var value in registryKey.Values) { switch (value.ValueName) { case "0": ProgramName0 = value.ValueData; break; case "1": ProgramVersion1 = value.ValueData; break; case "2": VenderName2 = value.ValueData; break; case "3": LocaleID3 = value.ValueData; break; case "5": Dword5 = int.Parse(value.ValueData); break; case "6": InstallSource6 = value.ValueData; break; case "7": UninstallKey7 = value.ValueData; break; case "a": try { var seca = long.Parse(value.ValueData); if (seca > 0) { EpochA = DateTimeOffset.FromUnixTimeSeconds(seca).ToUniversalTime(); } } catch (Exception) { //sometimes the number is way too big } break; case "b": var seconds = long.Parse(value.ValueData); if (seconds > 0) { EpochB = DateTimeOffset.FromUnixTimeSeconds(seconds).ToUniversalTime(); } break; case "d": PathListd = value.ValueData; break; case "f": Guidf = value.ValueData; break; case "10": Guid10 = value.ValueData; break; case "11": UninstallGuid11 = value.ValueData; break; case "12": Guid12 = value.ValueData; break; case "13": Dword13 = int.Parse(value.ValueData); break; case "14": Dword13 = int.Parse(value.ValueData); break; case "15": Dword13 = int.Parse(value.ValueData); break; case "16": UnknownBytes = value.ValueDataRaw; break; case "17": Qword17 = long.Parse(value.ValueData); break; case "18": Dword18 = int.Parse(value.ValueData); break; case "Files": RawFiles = value.ValueData; break; default: _logger.Warn( $"Unknown value name in Program at path {registryKey.KeyPath}: {value.ValueName}"); break; } } var pe = new ProgramsEntryOld(ProgramName0, ProgramVersion1, VenderName2, LocaleID3, InstallSource6, UninstallKey7, Guid10, Guid12, UninstallGuid11, Dword5, Dword13, Dword14, Dword15, UnknownBytes, Qword17, Dword18, EpochA, EpochB, PathListd, Guidf, RawFiles, registryKey.KeyName, registryKey.LastWriteTime.Value); ProgramsEntries.Add(pe); } catch (Exception ex) { _logger.Error($"Error parsing ProgramsEntry at {registryKey.KeyPath}. Error: {ex.Message}"); _logger.Error( $"Please send the following text to [email protected]. \r\n\r\nKey data: {registryKey}"); } } //For each Programs entry, add the related Files entries from Files\Volume subkey, put the rest in unassociated _logger.Debug("Getting Files data"); foreach (var registryKey in fileKey.SubKeys) { //These are the guids for volumes foreach (var subKey in registryKey.SubKeys) { var prodName = ""; int?langId = null; var fileVerString = ""; var fileVerNum = ""; var fileDesc = ""; var compName = ""; var fullPath = ""; var switchBack = ""; var peHash = ""; var progID = ""; var sha = ""; long binProdVersion = 0; ulong binFileVersion = 0; var linkerVersion = 0; var binType = 0; var isLocal = 0; var gProgramID = 0; int? fileSize = null; int? sizeOfImage = null; uint? peHeaderChecksum = null; DateTimeOffset?created = null; DateTimeOffset?lm = null; DateTimeOffset?lmStore = null; DateTimeOffset?linkDate = null; var hasLinkedProgram = false; try { //these are the files executed from the volume foreach (var keyValue in subKey.Values) { var keyVal = int.Parse(keyValue.ValueName, NumberStyles.HexNumber); switch (keyVal) { case ProductName: prodName = keyValue.ValueData; break; case CompanyName: compName = keyValue.ValueData; break; case FileVersionNumber: fileVerNum = keyValue.ValueData; break; case LanguageCode: langId = int.Parse(keyValue.ValueData); break; case SwitchBackContext: switchBack = keyValue.ValueData; break; case FileVersionString: fileVerString = keyValue.ValueData; break; case FileSize: fileSize = int.Parse(keyValue.ValueData); break; case SizeOfImage: sizeOfImage = int.Parse(keyValue.ValueData); break; case PEHeaderHash: peHash = keyValue.ValueData; break; case PEHeaderChecksum: peHeaderChecksum = uint.Parse(keyValue.ValueData); break; case BinProductVersion: binProdVersion = long.Parse(keyValue.ValueData); break; case BinFileVersion: binFileVersion = ulong.Parse(keyValue.ValueData); break; case FileDescription: fileDesc = keyValue.ValueData; break; case LinkerVersion: linkerVersion = int.Parse(keyValue.ValueData); break; case LinkDate: linkDate = DateTimeOffset.FromUnixTimeSeconds(long.Parse(keyValue.ValueData)) .ToUniversalTime(); break; case BinaryType: binType = int.Parse(keyValue.ValueData); break; case LastModified: lm = DateTimeOffset.FromFileTime(long.Parse(keyValue.ValueData)).ToUniversalTime(); break; case Created: created = DateTimeOffset.FromFileTime(long.Parse(keyValue.ValueData)).ToUniversalTime(); break; case FullPath: fullPath = keyValue.ValueData; break; case IsLocal: isLocal = int.Parse(keyValue.ValueData); break; case GuessProgramID: gProgramID = int.Parse(keyValue.ValueData); break; case LastModifiedStore: lmStore = DateTimeOffset.FromFileTime(long.Parse(keyValue.ValueData)) .ToUniversalTime(); break; case ProgramID: progID = keyValue.ValueData; var program = ProgramsEntries.SingleOrDefault(t => t.ProgramID == progID); if (program != null) { hasLinkedProgram = true; } break; case SHA1: sha = keyValue.ValueData; break; default: _logger.Warn( $"Unknown value name when processing FileEntry at path '{subKey.KeyPath}': 0x{keyVal:X}"); break; } } if (fullPath.Length == 0) { continue; } TotalFileEntries += 1; var fe = new FileEntryOld(prodName, progID, sha, fullPath, lmStore, registryKey.KeyName, registryKey.LastWriteTime.Value, subKey.KeyName, subKey.LastWriteTime.Value, isLocal, compName, langId, fileVerString, peHash, fileVerNum, fileDesc, binProdVersion, binFileVersion, linkerVersion, binType, switchBack, fileSize, linkDate, sizeOfImage, lm, created, peHeaderChecksum, gProgramID, subKey.KeyName); if (hasLinkedProgram) { var program = ProgramsEntries.SingleOrDefault(t => t.ProgramID == fe.ProgramID); fe.ProgramName = program.ProgramName_0; program.FileEntries.Add(fe); } else { fe.ProgramName = "Unassociated"; UnassociatedFileEntries.Add(fe); } } catch (Exception ex) { _logger.Error($"Error parsing FileEntry at {subKey.KeyPath}. Error: {ex.Message}"); _logger.Error( $"Please send the following text to [email protected]. \r\n\r\nKey data: {subKey}"); } } } }
public AmcacheOld(string hive, bool recoverDeleted) { _logger = LogManager.GetCurrentClassLogger(); var reg = new RegistryHive(hive) { RecoverDeleted = recoverDeleted }; reg.ParseHive(); var fileKey = reg.GetKey(@"Root\File"); var programsKey = reg.GetKey(@"Root\Programs"); UnassociatedFileEntries = new List <FileEntryOld>(); ProgramsEntries = new List <ProgramsEntryOld>(); if (fileKey == null || programsKey == null) { _logger.Error($"Hive does not contain a File and/or Programs key. Processing cannot continue"); return; } //First, we get data for all the Program entries under Programs key foreach (var registryKey in programsKey.SubKeys) { var ProgramName0 = ""; var ProgramVersion1 = ""; var Guid10 = ""; var UninstallGuid11 = ""; var Guid12 = ""; var Dword13 = 0; var Dword14 = 0; var Dword15 = 0; var UnknownBytes = new byte[0]; long Qword17 = 0; var Dword18 = 0; var VenderName2 = ""; var LocaleID3 = ""; var Dword5 = 0; var InstallSource6 = ""; var UninstallKey7 = ""; DateTimeOffset?EpochA = null; DateTimeOffset?EpochB = null; var PathListd = ""; var Guidf = ""; var RawFiles = ""; try { foreach (var value in registryKey.Values) { switch (value.ValueName) { case "0": ProgramName0 = value.ValueData; break; case "1": ProgramVersion1 = value.ValueData; break; case "2": VenderName2 = value.ValueData; break; case "3": LocaleID3 = value.ValueData; break; case "5": Dword5 = int.Parse(value.ValueData); break; case "6": InstallSource6 = value.ValueData; break; case "7": UninstallKey7 = value.ValueData; break; case "a": try { var seca = long.Parse(value.ValueData); if (seca > 0) { EpochA = DateTimeOffset.FromUnixTimeSeconds(seca).ToUniversalTime(); } } catch (Exception) { //sometimes the number is way too big } break; case "b": var seconds = long.Parse(value.ValueData); if (seconds > 0) { EpochB = DateTimeOffset.FromUnixTimeSeconds(seconds).ToUniversalTime(); } break; case "d": PathListd = value.ValueData; break; case "f": Guidf = value.ValueData; break; case "10": Guid10 = value.ValueData; break; case "11": UninstallGuid11 = value.ValueData; break; case "12": Guid12 = value.ValueData; break; case "13": Dword13 = int.Parse(value.ValueData); break; case "14": Dword13 = int.Parse(value.ValueData); break; case "15": Dword13 = int.Parse(value.ValueData); break; case "16": UnknownBytes = value.ValueDataRaw; break; case "17": Qword17 = long.Parse(value.ValueData); break; case "18": Dword18 = int.Parse(value.ValueData); break; case "Files": RawFiles = value.ValueData; break; default: _logger.Warn( $"Unknown value name in Program at path {registryKey.KeyPath}: {value.ValueName}"); break; } } var pe = new ProgramsEntryOld(ProgramName0, ProgramVersion1, VenderName2, LocaleID3, InstallSource6, UninstallKey7, Guid10, Guid12, UninstallGuid11, Dword5, Dword13, Dword14, Dword15, UnknownBytes, Qword17, Dword18, EpochA, EpochB, PathListd, Guidf, RawFiles, registryKey.KeyName, registryKey.LastWriteTime.Value); ProgramsEntries.Add(pe); } catch (Exception ex) { _logger.Error($"Error parsing ProgramsEntry at {registryKey.KeyPath}. Error: {ex.Message}"); _logger.Error( $"Please send the following text to [email protected]. \r\n\r\nKey data: {registryKey}"); } } //For each Programs entry, add the related Files entries from Files\Volume subkey, put the rest in unassociated foreach (var registryKey in fileKey.SubKeys) { //These are the guids for volumes foreach (var subKey in registryKey.SubKeys) { var prodName = ""; int?langId = null; var fileVerString = ""; var fileVerNum = ""; var fileDesc = ""; var compName = ""; var fullPath = ""; var switchBack = ""; var peHash = ""; var progID = ""; var sha = ""; long binProdVersion = 0; ulong binFileVersion = 0; var linkerVersion = 0; var binType = 0; var isLocal = 0; var gProgramID = 0; int? fileSize = null; int? sizeOfImage = null; int? peHeaderChecksum = null; DateTimeOffset?created = null; DateTimeOffset?lm = null; DateTimeOffset?lmStore = null; DateTimeOffset?linkDate = null; var hasLinkedProgram = false; try { //these are the files executed from the volume foreach (var keyValue in subKey.Values) { var keyVal = int.Parse(keyValue.ValueName, NumberStyles.HexNumber); switch (keyVal) { case ProductName: prodName = keyValue.ValueData; break; case CompanyName: compName = keyValue.ValueData; break; case FileVersionNumber: fileVerNum = keyValue.ValueData; break; case LanguageCode: langId = int.Parse(keyValue.ValueData); break; case SwitchBackContext: switchBack = keyValue.ValueData; break; case FileVersionString: fileVerString = keyValue.ValueData; break; case FileSize: fileSize = int.Parse(keyValue.ValueData); break; case SizeOfImage: sizeOfImage = int.Parse(keyValue.ValueData); break; case PEHeaderHash: peHash = keyValue.ValueData; break; case PEHeaderChecksum: peHeaderChecksum = int.Parse(keyValue.ValueData); break; case BinProductVersion: binProdVersion = long.Parse(keyValue.ValueData); break; case BinFileVersion: binFileVersion = ulong.Parse(keyValue.ValueData); break; case FileDescription: fileDesc = keyValue.ValueData; break; case LinkerVersion: linkerVersion = int.Parse(keyValue.ValueData); break; case LinkDate: linkDate = DateTimeOffset.FromUnixTimeSeconds(long.Parse(keyValue.ValueData)) .ToUniversalTime(); break; case BinaryType: binType = int.Parse(keyValue.ValueData); break; case LastModified: lm = DateTimeOffset.FromFileTime(long.Parse(keyValue.ValueData)).ToUniversalTime(); break; case Created: created = DateTimeOffset.FromFileTime(long.Parse(keyValue.ValueData)).ToUniversalTime(); break; case FullPath: fullPath = keyValue.ValueData; break; case IsLocal: isLocal = int.Parse(keyValue.ValueData); break; case GuessProgramID: gProgramID = int.Parse(keyValue.ValueData); break; case LastModifiedStore: lmStore = DateTimeOffset.FromFileTime(long.Parse(keyValue.ValueData)).ToUniversalTime(); break; case ProgramID: progID = keyValue.ValueData; var program = ProgramsEntries.SingleOrDefault(t => t.ProgramID == progID); if (program != null) { hasLinkedProgram = true; } break; case SHA1: sha = keyValue.ValueData; break; default: _logger.Warn( $"Unknown value name when processing FileEntry at path '{subKey.KeyPath}': 0x{keyVal:X}"); break; } } if (fullPath.Length == 0) { continue; } TotalFileEntries += 1; var fe = new FileEntryOld(prodName, progID, sha, fullPath, lmStore, registryKey.KeyName, registryKey.LastWriteTime.Value, subKey.KeyName, subKey.LastWriteTime.Value, isLocal, compName, langId, fileVerString, peHash, fileVerNum, fileDesc, binProdVersion, binFileVersion, linkerVersion, binType, switchBack, fileSize, linkDate, sizeOfImage, lm, created, peHeaderChecksum, gProgramID, subKey.KeyName); if (hasLinkedProgram) { var program = ProgramsEntries.SingleOrDefault(t => t.ProgramID == fe.ProgramID); fe.ProgramName = program.ProgramName_0; program.FileEntries.Add(fe); } else { fe.ProgramName = "Unassociated"; UnassociatedFileEntries.Add(fe); } } catch (Exception ex) { _logger.Error($"Error parsing FileEntry at {subKey.KeyPath}. Error: {ex.Message}"); _logger.Error( $"Please send the following text to [email protected]. \r\n\r\nKey data: {subKey}"); } } } }