private static int RunVerifyRulesCommand(VerifyOptions opts) { #if DEBUG Logger.Setup(true, opts.Verbose, opts.Quiet); #else Logger.Setup(opts.Debug, opts.Verbose, opts.Quiet); #endif var analyzer = new Analyzer(AsaHelpers.GetPlatform(), opts.AnalysisFile); if (analyzer.VerifyRules()) { return((int)ASA_ERROR.NONE); } return((int)ASA_ERROR.INVALID_RULES); }
public void TestRunIdToPlatform() { DatabaseManager.Setup("asa.sqlite"); var run1 = new AsaRun("Run1", DateTime.Now, "Version", AsaHelpers.GetPlatform(), new List <RESULT_TYPE>() { RESULT_TYPE.CERTIFICATE }, RUN_TYPE.COLLECT); DatabaseManager.InsertRun(run1); var platform = DatabaseManager.RunIdToPlatform("Run1"); Assert.IsTrue(run1.Platform == platform); }
public void TestFirewallCollectorWindows() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Assert.IsTrue(AsaHelpers.IsAdmin()); var rule = FirewallManager.Instance.CreatePortRule( @"TestFirewallPortRule", FirewallAction.Allow, 9999, FirewallProtocol.TCP ); FirewallManager.Instance.Rules.Add(rule); rule = FirewallManager.Instance.CreateApplicationRule( @"TestFirewallAppRule", FirewallAction.Allow, @"C:\MyApp.exe" ); rule.Direction = FirewallDirection.Outbound; FirewallManager.Instance.Rules.Add(rule); var fwc = new FirewallCollector(); fwc.TryExecute(); Assert.IsTrue(fwc.Results.Any(x => x is FirewallObject FWO && FWO.LocalPorts.Contains("9999"))); Assert.IsTrue(fwc.Results.Any(x => x is FirewallObject FWO && FWO.ApplicationName is string && FWO.ApplicationName.Equals(@"C:\MyApp.exe"))); ConcurrentStack <CollectObject> results = new ConcurrentStack <CollectObject>(); fwc = new FirewallCollector(changeHandler: x => results.Push(x)); fwc.TryExecute(); Assert.IsTrue(results.Any(x => x is FirewallObject FWO && FWO.LocalPorts.Contains("9999"))); Assert.IsTrue(results.Any(x => x is FirewallObject FWO && FWO.ApplicationName is string && FWO.ApplicationName.Equals(@"C:\MyApp.exe"))); var rules = FirewallManager.Instance.Rules.Where(r => r.Name == "TestFirewallPortRule"); foreach (var ruleIn in rules) { FirewallManager.Instance.Rules.Remove(ruleIn); } rules = FirewallManager.Instance.Rules.Where(r => r.Name == "TestFirewallAppRule"); foreach (var ruleIn in rules) { FirewallManager.Instance.Rules.Remove(ruleIn); } } }
public void TestFileCollector() { Setup(); var FirstRunId = "TestFileCollector-1"; var SecondRunId = "TestFileCollector-2"; var testFolder = AsaHelpers.GetTempFolder(); Directory.CreateDirectory(testFolder); var fsc = new FileSystemCollector(FirstRunId, enableHashing: true, directories: testFolder, downloadCloud: false, examineCertificates: true); fsc.Execute(); using (var file = File.Open(Path.Combine(testFolder, "AsaLibTesterMZ"), FileMode.OpenOrCreate)) { file.Write(FileSystemUtils.WindowsMagicNumber, 0, 2); file.Write(FileSystemUtils.WindowsMagicNumber, 0, 2); file.Close(); } using (var file = File.Open(Path.Combine(testFolder, "AsaLibTesterJavaClass"), FileMode.OpenOrCreate)) { file.Write(FileSystemUtils.JavaMagicNumber, 0, 4); file.Close(); } fsc = new FileSystemCollector(SecondRunId, enableHashing: true, directories: testFolder, downloadCloud: false, examineCertificates: true); fsc.Execute(); BaseCompare bc = new BaseCompare(); if (!bc.TryCompare(FirstRunId, SecondRunId)) { Assert.Fail(); } var results = bc.Results; Assert.IsTrue(results.ContainsKey("FILE_CREATED")); Assert.IsTrue(results["FILE_CREATED"].Where(x => x.Identity.Contains("AsaLibTesterMZ") && ((FileSystemObject)x.Compare).IsExecutable == true).Any()); Assert.IsTrue(results["FILE_CREATED"].Where(x => x.Identity.Contains("AsaLibTesterJavaClass") && ((FileSystemObject)x.Compare).IsExecutable == true).Any()); TearDown(); }
public void TestFileCollector() { var testFolder = AsaHelpers.GetTempFolder(); Directory.CreateDirectory(testFolder); var opts = new CollectorOptions() { EnableFileSystemCollector = true, GatherHashes = true, SelectedDirectories = new List <string>() { testFolder }, DownloadCloud = false, }; using (var file = File.Open(Path.Combine(testFolder, "AsaLibTesterMZ"), FileMode.OpenOrCreate)) { file.Write(FileSystemUtils.WindowsMagicNumber, 0, 2); file.Write(FileSystemUtils.WindowsMagicNumber, 0, 2); file.Close(); } using (var file = File.Open(Path.Combine(testFolder, "AsaLibTesterJavaClass"), FileMode.OpenOrCreate)) { file.Write(FileSystemUtils.JavaMagicNumber, 0, 4); file.Close(); } var fsc = new FileSystemCollector(opts); fsc.TryExecute(); Assert.IsTrue(fsc.Results.Any(x => x is FileSystemObject FSO && FSO.Path.EndsWith("AsaLibTesterJavaClass") && FSO.IsExecutable == true)); Assert.IsTrue(fsc.Results.Any(x => x is FileSystemObject FSO && FSO.Path.EndsWith("AsaLibTesterMZ") && FSO.IsExecutable == true)); ConcurrentStack <CollectObject> results = new ConcurrentStack <CollectObject>(); fsc = new FileSystemCollector(opts, x => results.Push(x)); fsc.TryExecute(); Assert.IsTrue(results.Any(x => x is FileSystemObject FSO && FSO.Path.EndsWith("AsaLibTesterJavaClass") && FSO.IsExecutable == true)); Assert.IsTrue(results.Any(x => x is FileSystemObject FSO && FSO.Path.EndsWith("AsaLibTesterMZ") && FSO.IsExecutable == true)); }
private static int RunVerifyRulesCommand(VerifyOptions opts) { #if DEBUG Logger.Setup(true, opts.Verbose, opts.Quiet); #else Logger.Setup(opts.Debug, opts.Verbose, opts.Quiet); #endif var analyzer = new Analyzer(AsaHelpers.GetPlatform(), opts.AnalysisFile); var violations = analyzer.VerifyRules(); Analyzer.PrintViolations(violations); if (violations.Any()) { Log.Error("Encountered {0} issues with rules at {1}", violations.Count, opts.AnalysisFile ?? "Embedded"); return((int)ASA_ERROR.INVALID_RULES); } Log.Information("Rules successfully verified. ✅"); return((int)ASA_ERROR.NONE); }
public ActionResult GetResults(string BaseId, string CompareId, int ResultType, int Offset, int NumResults) { var results = new List <CompareResult>(); using (var cmd = new SqliteCommand(GET_COMPARISON_RESULTS, DatabaseManager.Connection, DatabaseManager.Transaction)) { cmd.Parameters.AddWithValue("@comparison_id", AsaHelpers.RunIdsToCompareId(BaseId, CompareId)); cmd.Parameters.AddWithValue("@result_type", ResultType); cmd.Parameters.AddWithValue("@offset", Offset); cmd.Parameters.AddWithValue("@limit", NumResults); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var obj = JsonConvert.DeserializeObject <CompareResult>(reader["serialized"].ToString()); results.Add(obj); } } } Dictionary <string, object> output = new Dictionary <string, object>(); var result_count = 0; using (var cmd = new SqliteCommand(GET_RESULT_COUNT, DatabaseManager.Connection, DatabaseManager.Transaction)) { cmd.Parameters.AddWithValue("@comparison_id", AsaHelpers.RunIdsToCompareId(BaseId, CompareId)); cmd.Parameters.AddWithValue("@result_type", ResultType); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { result_count = int.Parse(reader["count(*)"].ToString(), CultureInfo.InvariantCulture); } } } output["Results"] = results; output["TotalCount"] = result_count; output["Offset"] = Offset; output["Requested"] = NumResults; output["Actual"] = results.Count; return(Json(JsonConvert.SerializeObject(output))); }
public ActionResult StartMonitoring(string RunId, string Directory, string Extension) { if (RunId != null) { using (var cmd = new SqliteCommand(INSERT_RUN, DatabaseManager.Connection, DatabaseManager.Transaction)) { cmd.Parameters.AddWithValue("@run_id", RunId.Trim()); cmd.Parameters.AddWithValue("@file_system", true); cmd.Parameters.AddWithValue("@ports", false); cmd.Parameters.AddWithValue("@users", false); cmd.Parameters.AddWithValue("@services", false); cmd.Parameters.AddWithValue("@registry", false); cmd.Parameters.AddWithValue("@certificates", false); cmd.Parameters.AddWithValue("@firewall", false); cmd.Parameters.AddWithValue("@comobjects", false); cmd.Parameters.AddWithValue("@type", "monitor"); cmd.Parameters.AddWithValue("@timestamp", DateTime.Now.ToString("o", CultureInfo.InvariantCulture)); cmd.Parameters.AddWithValue("@version", AsaHelpers.GetVersionString()); cmd.Parameters.AddWithValue("@platform", AsaHelpers.GetPlatformString()); try { cmd.ExecuteNonQuery(); DatabaseManager.Commit(); } catch (SqliteException e) { Log.Warning(e.StackTrace); Log.Warning(e.Message); return(Json((int)GUI_ERROR.UNIQUE_ID)); } } MonitorCommandOptions opts = new MonitorCommandOptions { RunId = RunId, EnableFileSystemMonitor = true, MonitoredDirectories = Directory, FilterLocation = "filters.json" }; AttackSurfaceAnalyzerClient.ClearMonitors(); return(Json((int)AttackSurfaceAnalyzerClient.RunGuiMonitorCommand(opts))); } return(Json(-1)); }
public void TestUserCollectorWindows() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Assert.IsTrue(AsaHelpers.IsAdmin()); var user = System.Guid.NewGuid().ToString().Substring(0, 10); var password = "******" + CryptoHelpers.GetRandomString(13); var cmd = string.Format("user /add {0} {1}", user, password); ExternalCommandRunner.RunExternalCommand("net", cmd); var uac = new UserAccountCollector(); uac.Execute(); Assert.IsTrue(uac.Results.Any(x => x is UserAccountObject y && y.Name.Equals(user))); cmd = string.Format("user /delete {0}", user); ExternalCommandRunner.RunExternalCommand("net", cmd); } }
public void TestUserCollectorWindows() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Assert.IsTrue(AsaHelpers.IsAdmin()); Setup(); var FirstRunId = "TestUserCollector-1"; var SecondRunId = "TestUserCollector-2"; var fwc = new UserAccountCollector(FirstRunId); fwc.Execute(); var user = System.Guid.NewGuid().ToString().Substring(0, 10); var password = System.Guid.NewGuid().ToString().Substring(0, 10); var cmd = string.Format("user /add {0} {1}", user, password); ExternalCommandRunner.RunExternalCommand("net", cmd); var serviceName = System.Guid.NewGuid(); fwc = new UserAccountCollector(SecondRunId); fwc.Execute(); cmd = string.Format("user /delete {0}", user); ExternalCommandRunner.RunExternalCommand("net", cmd); BaseCompare bc = new BaseCompare(); if (!bc.TryCompare(FirstRunId, SecondRunId)) { Assert.Fail(); } var results = bc.Results; Assert.IsTrue(results.ContainsKey("USER_CREATED")); Assert.IsTrue(results["USER_CREATED"].Where(x => x.Identity.Contains(user)).Count() > 0); TearDown(); } }
public void TestGetLatestRunIds() { DatabaseManager.Setup("asa.sqlite"); var run1 = new AsaRun("Run1", DateTime.Now, "Version", AsaHelpers.GetPlatform(), new List <RESULT_TYPE>() { RESULT_TYPE.CERTIFICATE }, RUN_TYPE.COLLECT); var run2 = new AsaRun("Run2", DateTime.Now, "Version", AsaHelpers.GetPlatform(), new List <RESULT_TYPE>() { RESULT_TYPE.CERTIFICATE }, RUN_TYPE.COLLECT); var run3 = new AsaRun("Run3", DateTime.Now, "Version", AsaHelpers.GetPlatform(), new List <RESULT_TYPE>() { RESULT_TYPE.CERTIFICATE }, RUN_TYPE.COLLECT); DatabaseManager.InsertRun(run1); DatabaseManager.InsertRun(run2); DatabaseManager.InsertRun(run3); var runids = DatabaseManager.GetLatestRunIds(10, RUN_TYPE.COLLECT); Assert.IsTrue(runids.Count == 3); }
public override void ExecuteInternal() { foreach (var hive in Hives) { Log.Debug("Starting " + hive.ToString()); if (!Filter.IsFiltered(AsaHelpers.GetPlatformString(), "Scan", "Registry", "Hive", "Include", hive.ToString()) && Filter.IsFiltered(AsaHelpers.GetPlatformString(), "Scan", "Registry", "Hive", "Exclude", hive.ToString(), out Regex? Capturer)) { Log.Debug("{0} '{1}' {2} '{3}'.", Strings.Get("ExcludingHive"), hive.ToString(), Strings.Get("DueToFilter"), Capturer?.ToString()); return; } Action <RegistryKey, RegistryView> IterateOn = (registryKey, registryView) => { try { var regObj = RegistryWalker.RegistryKeyToRegistryObject(registryKey, registryView); if (regObj != null) { DatabaseManager.Write(regObj, RunId); } } catch (InvalidOperationException e) { Log.Debug(e, JsonSerializer.Serialize(registryKey) + " invalid op exept"); } }; Filter.IsFiltered(AsaHelpers.GetPlatformString(), "Scan", "Registry", "Key", "Exclude", hive.ToString()); var x86_Enumerable = RegistryWalker.WalkHive(hive, RegistryView.Registry32); var x64_Enumerable = RegistryWalker.WalkHive(hive, RegistryView.Registry64); if (Parallelize) { Parallel.ForEach(x86_Enumerable, (registryKey => { IterateOn(registryKey, RegistryView.Registry32); })); Parallel.ForEach(x86_Enumerable, (registryKey => { IterateOn(registryKey, RegistryView.Registry64); })); } else { foreach (var registryKey in x86_Enumerable) { IterateOn(registryKey, RegistryView.Registry32); } foreach (var registryKey in x64_Enumerable) { IterateOn(registryKey, RegistryView.Registry64); } } Log.Debug("Finished " + hive.ToString()); } }
public static int RunCollectCommand(CollectCommandOptions opts) { if (opts == null) { return(-1); } #if DEBUG Logger.Setup(true, opts.Verbose, opts.Quiet); #else Logger.Setup(opts.Debug, opts.Verbose, opts.Quiet); #endif var dbSettings = new DBSettings() { ShardingFactor = opts.Shards }; SetupOrDie(opts.DatabaseFilename, dbSettings); AsaTelemetry.Setup(); Dictionary <string, string> StartEvent = new Dictionary <string, string>(); StartEvent.Add("Files", opts.EnableAllCollectors ? "True" : opts.EnableFileSystemCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Ports", opts.EnableNetworkPortCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Users", opts.EnableUserCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Certificates", opts.EnableCertificateCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Registry", opts.EnableRegistryCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Service", opts.EnableServiceCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Firewall", opts.EnableFirewallCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("ComObject", opts.EnableComObjectCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("EventLog", opts.EnableEventLogCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Admin", AsaHelpers.IsAdmin().ToString(CultureInfo.InvariantCulture)); AsaTelemetry.TrackEvent("Run Command", StartEvent); AdminOrQuit(); CheckFirstRun(); int returnValue = (int)ASA_ERROR.NONE; opts.RunId = opts.RunId?.Trim() ?? DateTime.Now.ToString("o", CultureInfo.InvariantCulture); if (opts.MatchedCollectorId != null) { var matchedRun = DatabaseManager.GetRun(opts.MatchedCollectorId); if (matchedRun is AsaRun) { foreach (var resultType in matchedRun.ResultTypes) { switch (resultType) { case RESULT_TYPE.FILE: opts.EnableFileSystemCollector = true; break; case RESULT_TYPE.PORT: opts.EnableNetworkPortCollector = true; break; case RESULT_TYPE.CERTIFICATE: opts.EnableCertificateCollector = true; break; case RESULT_TYPE.COM: opts.EnableComObjectCollector = true; break; case RESULT_TYPE.FIREWALL: opts.EnableFirewallCollector = true; break; case RESULT_TYPE.LOG: opts.EnableEventLogCollector = true; break; case RESULT_TYPE.SERVICE: opts.EnableServiceCollector = true; break; case RESULT_TYPE.USER: opts.EnableUserCollector = true; break; } } } } var dict = new List <RESULT_TYPE>(); if (opts.EnableFileSystemCollector || opts.EnableAllCollectors) { collectors.Add(new FileSystemCollector(opts)); dict.Add(RESULT_TYPE.FILE); } if (opts.EnableNetworkPortCollector || opts.EnableAllCollectors) { collectors.Add(new OpenPortCollector(opts.RunId)); dict.Add(RESULT_TYPE.PORT); } if (opts.EnableServiceCollector || opts.EnableAllCollectors) { collectors.Add(new ServiceCollector(opts.RunId)); dict.Add(RESULT_TYPE.SERVICE); } if (opts.EnableUserCollector || opts.EnableAllCollectors) { collectors.Add(new UserAccountCollector(opts.RunId)); dict.Add(RESULT_TYPE.USER); } if (opts.EnableRegistryCollector || (opts.EnableAllCollectors && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))) { collectors.Add(new RegistryCollector(opts.RunId, opts.Parallelization)); dict.Add(RESULT_TYPE.REGISTRY); } if (opts.EnableCertificateCollector || opts.EnableAllCollectors) { collectors.Add(new CertificateCollector(opts.RunId)); dict.Add(RESULT_TYPE.CERTIFICATE); } if (opts.EnableFirewallCollector || opts.EnableAllCollectors) { collectors.Add(new FirewallCollector(opts.RunId)); dict.Add(RESULT_TYPE.FIREWALL); } if (opts.EnableComObjectCollector || (opts.EnableAllCollectors && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))) { collectors.Add(new ComObjectCollector(opts.RunId)); dict.Add(RESULT_TYPE.COM); } if (opts.EnableEventLogCollector || opts.EnableAllCollectors) { collectors.Add(new EventLogCollector(opts.RunId, opts.GatherVerboseLogs)); dict.Add(RESULT_TYPE.LOG); } if (collectors.Count == 0) { Log.Warning(Strings.Get("Err_NoCollectors")); return((int)ASA_ERROR.NO_COLLECTORS); } if (opts.Overwrite) { DatabaseManager.DeleteRun(opts.RunId); } else { if (DatabaseManager.GetRun(opts.RunId) != null) { Log.Error(Strings.Get("Err_RunIdAlreadyUsed")); return((int)ASA_ERROR.UNIQUE_ID); } } Log.Information(Strings.Get("Begin"), opts.RunId); var run = new AsaRun(RunId: opts.RunId, Timestamp: DateTime.Now, Version: AsaHelpers.GetVersionString(), Platform: AsaHelpers.GetPlatform(), ResultTypes: dict, Type: RUN_TYPE.COLLECT); DatabaseManager.InsertRun(run); Log.Information(Strings.Get("StartingN"), collectors.Count.ToString(CultureInfo.InvariantCulture), Strings.Get("Collectors")); Console.CancelKeyPress += delegate { Log.Information("Cancelling collection. Rolling back transaction. Please wait to avoid corrupting database."); DatabaseManager.RollBack(); Environment.Exit(-1); }; Dictionary <string, string> EndEvent = new Dictionary <string, string>(); foreach (BaseCollector c in collectors) { try { c.Execute(); EndEvent.Add(c.GetType().ToString(), c.NumCollected().ToString(CultureInfo.InvariantCulture)); } catch (Exception e) { Log.Error(Strings.Get("Err_CollectingFrom"), c.GetType().Name, e.Message, e.StackTrace); Dictionary <string, string> ExceptionEvent = new Dictionary <string, string>(); ExceptionEvent.Add("Exception Type", e.GetType().ToString()); ExceptionEvent.Add("Stack Trace", e.StackTrace ?? string.Empty); ExceptionEvent.Add("Message", e.Message); AsaTelemetry.TrackEvent("CollectorCrashRogueException", ExceptionEvent); returnValue = 1; } } AsaTelemetry.TrackEvent("End Command", EndEvent); DatabaseManager.Commit(); DatabaseManager.CloseDatabase(); return(returnValue); }
public void TestFileCompare() { var FirstRunId = "TestFileCollector-1"; var SecondRunId = "TestFileCollector-2"; var testFolder = AsaHelpers.GetTempFolder(); Directory.CreateDirectory(testFolder); var opts = new CollectCommandOptions() { RunId = FirstRunId, EnableFileSystemCollector = true, GatherHashes = true, SelectedDirectories = testFolder, DownloadCloud = false, CertificatesFromFiles = false }; var fsc = new FileSystemCollector(opts); fsc.Execute(); fsc.Results.AsParallel().ForAll(x => DatabaseManager.Write(x, FirstRunId)); using (var file = File.Open(Path.Combine(testFolder, "AsaLibTesterMZ"), FileMode.OpenOrCreate)) { file.Write(FileSystemUtils.WindowsMagicNumber, 0, 2); file.Write(FileSystemUtils.WindowsMagicNumber, 0, 2); file.Close(); } using (var file = File.Open(Path.Combine(testFolder, "AsaLibTesterJavaClass"), FileMode.OpenOrCreate)) { file.Write(FileSystemUtils.JavaMagicNumber, 0, 4); file.Close(); } opts.RunId = SecondRunId; fsc = new FileSystemCollector(opts); fsc.Execute(); Assert.IsTrue(fsc.Results.Any(x => x is FileSystemObject FSO && FSO.Path.EndsWith("AsaLibTesterMZ"))); Assert.IsTrue(fsc.Results.Any(x => x is FileSystemObject FSO && FSO.Path.EndsWith("AsaLibTesterJavaClass"))); fsc.Results.AsParallel().ForAll(x => DatabaseManager.Write(x, SecondRunId)); while (DatabaseManager.HasElements) { Thread.Sleep(1); } BaseCompare bc = new BaseCompare(); if (!bc.TryCompare(FirstRunId, SecondRunId)) { Assert.Fail(); } var results = bc.Results; Assert.IsTrue(results.ContainsKey((RESULT_TYPE.FILE, CHANGE_TYPE.CREATED))); Assert.IsTrue(results[(RESULT_TYPE.FILE, CHANGE_TYPE.CREATED)].Any(x => x.Identity.Contains("AsaLibTesterMZ") && ((FileSystemObject)x.Compare).IsExecutable == true));
public ActionResult StartMonitoring(string RunId, string Directory) { if (RunId != null) { if (DatabaseManager.GetRun(RunId) != null) { return(Json(ASA_ERROR.UNIQUE_ID)); } var run = new AsaRun(RunId: RunId, Timestamp: DateTime.Now, Version: AsaHelpers.GetVersionString(), Platform: AsaHelpers.GetPlatform(), new List <RESULT_TYPE>() { RESULT_TYPE.FILEMONITOR }, RUN_TYPE.MONITOR); DatabaseManager.InsertRun(run); MonitorCommandOptions opts = new MonitorCommandOptions { RunId = RunId, EnableFileSystemMonitor = true, MonitoredDirectories = Directory, Verbose = Logger.Verbose, Debug = Logger.Debug, Quiet = Logger.Quiet }; AttackSurfaceAnalyzerClient.ClearMonitors(); return(Json((int)AttackSurfaceAnalyzerClient.RunGuiMonitorCommand(opts))); } return(Json(-1)); }
/// <summary> /// Converts a FileSystemInfo into a FileSystemObject by reading in data about the file /// </summary> /// <param name="fileInfo">A reference to a file on disk.</param> /// <param name="downloadCloud"> /// If the file is hosted in the cloud, the user has the option to include cloud files or not. /// </param> /// <param name="includeContentHash">If we should generate a hash of the file.</param> /// <returns></returns> public FileSystemObject FilePathToFileSystemObject(string path) { FileSystemObject obj = new FileSystemObject(path); // Get Owner/Group if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { try { var fileSecurity = new FileSecurity(path, AccessControlSections.Owner); IdentityReference oid = fileSecurity.GetOwner(typeof(SecurityIdentifier)); obj.Owner = AsaHelpers.SidToName(oid); } catch (Exception e) { Log.Verbose("Failed to get owner for {0} ({1}:{2})", path, e.GetType(), e.Message); } try { var fileSecurity = new FileSecurity(path, AccessControlSections.Group); IdentityReference gid = fileSecurity.GetGroup(typeof(SecurityIdentifier)); obj.Group = AsaHelpers.SidToName(gid); } catch (Exception e) { Log.Verbose("Failed to get group for {0} ({1}:{2})", path, e.GetType(), e.Message); } try { var fileSecurity = new FileSecurity(path, AccessControlSections.Access); var rules = fileSecurity.GetAccessRules(true, true, typeof(SecurityIdentifier)); obj.Permissions = new Dictionary <string, string>(); foreach (FileSystemAccessRule?rule in rules) { if (rule != null) { string name = AsaHelpers.SidToName(rule.IdentityReference); foreach (var permission in rule.FileSystemRights.ToString().Split(',')) { if (obj.Permissions.ContainsKey(name)) { obj.Permissions[name] = $"{obj.Permissions[name]},{permission}"; } else { obj.Permissions.Add(name, permission); } } } } } catch (Exception e) { Log.Verbose("Failed to get FileSecurity for {0} ({1}:{2})", path, e.GetType(), e.Message); } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { try { var file = new UnixSymbolicLinkInfo(path); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; obj.Permissions = new Dictionary <string, string>(); if (file.FileAccessPermissions.ToString().Equals("AllPermissions", StringComparison.InvariantCulture)) { obj.Permissions.Add("User", "Read,Write,Execute"); obj.Permissions.Add("Group", "Read,Write,Execute"); obj.Permissions.Add("Other", "Read,Write,Execute"); } else { var keys = new List <string>() { "User", "Group", "Other" }; var splits = file.FileAccessPermissions.ToString().Split(',').Select(x => x.Trim()); foreach (var key in keys) { foreach (var permission in splits.Where((x) => x.StartsWith(key, StringComparison.InvariantCulture))) { if (permission.Contains("ReadWriteExecute", StringComparison.InvariantCulture)) { obj.Permissions.Add(key, "Read,Write,Execute"); } else { if (obj.Permissions.ContainsKey(key)) { obj.Permissions[key] = $"{obj.Permissions[key]},{permission.Trim().Substring(key.Length)}"; } else { obj.Permissions.Add(key, permission.Trim().Substring(key.Length)); } } } } } } catch (Exception e) when( e is ArgumentNullException || e is ArgumentException || e is InvalidOperationException) { Log.Verbose("Failed to get permissions for {0} ({1}:{2})", path, e.GetType(), e.Message); } } try { FileIOPermission fiop = new FileIOPermission(FileIOPermissionAccess.Read, path); fiop.Demand(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (Directory.Exists(path)) { var fileInfo = new DirectoryInfo(path); if (fileInfo.Attributes.HasFlag(FileAttributes.ReparsePoint)) { obj.IsLink = true; obj.Target = NativeMethods.GetFinalPathName(path); } else { obj.IsDirectory = true; } } else { var fileInfo = new FileInfo(path); obj.Size = fileInfo.Length; obj.SizeOnDisk = WindowsSizeOnDisk(fileInfo); // This check is to try to prevent reading of cloud based files (like a // dropbox folder) and subsequently causing a download, unless the user // specifically requests it with DownloadCloud. if (opts.DownloadCloud || obj.SizeOnDisk > 0 || WindowsFileSystemUtils.IsLocal(obj.Path)) { obj.LastModified = File.GetLastWriteTimeUtc(path); obj.Created = File.GetCreationTimeUtc(path); if (opts.GatherHashes == true) { obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo); } var exeType = FileSystemUtils.GetExecutableType(path); if (exeType != EXECUTABLE_TYPE.NONE && exeType != EXECUTABLE_TYPE.UNKNOWN) { obj.IsExecutable = true; } if (exeType == EXECUTABLE_TYPE.WINDOWS) { obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(path); obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(path); } else if (exeType == EXECUTABLE_TYPE.MACOS) { obj.MacSignatureStatus = FileSystemUtils.GetMacSignature(path); } } } } else { UnixSymbolicLinkInfo i = new UnixSymbolicLinkInfo(path); obj.FileType = i.FileType.ToString(); obj.Size = i.Length; obj.IsDirectory = false; switch (i.FileType) { case FileTypes.SymbolicLink: obj.IsLink = true; obj.Target = i.ContentsPath; break; case FileTypes.Fifo: case FileTypes.Socket: case FileTypes.BlockDevice: case FileTypes.CharacterDevice: case FileTypes.Directory: obj.IsDirectory = true; if (path?.EndsWith(".app", StringComparison.InvariantCultureIgnoreCase) ?? false) { obj.MacSignatureStatus = FileSystemUtils.GetMacSignature(path); } break; case FileTypes.RegularFile: var fileInfo = new FileInfo(path); obj.SizeOnDisk = i.BlocksAllocated * i.BlockSize; if (opts.DownloadCloud || obj.SizeOnDisk > 0) { obj.LastModified = File.GetLastWriteTimeUtc(path); obj.Created = File.GetCreationTimeUtc(path); if (opts.GatherHashes) { obj.ContentHash = FileSystemUtils.GetFileHash(path); } var exeType = FileSystemUtils.GetExecutableType(path); if (exeType != EXECUTABLE_TYPE.NONE && exeType != EXECUTABLE_TYPE.UNKNOWN) { obj.IsExecutable = true; } if (exeType == EXECUTABLE_TYPE.WINDOWS) { obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(path); obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(path); } else if (exeType == EXECUTABLE_TYPE.MACOS) { obj.MacSignatureStatus = FileSystemUtils.GetMacSignature(path); } } break; } } } catch (Exception e) when( e is ArgumentNullException || e is SecurityException || e is ArgumentException || e is UnauthorizedAccessException || e is PathTooLongException || e is NotSupportedException || e is InvalidOperationException || e is FileNotFoundException || e is Win32Exception || e is IOException) { Log.Verbose("Failed to create FileInfo from File at {0} ({1}:{2})", path, e.GetType(), e.Message); } catch (Exception e) { Log.Debug("Should be caught in DirectoryWalker {0} {1}", e.GetType().ToString(), path); } try { obj.LastModified = File.GetLastWriteTimeUtc(path); obj.Created = File.GetCreationTimeUtc(path); } catch (Exception e) { Log.Verbose("Failed to get last modified for {0} ({1}:{2})", path, e.GetType(), e.Message); } return(obj); }
public static int RunCollectCommand(CollectCommandOptions opts) { if (opts == null) { return(-1); } #if DEBUG Logger.Setup(true, opts.Verbose, opts.Quiet); #else Logger.Setup(opts.Debug, opts.Verbose, opts.Quiet); #endif var dbSettings = new DBSettings() { ShardingFactor = opts.Shards }; SetupOrDie(opts.DatabaseFilename, dbSettings); AsaTelemetry.Setup(); Dictionary <string, string> StartEvent = new Dictionary <string, string>(); StartEvent.Add("Files", opts.EnableAllCollectors ? "True" : opts.EnableFileSystemCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Ports", opts.EnableNetworkPortCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Users", opts.EnableUserCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Certificates", opts.EnableCertificateCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Registry", opts.EnableRegistryCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Service", opts.EnableServiceCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Firewall", opts.EnableFirewallCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("ComObject", opts.EnableComObjectCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("EventLog", opts.EnableEventLogCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Admin", AsaHelpers.IsAdmin().ToString(CultureInfo.InvariantCulture)); AsaTelemetry.TrackEvent("Run Command", StartEvent); AdminOrQuit(); CheckFirstRun(); int returnValue = (int)ASA_ERROR.NONE; opts.RunId = opts.RunId?.Trim() ?? DateTime.Now.ToString("o", CultureInfo.InvariantCulture); if (opts.MatchedCollectorId != null) { var matchedRun = DatabaseManager.GetRun(opts.MatchedCollectorId); if (matchedRun is AsaRun) { foreach (var resultType in matchedRun.ResultTypes) { switch (resultType) { case RESULT_TYPE.FILE: opts.EnableFileSystemCollector = true; break; case RESULT_TYPE.PORT: opts.EnableNetworkPortCollector = true; break; case RESULT_TYPE.CERTIFICATE: opts.EnableCertificateCollector = true; break; case RESULT_TYPE.COM: opts.EnableComObjectCollector = true; break; case RESULT_TYPE.FIREWALL: opts.EnableFirewallCollector = true; break; case RESULT_TYPE.LOG: opts.EnableEventLogCollector = true; break; case RESULT_TYPE.SERVICE: opts.EnableServiceCollector = true; break; case RESULT_TYPE.USER: opts.EnableUserCollector = true; break; } } } } var dict = new List <RESULT_TYPE>(); if (opts.EnableFileSystemCollector || opts.EnableAllCollectors) { collectors.Add(new FileSystemCollector(opts)); dict.Add(RESULT_TYPE.FILE); } if (opts.EnableNetworkPortCollector || opts.EnableAllCollectors) { collectors.Add(new OpenPortCollector()); dict.Add(RESULT_TYPE.PORT); } if (opts.EnableServiceCollector || opts.EnableAllCollectors) { collectors.Add(new ServiceCollector()); dict.Add(RESULT_TYPE.SERVICE); } if (opts.EnableUserCollector || opts.EnableAllCollectors) { collectors.Add(new UserAccountCollector()); dict.Add(RESULT_TYPE.USER); } if (opts.EnableRegistryCollector || (opts.EnableAllCollectors && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))) { collectors.Add(new RegistryCollector(opts.Parallelization)); dict.Add(RESULT_TYPE.REGISTRY); } if (opts.EnableCertificateCollector || opts.EnableAllCollectors) { collectors.Add(new CertificateCollector()); dict.Add(RESULT_TYPE.CERTIFICATE); } if (opts.EnableFirewallCollector || opts.EnableAllCollectors) { collectors.Add(new FirewallCollector()); dict.Add(RESULT_TYPE.FIREWALL); } if (opts.EnableComObjectCollector || (opts.EnableAllCollectors && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))) { collectors.Add(new ComObjectCollector()); dict.Add(RESULT_TYPE.COM); } if (opts.EnableEventLogCollector || opts.EnableAllCollectors) { collectors.Add(new EventLogCollector(opts.GatherVerboseLogs)); dict.Add(RESULT_TYPE.LOG); } if (collectors.Count == 0) { Log.Warning(Strings.Get("Err_NoCollectors")); return((int)ASA_ERROR.NO_COLLECTORS); } if (opts.Overwrite) { DatabaseManager.DeleteRun(opts.RunId); } else { if (DatabaseManager.GetRun(opts.RunId) != null) { Log.Error(Strings.Get("Err_RunIdAlreadyUsed")); return((int)ASA_ERROR.UNIQUE_ID); } } Log.Information(Strings.Get("Begin"), opts.RunId); var run = new AsaRun(RunId: opts.RunId, Timestamp: DateTime.Now, Version: AsaHelpers.GetVersionString(), Platform: AsaHelpers.GetPlatform(), ResultTypes: dict, Type: RUN_TYPE.COLLECT); DatabaseManager.InsertRun(run); Log.Information(Strings.Get("StartingN"), collectors.Count.ToString(CultureInfo.InvariantCulture), Strings.Get("Collectors")); Console.CancelKeyPress += delegate { Log.Information("Cancelling collection. Rolling back transaction. Please wait to avoid corrupting database."); DatabaseManager.RollBack(); Environment.Exit(-1); }; Dictionary <string, string> EndEvent = new Dictionary <string, string>(); foreach (BaseCollector c in collectors) { try { DatabaseManager.BeginTransaction(); var StopWatch = Stopwatch.StartNew(); Task.Run(() => c.Execute()); Thread.Sleep(1); while (c.RunStatus == RUN_STATUS.RUNNING) { if (c.Results.TryDequeue(out CollectObject? res)) { DatabaseManager.Write(res, opts.RunId); } else { Thread.Sleep(1); } } StopWatch.Stop(); TimeSpan t = TimeSpan.FromMilliseconds(StopWatch.ElapsedMilliseconds); string answer = string.Format(CultureInfo.InvariantCulture, "{0:D2}h:{1:D2}m:{2:D2}s:{3:D3}ms", t.Hours, t.Minutes, t.Seconds, t.Milliseconds); Log.Debug(Strings.Get("Completed"), c.GetType().Name, answer); c.Results.AsParallel().ForAll(x => DatabaseManager.Write(x, opts.RunId)); var prevFlush = DatabaseManager.Connections.Select(x => x.WriteQueue.Count).Sum(); var totFlush = prevFlush; var printInterval = 10; var currentInterval = 0; StopWatch = Stopwatch.StartNew(); while (DatabaseManager.HasElements) { Thread.Sleep(1000); if (currentInterval++ % printInterval == 0) { var actualDuration = (currentInterval < printInterval) ? currentInterval : printInterval; var sample = DatabaseManager.Connections.Select(x => x.WriteQueue.Count).Sum(); var curRate = prevFlush - sample; var totRate = (double)(totFlush - sample) / StopWatch.ElapsedMilliseconds; try { t = (curRate > 0) ? TimeSpan.FromMilliseconds(sample / ((double)curRate / (actualDuration * 1000))) : TimeSpan.FromMilliseconds(99999999); //lgtm[cs/loss-of-precision] answer = string.Format(CultureInfo.InvariantCulture, "{0:D2}h:{1:D2}m:{2:D2}s:{3:D3}ms", t.Hours, t.Minutes, t.Seconds, t.Milliseconds); Log.Debug("Flushing {0} results. ({1}/{4}s {2:0.00}/s overall {3} ETA)", sample, curRate, totRate * 1000, answer, actualDuration); } catch (Exception e) when( e is OverflowException) { Log.Debug($"Overflowed: {curRate} {totRate} {sample} {t} {answer}"); Log.Debug("Flushing {0} results. ({1}/s {2:0.00}/s)", sample, curRate, totRate * 1000); } prevFlush = sample; } } StopWatch.Stop(); t = TimeSpan.FromMilliseconds(StopWatch.ElapsedMilliseconds); answer = string.Format(CultureInfo.InvariantCulture, "{0:D2}h:{1:D2}m:{2:D2}s:{3:D3}ms", t.Hours, t.Minutes, t.Seconds, t.Milliseconds); Log.Debug("Completed flushing in {0}", answer); DatabaseManager.Commit(); } catch (Exception e) { Log.Error(Strings.Get("Err_CollectingFrom"), c.GetType().Name, e.Message, e.StackTrace); Dictionary <string, string> ExceptionEvent = new Dictionary <string, string>(); ExceptionEvent.Add("Exception Type", e.GetType().ToString()); ExceptionEvent.Add("Stack Trace", e.StackTrace ?? string.Empty); ExceptionEvent.Add("Message", e.Message); AsaTelemetry.TrackEvent("CollectorCrashRogueException", ExceptionEvent); returnValue = 1; } } AsaTelemetry.TrackEvent("End Command", EndEvent); DatabaseManager.Commit(); DatabaseManager.CloseDatabase(); return(returnValue); }
private static int RunMonitorCommand(MonitorCommandOptions opts) { #if DEBUG Logger.Setup(true, opts.Verbose); #else Logger.Setup(opts.Debug, opts.Verbose); #endif AdminOrQuit(); SetupOrDie(opts.DatabaseFilename); AsaTelemetry.Setup(); Dictionary <string, string> StartEvent = new Dictionary <string, string>(); StartEvent.Add("Files", opts.EnableFileSystemMonitor.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Admin", AsaHelpers.IsAdmin().ToString(CultureInfo.InvariantCulture)); AsaTelemetry.TrackEvent("Begin monitoring", StartEvent); CheckFirstRun(); if (opts.RunId is string) { opts.RunId = opts.RunId.Trim(); } else { opts.RunId = DateTime.Now.ToString("o", CultureInfo.InvariantCulture); } if (opts.Overwrite) { DatabaseManager.DeleteRun(opts.RunId); } else { if (DatabaseManager.GetRun(opts.RunId) != null) { Log.Error(Strings.Get("Err_RunIdAlreadyUsed")); return((int)ASA_ERROR.UNIQUE_ID); } } var run = new AsaRun(RunId: opts.RunId, Timestamp: DateTime.Now, Version: AsaHelpers.GetVersionString(), Platform: AsaHelpers.GetPlatform(), new List <RESULT_TYPE>() { RESULT_TYPE.FILEMONITOR }, RUN_TYPE.MONITOR); DatabaseManager.InsertRun(run); int returnValue = 0; if (opts.EnableFileSystemMonitor) { List <String> directories = new List <string>(); if (opts.MonitoredDirectories != null) { var parts = opts.MonitoredDirectories.Split(','); foreach (String part in parts) { directories.Add(part); } } else { if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { directories.Add("/"); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { directories.Add("C:\\"); } if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { directories.Add("/"); } } List <NotifyFilters> filterOptions = new List <NotifyFilters> { NotifyFilters.Attributes, NotifyFilters.CreationTime, NotifyFilters.DirectoryName, NotifyFilters.FileName, NotifyFilters.LastAccess, NotifyFilters.LastWrite, NotifyFilters.Security, NotifyFilters.Size }; foreach (String dir in directories) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { var newMon = new FileSystemMonitor(opts.RunId, dir, false); monitors.Add(newMon); } else { foreach (NotifyFilters filter in filterOptions) { Log.Information("Adding Path {0} Filter Type {1}", dir, filter.ToString()); var newMon = new FileSystemMonitor(opts.RunId, dir, false, filter); monitors.Add(newMon); } } } } //if (opts.EnableRegistryMonitor) //{ //var monitor = new RegistryMonitor(); //monitors.Add(monitor); //} if (monitors.Count == 0) { Log.Warning(Strings.Get("Err_NoMonitors")); returnValue = (int)ASA_ERROR.NO_COLLECTORS; } using var exitEvent = new ManualResetEvent(false); // If duration is set, we use the secondary timer. if (opts.Duration > 0) { Log.Information("{0} {1} {2}.", Strings.Get("MonitorStartedFor"), opts.Duration, Strings.Get("Minutes")); using var aTimer = new System.Timers.Timer { Interval = opts.Duration * 60 * 1000, //lgtm [cs/loss-of-precision] AutoReset = false, }; aTimer.Elapsed += (source, e) => { exitEvent.Set(); }; // Start the timer aTimer.Enabled = true; } foreach (FileSystemMonitor c in monitors) { Log.Information(Strings.Get("Begin"), c.GetType().Name); try { c.StartRun(); } catch (Exception ex) { Log.Error(Strings.Get("Err_CollectingFrom"), c.GetType().Name, ex.Message, ex.StackTrace); returnValue = 1; } } // Set up the event to capture CTRL+C Console.CancelKeyPress += (sender, eventArgs) => { eventArgs.Cancel = true; exitEvent.Set(); }; Console.Write(Strings.Get("MonitoringPressC")); // Write a spinner and wait until CTRL+C WriteSpinner(exitEvent); Log.Information(""); foreach (var c in monitors) { Log.Information(Strings.Get("End"), c.GetType().Name); try { c.StopRun(); if (c is FileSystemMonitor) { ((FileSystemMonitor)c).Dispose(); } } catch (Exception ex) { Log.Error(ex, " {0}: {1}", c.GetType().Name, ex.Message, Strings.Get("Err_Stopping")); } } DatabaseManager.Commit(); return(returnValue); }
public static void WriteScanJson(int ResultType, string BaseId, string CompareId, bool ExportAll, string OutputPath) { List <RESULT_TYPE> ToExport = new List <RESULT_TYPE> { (RESULT_TYPE)ResultType }; Dictionary <RESULT_TYPE, int> actualExported = new Dictionary <RESULT_TYPE, int>(); JsonSerializer serializer = JsonSerializer.Create(new JsonSerializerSettings() { Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore, Converters = new List <JsonConverter>() { new StringEnumConverter() } }); if (ExportAll) { ToExport = new List <RESULT_TYPE> { RESULT_TYPE.FILE, RESULT_TYPE.CERTIFICATE, RESULT_TYPE.PORT, RESULT_TYPE.REGISTRY, RESULT_TYPE.SERVICE, RESULT_TYPE.USER }; } foreach (RESULT_TYPE ExportType in ToExport) { Log.Information("Exporting {0}", ExportType); List <CompareResult> records = DatabaseManager.GetComparisonResults(AsaHelpers.RunIdsToCompareId(BaseId, CompareId), ExportType); actualExported.Add(ExportType, records.Count); if (records.Count > 0) { serializer.Converters.Add(new StringEnumConverter()); var o = new Dictionary <string, Object>(); o["results"] = records; o["metadata"] = AsaHelpers.GenerateMetadata(); using (StreamWriter sw = new StreamWriter(Path.Combine(OutputPath, AsaHelpers.MakeValidFileName(BaseId + "_vs_" + CompareId + "_" + ExportType.ToString() + ".json.txt")))) //lgtm [cs/path-injection] { using (JsonWriter writer = new JsonTextWriter(sw)) { serializer.Serialize(writer, o); } } } } serializer.Converters.Add(new StringEnumConverter()); var output = new Dictionary <string, Object>(); output["results"] = actualExported; output["metadata"] = AsaHelpers.GenerateMetadata(); using (StreamWriter sw = new StreamWriter(Path.Combine(OutputPath, AsaHelpers.MakeValidFileName(BaseId + "_vs_" + CompareId + "_summary.json.txt")))) //lgtm [cs/path-injection] { using (JsonWriter writer = new JsonTextWriter(sw)) { serializer.Serialize(writer, output); } } }
private static int RunExportCollectCommand(ExportCollectCommandOptions opts) { #if DEBUG Logger.Setup(true, opts.Verbose, opts.Quiet); #else Logger.Setup(opts.Debug, opts.Verbose, opts.Quiet); #endif if (opts.OutputPath != null && !Directory.Exists(opts.OutputPath)) { Log.Fatal(Strings.Get("Err_OutputPathNotExist"), opts.OutputPath); return(0); } SetupOrDie(opts.DatabaseFilename); CheckFirstRun(); AsaTelemetry.Setup(); if (opts.FirstRunId is null || opts.SecondRunId is null) { Log.Information("Provided null run Ids using latest two runs."); List <string> runIds = DatabaseManager.GetLatestRunIds(2, RUN_TYPE.COLLECT); if (runIds.Count < 2) { Log.Fatal(Strings.Get("Err_CouldntDetermineTwoRun")); System.Environment.Exit(-1); } else { opts.SecondRunId = runIds.First(); opts.FirstRunId = runIds.ElementAt(1); } } if (opts.FirstRunId is null || opts.SecondRunId is null) { return((int)ASA_ERROR.INVALID_ID); } Log.Information(Strings.Get("Comparing"), opts.FirstRunId, opts.SecondRunId); Dictionary <string, string> StartEvent = new Dictionary <string, string>(); StartEvent.Add("OutputPathSet", (opts.OutputPath != null).ToString(CultureInfo.InvariantCulture)); AsaTelemetry.TrackEvent("{0} Export Compare", StartEvent); CompareCommandOptions options = new CompareCommandOptions(opts.FirstRunId, opts.SecondRunId) { DatabaseFilename = opts.DatabaseFilename, AnalysesFile = opts.AnalysesFile, Analyze = opts.Analyze, SaveToDatabase = opts.SaveToDatabase }; var results = CompareRuns(options).Select(x => new KeyValuePair <string, object>($"{x.Key.Item1}_{x.Key.Item2}", x.Value)).ToDictionary(x => x.Key, x => x.Value); JsonSerializer serializer = JsonSerializer.Create(new JsonSerializerSettings() { Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore, Converters = new List <JsonConverter>() { new StringEnumConverter() }, ContractResolver = new AsaExportContractResolver() }); var outputPath = opts.OutputPath; if (outputPath is null) { outputPath = Directory.GetCurrentDirectory(); } if (opts.ExplodedOutput) { results.Add("metadata", AsaHelpers.GenerateMetadata()); string path = Path.Combine(outputPath, AsaHelpers.MakeValidFileName(opts.FirstRunId + "_vs_" + opts.SecondRunId)); Directory.CreateDirectory(path); foreach (var key in results.Keys) { string filePath = Path.Combine(path, AsaHelpers.MakeValidFileName(key)); using (StreamWriter sw = new StreamWriter(filePath)) //lgtm[cs/path-injection] { using (JsonWriter writer = new JsonTextWriter(sw)) { serializer.Serialize(writer, results[key]); } } } Log.Information(Strings.Get("OutputWrittenTo"), (new DirectoryInfo(path)).FullName); } else { string path = Path.Combine(outputPath, AsaHelpers.MakeValidFileName(opts.FirstRunId + "_vs_" + opts.SecondRunId + "_summary.json.txt")); var output = new Dictionary <string, object>(); output["results"] = results; output["metadata"] = AsaHelpers.GenerateMetadata(); using (StreamWriter sw = new StreamWriter(path)) //lgtm[cs/path-injection] { using (JsonWriter writer = new JsonTextWriter(sw)) { serializer.Serialize(writer, output); } } Log.Information(Strings.Get("OutputWrittenTo"), (new FileInfo(path)).FullName); } return(0); }
private static void SleepAndOpenBrowser(int sleep) { Thread.Sleep(sleep); AsaHelpers.OpenBrowser(new System.Uri("http://localhost:5000")); /*DevSkim: ignore DS137138*/ }
public override void ExecuteInternal() { foreach (var hive in Hives) { Log.Debug("Starting " + hive.ToString()); if (!Filter.IsFiltered(AsaHelpers.GetPlatformString(), "Scan", "Registry", "Hive", "Include", hive.ToString()) && Filter.IsFiltered(AsaHelpers.GetPlatformString(), "Scan", "Registry", "Hive", "Exclude", hive.ToString(), out Regex Capturer)) { Log.Debug("{0} '{1}' {2} '{3}'.", Strings.Get("ExcludingHive"), hive.ToString(), Strings.Get("DueToFilter"), Capturer.ToString()); return; } Filter.IsFiltered(AsaHelpers.GetPlatformString(), "Scan", "Registry", "Key", "Exclude", hive.ToString()); var registryInfoEnumerable = RegistryWalker.WalkHive(hive); Parallel.ForEach(registryInfoEnumerable, (registryKey => { try { var regObj = RegistryKeyToRegistryObject(registryKey); if (regObj != null) { DatabaseManager.Write(regObj, RunId); } } catch (InvalidOperationException e) { Log.Debug(e, JsonConvert.SerializeObject(registryKey) + " invalid op exept"); } })); Log.Debug("Finished " + hive.ToString()); } }
/// <summary> /// Converts a FileSystemInfo into a FileSystemObject by reading in data about the file /// </summary> /// <param name="fileInfo">A reference to a file on disk.</param> /// <param name="downloadCloud">If the file is hosted in the cloud, the user has the option to include cloud files or not.</param> /// <param name="includeContentHash">If we should generate a hash of the file.</param> /// <returns></returns> public static FileSystemObject FilePathToFileSystemObject(string path, bool downloadCloud = false, bool includeContentHash = false) { FileSystemObject obj = new FileSystemObject(path); // Get Owner/Group if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { try { var fileSecurity = new FileSecurity(path, AccessControlSections.All); IdentityReference oid = fileSecurity.GetOwner(typeof(SecurityIdentifier)); IdentityReference gid = fileSecurity.GetGroup(typeof(SecurityIdentifier)); obj.Owner = AsaHelpers.SidToName(oid); obj.Group = AsaHelpers.SidToName(gid); var rules = fileSecurity.GetAccessRules(true, true, typeof(SecurityIdentifier)); foreach (FileSystemAccessRule?rule in rules) { if (rule != null) { string name = AsaHelpers.SidToName(rule.IdentityReference); obj.Permissions = new Dictionary <string, string>(); foreach (var permission in rule.FileSystemRights.ToString().Split(',')) { if (obj.Permissions.ContainsKey(name)) { obj.Permissions[name] = $"{obj.Permissions[name]},{permission}"; } else { obj.Permissions.Add(name, permission); } } } } } catch (Exception e) when( e is ArgumentException || e is ArgumentNullException || e is DirectoryNotFoundException || e is FileNotFoundException || e is IOException || e is NotSupportedException || e is PlatformNotSupportedException || e is PathTooLongException || e is PrivilegeNotHeldException || e is SystemException || e is UnauthorizedAccessException) { Log.Verbose($"Error instantiating FileSecurity object {obj.Path} {e.GetType().ToString()}"); } } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { try { var file = new UnixSymbolicLinkInfo(path); obj.Owner = file.OwnerUser.UserName; obj.Group = file.OwnerGroup.GroupName; obj.SetGid = file.IsSetGroup; obj.SetUid = file.IsSetUser; obj.Permissions = new Dictionary <string, string>(); if (file.FileAccessPermissions.ToString().Equals("AllPermissions", StringComparison.InvariantCulture)) { obj.Permissions.Add("User", "Read,Write,Execute"); obj.Permissions.Add("Group", "Read,Write,Execute"); obj.Permissions.Add("Other", "Read,Write,Execute"); } else { var keys = new List <string>() { "User", "Group", "Other" }; var splits = file.FileAccessPermissions.ToString().Split(',').Select(x => x.Trim()); foreach (var key in keys) { foreach (var permission in splits.Where((x) => x.StartsWith(key, StringComparison.InvariantCulture))) { if (permission.Contains("ReadWriteExecute", StringComparison.InvariantCulture)) { obj.Permissions.Add(key, "Read,Write,Execute"); } else { if (obj.Permissions.ContainsKey(key)) { obj.Permissions[key] = $"{obj.Permissions[key]},{permission.Trim().Substring(key.Length)}"; } else { obj.Permissions.Add(key, permission.Trim().Substring(key.Length)); } } } } } } catch (Exception e) when( e is ArgumentNullException || e is ArgumentException || e is InvalidOperationException) { Log.Debug($"Failed to get permissions for {path} {e.GetType().ToString()}"); } } try { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (Directory.Exists(path)) { var fileInfo = new DirectoryInfo(path); if (fileInfo.Attributes.HasFlag(FileAttributes.ReparsePoint)) { obj.IsLink = true; obj.Target = NativeMethods.GetFinalPathName(path); } else { obj.IsDirectory = true; } } else { var fileInfo = new FileInfo(path); var size = (ulong)fileInfo.Length; obj.Size = size; if (WindowsFileSystemUtils.IsLocal(obj.Path) || downloadCloud) { if (includeContentHash) { obj.ContentHash = FileSystemUtils.GetFileHash(fileInfo); } obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path, size); if (obj.IsExecutable != null && (bool)obj.IsExecutable) { // TODO: This can be optimized into fewer touches, GetSignatureStatus also runs IsExecutable checks against the first 4 bytes obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(path); obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(path); } } } } else { UnixSymbolicLinkInfo i = new UnixSymbolicLinkInfo(path); obj.FileType = i.FileType.ToString(); obj.Size = (ulong)i.Length; obj.IsDirectory = false; switch (i.FileType) { case FileTypes.SymbolicLink: obj.IsLink = true; obj.Target = i.ContentsPath; break; case FileTypes.Fifo: case FileTypes.Socket: case FileTypes.BlockDevice: case FileTypes.CharacterDevice: case FileTypes.Directory: obj.IsDirectory = true; break; case FileTypes.RegularFile: if (i.HasContents) { if (includeContentHash) { obj.ContentHash = FileSystemUtils.GetFileHash(path); } obj.IsExecutable = FileSystemUtils.IsExecutable(obj.Path, obj.Size); } break; } } } catch (Exception e) when( e is ArgumentNullException || e is SecurityException || e is ArgumentException || e is UnauthorizedAccessException || e is PathTooLongException || e is NotSupportedException || e is InvalidOperationException) { Log.Verbose("Failed to create FileInfo from File at {0} {1}", path, e.GetType().ToString()); } catch (Exception e) { Log.Debug("Should be caught in DirectoryWalker {0}", e.GetType().ToString()); } try { obj.LastModified = File.GetLastWriteTimeUtc(path); obj.Created = File.GetCreationTimeUtc(path); } catch (Exception) { } return(obj); }
public static int RunCollectCommand(CollectCommandOptions opts) { if (opts == null) { return(-1); } #if DEBUG Logger.Setup(true, opts.Verbose, opts.Quiet); #else Logger.Setup(opts.Debug, opts.Verbose, opts.Quiet); #endif DatabaseManager.Setup(opts.DatabaseFilename); AsaTelemetry.Setup(); Dictionary <string, string> StartEvent = new Dictionary <string, string>(); StartEvent.Add("Files", opts.EnableAllCollectors ? "True" : opts.EnableFileSystemCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Ports", opts.EnableNetworkPortCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Users", opts.EnableUserCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Certificates", opts.EnableCertificateCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Registry", opts.EnableRegistryCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Service", opts.EnableServiceCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Firewall", opts.EnableFirewallCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("ComObject", opts.EnableComObjectCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("EventLog", opts.EnableEventLogCollector.ToString(CultureInfo.InvariantCulture)); StartEvent.Add("Admin", AsaHelpers.IsAdmin().ToString(CultureInfo.InvariantCulture)); AsaTelemetry.TrackEvent("Run Command", StartEvent); AdminOrQuit(); CheckFirstRun(); DatabaseManager.VerifySchemaVersion(); int returnValue = (int)GUI_ERROR.NONE; opts.RunId = opts.RunId.Trim(); if (opts.RunId.Equals("Timestamp", StringComparison.InvariantCulture)) { opts.RunId = DateTime.Now.ToString("o", CultureInfo.InvariantCulture); } if (opts.MatchedCollectorId != null) { var resultTypes = DatabaseManager.GetResultTypes(opts.MatchedCollectorId); foreach (var resultType in resultTypes) { switch (resultType.Key) { case RESULT_TYPE.FILE: opts.EnableFileSystemCollector = resultType.Value; break; case RESULT_TYPE.PORT: opts.EnableNetworkPortCollector = resultType.Value; break; case RESULT_TYPE.CERTIFICATE: opts.EnableCertificateCollector = resultType.Value; break; case RESULT_TYPE.COM: opts.EnableComObjectCollector = resultType.Value; break; case RESULT_TYPE.FIREWALL: opts.EnableFirewallCollector = resultType.Value; break; case RESULT_TYPE.LOG: opts.EnableEventLogCollector = resultType.Value; break; case RESULT_TYPE.SERVICE: opts.EnableServiceCollector = resultType.Value; break; case RESULT_TYPE.USER: opts.EnableUserCollector = resultType.Value; break; } } } var dict = new Dictionary <RESULT_TYPE, bool>(); if (opts.EnableFileSystemCollector || opts.EnableAllCollectors) { collectors.Add(new FileSystemCollector(opts.RunId, enableHashing: opts.GatherHashes, directories: opts.SelectedDirectories, downloadCloud: opts.DownloadCloud, examineCertificates: opts.CertificatesFromFiles, parallel: opts.Parallelization)); dict.Add(RESULT_TYPE.FILE, true); } if (opts.EnableNetworkPortCollector || opts.EnableAllCollectors) { collectors.Add(new OpenPortCollector(opts.RunId)); dict.Add(RESULT_TYPE.PORT, true); } if (opts.EnableServiceCollector || opts.EnableAllCollectors) { collectors.Add(new ServiceCollector(opts.RunId)); dict.Add(RESULT_TYPE.SERVICE, true); } if (opts.EnableUserCollector || opts.EnableAllCollectors) { collectors.Add(new UserAccountCollector(opts.RunId)); dict.Add(RESULT_TYPE.USER, true); } if (opts.EnableRegistryCollector || (opts.EnableAllCollectors && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))) { collectors.Add(new RegistryCollector(opts.RunId, opts.Parallelization)); dict.Add(RESULT_TYPE.REGISTRY, true); } if (opts.EnableCertificateCollector || opts.EnableAllCollectors) { collectors.Add(new CertificateCollector(opts.RunId)); dict.Add(RESULT_TYPE.CERTIFICATE, true); } if (opts.EnableFirewallCollector || opts.EnableAllCollectors) { collectors.Add(new FirewallCollector(opts.RunId)); dict.Add(RESULT_TYPE.FIREWALL, true); } if (opts.EnableComObjectCollector || (opts.EnableAllCollectors && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))) { collectors.Add(new ComObjectCollector(opts.RunId)); dict.Add(RESULT_TYPE.COM, true); } if (opts.EnableEventLogCollector || opts.EnableAllCollectors) { collectors.Add(new EventLogCollector(opts.RunId, opts.GatherVerboseLogs)); dict.Add(RESULT_TYPE.LOG, true); } if (collectors.Count == 0) { Log.Warning(Strings.Get("Err_NoCollectors")); return((int)GUI_ERROR.NO_COLLECTORS); } if (!opts.NoFilters) { if (opts.FilterLocation.Equals("Use embedded filters.", StringComparison.InvariantCulture)) { Filter.LoadEmbeddedFilters(); } else { Filter.LoadFilters(opts.FilterLocation); } } if (opts.Overwrite) { DatabaseManager.DeleteRun(opts.RunId); } else { if (DatabaseManager.GetRun(opts.RunId) != null) { Log.Error(Strings.Get("Err_RunIdAlreadyUsed")); return((int)GUI_ERROR.UNIQUE_ID); } } Log.Information(Strings.Get("Begin"), opts.RunId); DatabaseManager.InsertRun(opts.RunId, dict); Log.Information(Strings.Get("StartingN"), collectors.Count.ToString(CultureInfo.InvariantCulture), Strings.Get("Collectors")); Console.CancelKeyPress += delegate { Log.Information("Cancelling collection. Rolling back transaction. Please wait to avoid corrupting database."); DatabaseManager.RollBack(); Environment.Exit(0); }; Dictionary <string, string> EndEvent = new Dictionary <string, string>(); foreach (BaseCollector c in collectors) { try { c.Execute(); EndEvent.Add(c.GetType().ToString(), c.NumCollected().ToString(CultureInfo.InvariantCulture)); } catch (Exception e) { Log.Error(Strings.Get("Err_CollectingFrom"), c.GetType().Name, e.Message, e.StackTrace); Dictionary <string, string> ExceptionEvent = new Dictionary <string, string>(); ExceptionEvent.Add("Exception Type", e.GetType().ToString()); ExceptionEvent.Add("Stack Trace", e.StackTrace); ExceptionEvent.Add("Message", e.Message); AsaTelemetry.TrackEvent("CollectorCrashRogueException", ExceptionEvent); returnValue = 1; } } AsaTelemetry.TrackEvent("End Command", EndEvent); DatabaseManager.Commit(); return(returnValue); }
public void VerifyEmbeddedRulesAreValid() { var analyzer = new Analyzer(AsaHelpers.GetPlatform()); Assert.IsTrue(analyzer.VerifyRules()); }