This commit is contained in:
Gabe Stocco 2021-08-02 11:47:21 -07:00 коммит произвёл GitHub
Родитель 082a498e8d
Коммит e798c30485
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
32 изменённых файлов: 322 добавлений и 171 удалений

Просмотреть файл

@ -10,8 +10,8 @@
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.0" />
<PackageReference Include="LiteDB" Version="5.0.10" />
<PackageReference Include="System.Data.SQLite" Version="1.0.114" />
<PackageReference Include="LiteDB" Version="5.0.11" />
<PackageReference Include="System.Data.SQLite" Version="1.0.114.4" />
<PackageReference Include="murmurhash" Version="1.0.3" />
</ItemGroup>
@ -25,6 +25,6 @@
<None Include="BenchmarkDotNet.Artifacts\OldResults\AttackSurfaceAnalyzer.Benchmarks.LiteDbInsertTests-report-full.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Nerdbank.GitVersioning" Version="3.4.203" />
<PackageReference Update="Nerdbank.GitVersioning" Version="3.4.231" />
</ItemGroup>
</Project>

Просмотреть файл

@ -68,7 +68,7 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Utils
var firstRun = runs?.FindOne(x => x.RunId.Equals(baseId));
var secondRun = runs?.FindOne(x => x.RunId.Equals(compareId));
return firstRun?.ResultTypes.Intersect(secondRun?.ResultTypes);
return firstRun?.ResultTypes.Intersect(secondRun?.ResultTypes ?? new List<RESULT_TYPE>()) ?? secondRun?.ResultTypes ?? new List<RESULT_TYPE>();
}
public static bool? GetComparisonCompleted(string firstRunId, string secondRunId)

Просмотреть файл

@ -76,7 +76,7 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Utils
var runOne = GetRun(baseId);
var runTwo = GetRun(compareId);
return runOne?.ResultTypes.Intersect(runTwo?.ResultTypes).ToList() ?? new List<RESULT_TYPE>();
return runOne?.ResultTypes.Intersect(runTwo?.ResultTypes ?? new List<RESULT_TYPE>()).ToList() ?? runTwo?.ResultTypes ?? new List<RESULT_TYPE>();
}
public static bool GetComparisonCompleted(string firstRunId, string secondRunId)

Просмотреть файл

@ -33,7 +33,7 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
private static readonly List<BaseMonitor> monitors = new List<BaseMonitor>();
private static List<BaseCompare> comparators = new List<BaseCompare>();
public static DatabaseManager DatabaseManager { get; private set; }
public static DatabaseManager? DatabaseManager { get; private set; }
private static void SetupLogging(CommandOptions opts)
{
@ -197,7 +197,12 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
public static ConcurrentDictionary<(RESULT_TYPE, CHANGE_TYPE), List<CompareResult>> AnalyzeMonitored(CompareCommandOptions opts)
{
if (opts is null) { return new ConcurrentDictionary<(RESULT_TYPE, CHANGE_TYPE), List<CompareResult>>(); }
if (DatabaseManager is null)
{
Log.Error("Err_DatabaseManagerNull", "InsertCompareResults");
return new ConcurrentDictionary<(RESULT_TYPE, CHANGE_TYPE), List<CompareResult>>();
}
if (opts is null || opts.SecondRunId is null) { return new ConcurrentDictionary<(RESULT_TYPE, CHANGE_TYPE), List<CompareResult>>(); }
var analyzer = new AsaAnalyzer(new AnalyzerOptions(opts.RunScripts));
return AnalyzeMonitored(opts, analyzer, DatabaseManager.GetMonitorResults(opts.SecondRunId), opts.AnalysesFile ?? throw new ArgumentNullException(nameof(opts.AnalysesFile)));
}
@ -257,6 +262,11 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
internal static void InsertCompareResults(ConcurrentDictionary<(RESULT_TYPE, CHANGE_TYPE), List<CompareResult>> results, string? FirstRunId, string SecondRunId, string AnalysesHash)
{
if (DatabaseManager is null)
{
Log.Error("Err_DatabaseManagerNull", "InsertCompareResults");
return;
}
DatabaseManager.InsertCompareRun(FirstRunId, SecondRunId, AnalysesHash, RUN_STATUS.RUNNING);
foreach (var key in results.Keys)
{
@ -331,7 +341,11 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
else
{
SetupDatabase(opts);
if (DatabaseManager is null)
{
Log.Error("Err_DatabaseManagerNull", "RunConfigCommand");
return ASA_ERROR.DATABASE_NULL;
}
if (opts.ListRuns)
{
if (DatabaseManager.FirstRun)
@ -408,6 +422,11 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
private static ASA_ERROR RunExportCollectCommand(ExportCollectCommandOptions opts)
{
if (DatabaseManager is null)
{
Log.Error("Err_DatabaseManagerNull", "RunExportCollectCommand");
return ASA_ERROR.DATABASE_NULL;
}
if (opts.OutputPath != null && !Directory.Exists(opts.OutputPath))
{
Log.Fatal(Strings.Get("Err_OutputPathNotExist"), opts.OutputPath);
@ -611,6 +630,11 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
private static ASA_ERROR RunExportMonitorCommand(ExportMonitorCommandOptions opts)
{
if (DatabaseManager is null)
{
Log.Error("Err_DatabaseManagerNull", "RunExportMonitorCommand");
return ASA_ERROR.DATABASE_NULL;
}
if (opts.RunId is null)
{
var runIds = DatabaseManager.GetLatestRunIds(1, RUN_TYPE.MONITOR);
@ -644,6 +668,11 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
public static void WriteMonitorJson(string RunId, int ResultType, string OutputPath)
{
if (DatabaseManager is null)
{
Log.Error("Err_DatabaseManagerNull", "WriteMonitorJson");
return;
}
var invalidFileNameChars = Path.GetInvalidPathChars().ToList();
OutputPath = new string(OutputPath.Select(ch => invalidFileNameChars.Contains(ch) ? Convert.ToChar(invalidFileNameChars.IndexOf(ch) + 65) : ch).ToArray());
@ -672,6 +701,11 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
private static ASA_ERROR RunMonitorCommand(MonitorCommandOptions opts)
{
if (DatabaseManager is null)
{
Log.Error("Err_DatabaseManagerNull", "RunMonitorCommand");
return ASA_ERROR.DATABASE_NULL;
}
if (opts.RunId is string)
{
opts.RunId = opts.RunId.Trim();
@ -742,7 +776,7 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
}
}
void consoleCancelDelegate(object sender, ConsoleCancelEventArgs args)
void consoleCancelDelegate(object? sender, ConsoleCancelEventArgs args)
{
args.Cancel = true;
exitEvent.Set();
@ -804,7 +838,11 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
{
throw new ArgumentNullException(nameof(opts));
}
if (DatabaseManager is null)
{
Log.Error("Err_DatabaseManagerNull", "CompareRuns");
return new ConcurrentDictionary<(RESULT_TYPE, CHANGE_TYPE), List<CompareResult>>();
}
comparators = new List<BaseCompare>();
Dictionary<string, string> EndEvent = new Dictionary<string, string>();
@ -827,51 +865,58 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
if (!opts.DisableAnalysis)
{
watch = Stopwatch.StartNew();
var analyzer = new AsaAnalyzer(new AnalyzerOptions(opts.RunScripts));
var platform = DatabaseManager.RunIdToPlatform(opts.SecondRunId);
var violations = analyzer.EnumerateRuleIssues(opts.AnalysesFile.GetRules());
OAT.Utils.Strings.Setup();
OAT.Utils.Helpers.PrintViolations(violations);
if (violations.Any())
if (opts.AnalysesFile is not null)
{
Log.Error("Encountered {0} issues with rules in {1}. Skipping analysis.", violations.Count(), opts.AnalysesFile.Source ?? "Embedded");
}
else
{
if (c.Results.Count > 0)
watch = Stopwatch.StartNew();
var analyzer = new AsaAnalyzer(new AnalyzerOptions(opts.RunScripts));
var platform = DatabaseManager.RunIdToPlatform(opts.SecondRunId);
var violations = analyzer.EnumerateRuleIssues(opts.AnalysesFile.GetRules());
OAT.Utils.Strings.Setup();
OAT.Utils.Helpers.PrintViolations(violations);
if (violations.Any())
{
foreach (var key in c.Results.Keys)
Log.Error("Encountered {0} issues with rules in {1}. Skipping analysis.", violations.Count(), opts.AnalysesFile?.Source ?? "Embedded");
}
else
{
if (c.Results.Count > 0)
{
if (c.Results[key] is List<CompareResult> queue)
foreach (var key in c.Results.Keys)
{
queue.AsParallel().ForAll(res =>
if (c.Results[key] is List<CompareResult> queue)
{
// Select rules with the appropriate change type, platform and target
// - Target is also checked inside Analyze, but this shortcuts repeatedly
// checking rules which don't apply
var selectedRules = opts.AnalysesFile.Rules.Where((rule) =>
(rule.ChangeTypes == null || rule.ChangeTypes.Contains(res.ChangeType))
&& (rule.Platforms == null || rule.Platforms.Contains(platform))
&& (rule.ResultType == res.ResultType));
res.Rules = analyzer.Analyze(selectedRules, res.Base, res.Compare).ToList();
res.Analysis = res.Rules.Count
> 0 ? res.Rules.Max(x => ((AsaRule)x).Flag) : opts.AnalysesFile.DefaultLevels[res.ResultType];
res.AnalysesHash = opts.AnalysesFile.GetHash();
});
queue.AsParallel().ForAll(res =>
{
// Select rules with the appropriate change type, platform and target
// - Target is also checked inside Analyze, but this shortcuts repeatedly
// checking rules which don't apply
var selectedRules = opts.AnalysesFile.Rules.Where((rule) =>
(rule.ChangeTypes == null || rule.ChangeTypes.Contains(res.ChangeType))
&& (rule.Platforms == null || rule.Platforms.Contains(platform))
&& (rule.ResultType == res.ResultType));
res.Rules = analyzer.Analyze(selectedRules, res.Base, res.Compare).ToList();
res.Analysis = res.Rules.Count
> 0 ? res.Rules.Max(x => ((AsaRule)x).Flag) : opts.AnalysesFile.DefaultLevels[res.ResultType];
res.AnalysesHash = opts.AnalysesFile.GetHash();
});
}
}
}
}
}
watch.Stop();
t = TimeSpan.FromMilliseconds(watch.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.Information(Strings.Get("Completed"), "Analysis", answer);
watch.Stop();
t = TimeSpan.FromMilliseconds(watch.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.Information(Strings.Get("Completed"), "Analysis", answer);
}
else
{
Log.Error(Strings.Get("Err_AnalysisNull"));
}
}
return c.Results;
@ -879,6 +924,11 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
public static ASA_ERROR RunGuiMonitorCommand(MonitorCommandOptions opts)
{
if (DatabaseManager is null)
{
Log.Error("Err_DatabaseManagerNull", "RunGuiMonitorCommand");
return ASA_ERROR.DATABASE_NULL;
}
if (opts is null)
{
return ASA_ERROR.NO_COLLECTORS;
@ -894,7 +944,7 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
{
Log.Warning(Strings.Get("Err_NoMonitors"));
}
var run = new AsaRun(RunId: opts.RunId, Timestamp: DateTime.Now, Version: AsaHelpers.GetVersionString(), Platform: AsaHelpers.GetPlatform(), ResultTypes: setResultTypes, Type: RUN_TYPE.MONITOR);
var run = new AsaRun(RunId: opts?.RunId ?? string.Empty, Timestamp: DateTime.Now, Version: AsaHelpers.GetVersionString(), Platform: AsaHelpers.GetPlatform(), ResultTypes: setResultTypes, Type: RUN_TYPE.MONITOR);
DatabaseManager.InsertRun(run);
foreach (var c in monitors)
@ -907,6 +957,7 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
public static int StopMonitors()
{
foreach (var c in monitors)
{
Log.Information(Strings.Get("End"), c.GetType().Name);
@ -916,6 +967,12 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
FlushResults();
if (DatabaseManager is null)
{
Log.Error("Err_DatabaseManagerNull", "RunGuiMonitorCommand");
return (int)ASA_ERROR.DATABASE_NULL;
}
DatabaseManager.Commit();
return 0;
@ -948,6 +1005,11 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
public static ASA_ERROR RunCollectCommand(CollectCommandOptions opts)
{
if (DatabaseManager is null)
{
Log.Error("Err_DatabaseManagerNull", "RunCollectCommand");
return ASA_ERROR.DATABASE_NULL;
}
if (opts == null) { return ASA_ERROR.NO_COLLECTORS; }
collectors.Clear();
AdminOrWarn();
@ -1123,11 +1185,19 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
using CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
void cancelKeyDelegate(object sender, ConsoleCancelEventArgs args)
void cancelKeyDelegate(object? sender, ConsoleCancelEventArgs args)
{
Log.Information("Cancelling collection. Rolling back transaction. Please wait to avoid corrupting database.");
source.Cancel();
DatabaseManager.CloseDatabase();
if (DatabaseManager is null)
{
Log.Error("Err_DatabaseManagerNull", "InsertCompareResults");
}
else
{
DatabaseManager.CloseDatabase();
}
Environment.Exit((int)ASA_ERROR.CANCELLED);
}
Console.CancelKeyPress += cancelKeyDelegate;
@ -1163,6 +1233,10 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
private static void FlushResults()
{
if (DatabaseManager is null)
{
return;
}
var prevFlush = DatabaseManager.QueueSize;
var totFlush = prevFlush;

Просмотреть файл

@ -33,17 +33,16 @@
<None Include="..\icon-128.png" Pack="true" PackagePath="" />
<None Include="..\LICENSE.txt" Pack="true" PackagePath="" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CST.OAT" Version="1.0.86" />
<PackageReference Include="Microsoft.CST.OAT.Blazor.Components" Version="1.0.86" />
<PackageReference Include="Tewr.Blazor.FileReader" Version="3.0.0.20340" />
<PackageReference Include="Tewr.Blazor.FileReader.Wasm" Version="0.11.19128" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.9.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" />
<PackageReference Include="Microsoft.CST.OAT" Version="1.0.91" />
<PackageReference Include="Microsoft.CST.OAT.Blazor.Components" Version="1.0.91" />
<PackageReference Include="Tewr.Blazor.FileReader" Version="3.2.0.21211" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Nerdbank.GitVersioning" Version="3.4.203" />
<PackageReference Update="Nerdbank.GitVersioning" Version="3.4.231" />
</ItemGroup>
</Project>

Просмотреть файл

@ -66,7 +66,7 @@
@code{
Helper.GlowClass directorySelectElementGlowClass = new Helper.GlowClass();
string SelectedDirectoryInput;
string SelectedDirectoryInput = string.Empty;
int SelectedDirectoryTop;
void RemoveInputFromList()

Просмотреть файл

@ -39,7 +39,7 @@
@code{
Helper.GlowClass directorySelectElementGlowClass = new Helper.GlowClass();
string SelectedHiveInput;
string SelectedHiveInput = string.Empty;
int SelectedHiveTop;
void RemoveInputFromList()

Просмотреть файл

@ -46,7 +46,7 @@
@code{
Helper.GlowClass directorySelectElementGlowClass = new Helper.GlowClass();
string SelectedDirectoryInput;
string SelectedDirectoryInput = string.Empty;
int SelectedDirectoryTop;
void RemoveInputFromList()

Просмотреть файл

@ -3,5 +3,5 @@
@code{
[Parameter]
public Action Continue { get; set; }
public Action Continue { get; set; } = delegate () { };
}

Просмотреть файл

@ -67,18 +67,15 @@ else
}
@code {
string _firstRunId = string.Empty;
string _secondRundId = string.Empty;
string _analysesHash = string.Empty;
string _monitorRunId = string.Empty;
[Parameter]
public string FirstRunId { get { return _firstRunId; } set { _firstRunId = value; OnInitialized(); } }
public string FirstRunId { get; set; } = string.Empty;
[Parameter]
public string SecondRunId { get { return _secondRundId; } set { _secondRundId = value; OnInitialized(); } }
public string SecondRunId { get; set; } = string.Empty;
[Parameter]
public string AnalysesHash { get { return _analysesHash; } set { _analysesHash = value; OnInitialized(); } }
public string AnalysesHash { get; set; } = string.Empty;
[Parameter]
public string MonitorRunId { get { return _monitorRunId; } set { _monitorRunId = value; OnInitialized(); } }
public string MonitorRunId { get; set; } = string.Empty;
protected override void OnInitialized()
{
@ -150,6 +147,11 @@ else
public void GetAnalysisResults()
{
if (AttackSurfaceAnalyzerClient.DatabaseManager is null)
{
analysisResults = new List<CompareResult>();
return;
}
var resultType = (RESULT_TYPE)Enum.Parse(typeof(RESULT_TYPE), SelectedResultType);
switch (resultType)
{
@ -165,6 +167,10 @@ else
public void ParseOptsToResultTypes()
{
foundResultTypes.Clear();
if (AttackSurfaceAnalyzerClient.DatabaseManager is null)
{
return;
}
foreach (var resultType in Enum.GetValues(typeof(RESULT_TYPE)))
{
var found = AttackSurfaceAnalyzerClient.DatabaseManager.GetComparisonResultsCount(FirstRunId, SecondRunId, AnalysesHash, (int)resultType);

Просмотреть файл

@ -13,7 +13,7 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli
/// </summary>
public class GlowClass
{
public string ClassName;
public string ClassName { get; set; } = string.Empty;
}
public static string GetGlowClass(bool value)

Просмотреть файл

@ -49,7 +49,7 @@
Error
}
List<string> Runs = AttackSurfaceAnalyzerClient.DatabaseManager.GetRuns();
List<string> Runs = AttackSurfaceAnalyzerClient.DatabaseManager?.GetRuns() ?? new List<string>();
int RunIdInput {
get
@ -99,7 +99,7 @@
await AnalyzeIt();
pageState = PageState.Finished;
}
System.Threading.Timer timer;
System.Threading.Timer? timer;
async Task<ASA_ERROR> AnalyzeIt()
{
@ -117,7 +117,7 @@
CompareOneOptions.FirstRunId = appData.ExportCollectCommandOptions.FirstRunId;
CompareOneOptions.SecondRunId = appData.ExportCollectCommandOptions.SecondRunId;
var results = AttackSurfaceAnalyzerClient.CompareRuns(CompareOneOptions);
AttackSurfaceAnalyzerClient.InsertCompareResults(results, CompareOneOptions.FirstRunId, CompareOneOptions.SecondRunId, appData.CompareCommandOptions.AnalysesFile.GetHash());
AttackSurfaceAnalyzerClient.InsertCompareResults(results, CompareOneOptions.FirstRunId, CompareOneOptions.SecondRunId, appData.CompareCommandOptions.AnalysesFile?.GetHash() ?? string.Empty);
});
return ASA_ERROR.NONE;

Просмотреть файл

@ -10,13 +10,7 @@
<select class="form-control mr-3" id="RunId" @bind="RunIdInput">
@for (int i = 0; i < Runs.Count; i++)
{
if (!string.IsNullOrEmpty(@Runs[i].firstRunId))
{
<option value="@i">@Runs[i].firstRunId vs @Runs[i].secondRunId (@Runs[i].runStatus)</option>
}
else{
<option value="@i">@Runs[i].secondRunId (@Runs[i].runStatus)</option>
}
<option value="@i">@Runs[i]</option>
}
</select>
</div>
@ -50,12 +44,4 @@ else
this.StateHasChanged();
}
}
System.Threading.Timer timer;
protected override void OnInitialized()
{
//timer = new System.Threading.Timer((_) => InvokeAsync(() => StateHasChanged()), null, 0, 100);
base.OnInitialized();
}
}

Просмотреть файл

@ -29,8 +29,13 @@
<li class="nav-item">
<a class="nav-link" id="sandbox-view-tab" data-toggle="tab" href="#sandbox-view" role="tab" aria-controls="sandbox-view" aria-selected="false">View</a>
</li>
<li class="nav-item">
<a class="nav-link" id="sandbox-manage-tab" data-toggle="tab" href="#sandbox-manage" role="tab" aria-controls="sandbox-manage" aria-selected="false">Manage</a>
</li>
</ul>
<div class="tab-content mb-3" id="sandbox-tabs-content">
<!-- Create Tab -->
<div class="tab-pane fade show active" id="sandbox-create" role="tabpanel" aria-labelledby="sandbox-create-tab">
<div class="form-inline mb-3">
<label class="mr-2" for="typeToCreate">Type to Create:</label>
@ -69,11 +74,9 @@
</div>
</div>
<!-- View tab -->
<div class="tab-pane fade" id="sandbox-view" role="tabpanel" aria-labelledby="sandbox-view-tab">
<h5>State</h5>
<p>Load in JSON serialized Sandbox State.</p>
<FileUpload ProcessFile="LoadSandbox" ReadLabel="Load Sandbox" ClearAction="ClearSandbox" ClearLabel="Clear Sandbox" />
<button class="btn btn-primary" @onclick="SaveSandboxState">Save Sandbox State</button>
<button class="btn btn-primary mb-2" @onclick="RemoveLastObject" disabled=@removeDisabled>Remove Last Object</button>
@if (SandBoxErrors.Any())
{
@ -98,6 +101,24 @@
</div>
}
</div>
<!-- Manage tab -->
<div class="tab-pane fade" id="sandbox-manage" role="tabpanel" aria-labelledby="sandbox-manage-tab">
<h5>State</h5>
<p>Load in JSON serialized Sandbox State.</p>
<FileUpload ProcessFile="LoadSandbox" ReadLabel="Load Sandbox" ClearAction="ClearSandbox" ClearLabel="Clear Sandbox" />
<button class="btn btn-primary" @onclick="SaveSandboxState">Save Sandbox State</button>
@if (SandBoxErrors.Any())
{
<div class="alert alert-warning" role="alert">
@foreach (var error in SandBoxErrors)
{
<p>@error</p>
}
</div>
}
</div>
</div>
</div>
@ -176,14 +197,17 @@
var inputs = new List<object?>();
foreach (var param in ctor.GetParameters())
{
var representation = objState?[param.Name]?.ToObject<string>();
if (representation != null && GetValueFromJObject(param.ParameterType, representation) is { } obj)
if (param.Name is not null)
{
inputs.Add(obj);
}
else
{
inputs.Add(null);
var representation = objState?[param.Name]?.ToObject<string>();
if (representation != null && GetValueFromJObject(param.ParameterType, representation) is { } obj)
{
inputs.Add(obj);
}
else
{
inputs.Add(null);
}
}
}
var empty = ctor.Invoke(inputs.ToArray());
@ -262,7 +286,7 @@
ScaffoldedObject = new Scaffold(constructors[value]);
if (constructors[value].DeclaringType == typeof(CertificateObject))
{
ScaffoldedObject.Parameters["Certificate"] = new Scaffold(typeof(SerializableCertificate).GetConstructors().Where(x => x.GetParameters().Count() > 1).FirstOrDefault());
ScaffoldedObject.Parameters["Certificate"] = (new Scaffold(typeof(SerializableCertificate).GetConstructors().Where(x => x.GetParameters().Count() > 1).First()), typeof(SerializableCertificate));
}
}
RefreshState();
@ -285,7 +309,7 @@
ScaffoldedObject = new Scaffold(constructorToUse, Assemblies);
if (constructors[constructorToInvoke].DeclaringType == typeof(CertificateObject))
{
ScaffoldedObject.Parameters["Certificate"] = new Scaffold(typeof(SerializableCertificate).GetConstructors().Where(x => x.GetParameters().Count() > 1).FirstOrDefault());
ScaffoldedObject.Parameters["Certificate"] = (new Scaffold(typeof(SerializableCertificate).GetConstructors().Where(x => x.GetParameters().Count() > 1).First()), typeof(SerializableCertificate));
}
}
RefreshState();
@ -470,7 +494,7 @@
}
else if (type.IsEnum)
{
if (Enum.TryParse(type, objectState, out object result))
if (Enum.TryParse(type, objectState, out object? result))
{
return Convert.ChangeType(result, type);
}
@ -484,13 +508,16 @@
foreach (var obj in AppState.TestObjects)
{
var t = obj.GetType();
if (!objects.ContainsKey(t.FullName))
if (t.FullName is not null)
{
objects.Add(t.FullName, new List<object>());
if (!objects.ContainsKey(t.FullName))
{
objects.Add(t.FullName, new List<object>());
}
objects[t.FullName].Add(obj);
}
objects[t.FullName].Add(obj);
}
var state = new SandboxState(objects);
var state = new Cli.SandboxState(objects);
await JSRuntime.InvokeAsync<object>(
"FileSaveAs",
"SandboxState.json",

Просмотреть файл

@ -59,6 +59,10 @@ main {
border-color: #db7500;
}
.form-group {
margin-bottom: 0.5rem;
}
.hover-shadow-circle:hover {
box-shadow: 0px 0px 6px 3px rgba(255, 255, 255, 0.7);
border-radius: 50%;

Просмотреть файл

@ -2,7 +2,7 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="Nerdbank.GitVersioning">
<Version>3.3.37</Version>
<Version>3.4.231</Version>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

Просмотреть файл

@ -91,7 +91,7 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Collectors
try
{
var fileSecurity = new FileSecurity(path, AccessControlSections.Owner);
IdentityReference oid = fileSecurity.GetOwner(typeof(SecurityIdentifier));
IdentityReference? oid = fileSecurity.GetOwner(typeof(SecurityIdentifier));
obj.Owner = AsaHelpers.SidToName(oid);
}
catch (Exception e)
@ -101,7 +101,7 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Collectors
try
{
var fileSecurity = new FileSecurity(path, AccessControlSections.Group);
IdentityReference gid = fileSecurity.GetGroup(typeof(SecurityIdentifier));
IdentityReference? gid = fileSecurity.GetGroup(typeof(SecurityIdentifier));
obj.Group = AsaHelpers.SidToName(gid);
}
catch (Exception e)
@ -193,8 +193,6 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Collectors
try
{
FileIOPermission fiop = new FileIOPermission(FileIOPermissionAccess.Read, path);
fiop.Demand();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if (Directory.Exists(path))
@ -326,14 +324,17 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Collectors
Log.Debug("Should be caught in DirectoryWalker {0} {1}", e.GetType().ToString(), path);
}
try
if (path is not null)
{
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);
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;
@ -383,7 +384,11 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Collectors
try
{
uint clusterSize = 0;
var root = path.Directory.Root.FullName;
var root = path.Directory?.Root.FullName;
if (root is null)
{
throw new ArgumentNullException(nameof(path.Directory));
}
if (!ClusterSizes.ContainsKey(root))
{
NativeMethods.GetDiskFreeSpace(root, out uint lpSectorsPerCluster, out uint lpBytesPerSector, out _, out _);
@ -447,7 +452,7 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Collectors
{
var opts = new ExtractorOptions() { ExtractSelfOnFail = false };
Extractor extractor = new Extractor();
foreach (var fso in extractor.ExtractFile(path, opts).Select(fileEntry => FileEntryToFileSystemObject(fileEntry)))
foreach (var fso in extractor.Extract(path, opts).Select(fileEntry => FileEntryToFileSystemObject(fileEntry)))
{
HandleChange(fso);
}

Просмотреть файл

@ -32,23 +32,23 @@
<Copy SourceFiles="..\LICENSE.txt" DestinationFolder="$(PublishDir)" />
<Copy SourceFiles="..\NOTICE.txt" DestinationFolder="$(PublishDir)" />
</Target>
<ItemGroup>
<PackageReference Include="MedallionShell" Version="1.6.2" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.9.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" />
<PackageReference Include="Microsoft.CST.OAT" Version="1.0.86" />
<PackageReference Include="Microsoft.CST.RecursiveExtractor" Version="1.0.64" />
<PackageReference Include="Microsoft.CST.OAT" Version="1.0.91" />
<PackageReference Include="Microsoft.CST.RecursiveExtractor" Version="1.1.1" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="CompareNETObjects" Version="4.73.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="5.0.6" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="5.0.8" />
<PackageReference Include="Microsoft.PowerShell.Commands.Diagnostics" Version="7.1.3" />
<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.1.3" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="Microsoft.Windows.Compatibility" Version="5.0.2" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
<PackageReference Include="System.Management" Version="5.0.0" />
<PackageReference Include="System.Net.NetworkInformation" Version="4.3.0" />
@ -60,7 +60,7 @@
<PackageReference Include="System.Net.Security" Version="4.3.2" />
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
<PackageReference Include="Serilog.Sinks.ApplicationInsights" Version="3.1.0" />
<PackageReference Include="Nerdbank.GitVersioning" Version="3.4.203">
<PackageReference Include="Nerdbank.GitVersioning" Version="3.4.231">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
@ -77,7 +77,7 @@
<None Include="..\AttackSurfaceAnalyzer.sln.licenseheader" Link="AttackSurfaceAnalyzer.sln.licenseheader" />
<None Include="..\PRIVACY.md" Link="PRIVACY.md" />
<None Include="..\README.md" Link="README.md" />
<None Include="..\icon-128.png" Pack="true" PackagePath="" />
<None Include="..\LICENSE.txt" Pack="true" PackagePath="" />
<None Include="..\icon-128.png" Pack="true" PackagePath="" />
<None Include="..\LICENSE.txt" Pack="true" PackagePath="" />
</ItemGroup>
</Project>

Просмотреть файл

@ -208,7 +208,7 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer
public string? FirstRunId { get; set; }
[Option(HelpText = "Second run (post-install) identifier")]
public string? SecondRunId { get; set; }
public string SecondRunId { get; set; } = string.Empty;
}
[Verb("export-monitor", HelpText = "Output a .json report for a monitor run")]

Просмотреть файл

@ -11,6 +11,7 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects
{
public CryptographicKeyObject(string Source, TpmAlgId tpmAlgId)
{
this.ResultType = Types.RESULT_TYPE.KEY;
this.Source = Source;
this.tpmAlgId = tpmAlgId;
}

Просмотреть файл

@ -9,6 +9,7 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects
public FileMonitorObject(string PathIn)
{
Path = PathIn;
ResultType = RESULT_TYPE.FILEMONITOR;
}
public string? ExtendedResults { get; set; }

Просмотреть файл

@ -13,6 +13,12 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects
ResultType = RESULT_TYPE.FILE;
}
public FileSystemObject()
{
Path = string.Empty;
ResultType = RESULT_TYPE.FILE;
}
/// <summary>
/// If this is windows executable what DLL Characteristics are set
/// </summary>

Просмотреть файл

@ -6,17 +6,18 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects
{
public class ProcessModuleObject
{
public ProcessModuleObject(string FileName, string ModuleName, SerializableFileVersionInfo? FileVersionInfo)
public ProcessModuleObject(string? FileName, string? ModuleName, SerializableFileVersionInfo? FileVersionInfo)
{
this.FileName = FileName;
this.ModuleName = ModuleName;
this.FileVersionInfo = FileVersionInfo;
}
public string FileName { get; }
public ProcessModuleObject() { }
public SerializableFileVersionInfo? FileVersionInfo { get; }
public string ModuleName { get; }
public string? FileName { get; set; }
public SerializableFileVersionInfo? FileVersionInfo { get; set; }
public string? ModuleName { get; set; }
internal static ProcessModuleObject FromProcessModule(ProcessModule mainModule)
{

Просмотреть файл

@ -94,7 +94,10 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects
try
{
obj.MainModule = ProcessModuleObject.FromProcessModule(process.MainModule);
if (process.MainModule is { })
{
obj.MainModule = ProcessModuleObject.FromProcessModule(process.MainModule);
}
}
catch (Exception e)
{

Просмотреть файл

@ -34,13 +34,10 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects
/// </summary>
/// <param name="IsAuthenticodeValid"> </param>
[JsonConstructor]
public Signature(bool IsAuthenticodeValid)
public Signature()
{
this.IsAuthenticodeValid = IsAuthenticodeValid;
}
public bool IsAuthenticodeValid { get; set; }
public bool IsTimeValid
{
get
@ -53,6 +50,7 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects
}
}
public bool IsAuthenticodeValid { get; set; }
public string? SignedHash { get; set; }
public string? SignerSerialNumber { get; set; }
public SerializableCertificate? SigningCertificate { get; set; }

Просмотреть файл

@ -100,7 +100,8 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Types
FAILED_TO_ESTABLISH_MAIN_DB_CONNECTION,
UNKNOWN,
CANCELLED,
FAILED_TO_COMMIT
FAILED_TO_COMMIT,
DATABASE_NULL
}
/// <summary>

Просмотреть файл

@ -5,6 +5,7 @@
public WifiObject(string SSID)
{
this.SSID = SSID;
this.ResultType = Types.RESULT_TYPE.WIFI;
}
public string? Authentication { get; set; }

Просмотреть файл

@ -591,4 +591,13 @@
<data name="Err_ClauseMissingCustomOperation" xml:space="preserve">
<value>Rule {0} Clause {1} has specified custom operation but the CustomOperation field is missing.</value>
</data>
<data name="Err_AnalysisNull" xml:space="preserve">
<value>The AnalysisFile passed in options was null and analysis cannot be performed.</value>
</data>
<data name="Err_CreateHash" xml:space="preserve">
<value>Cryptographic Exception: Failed to get hash of {0}.</value>
</data>
<data name="Err_DatabaseManagerNull" xml:space="preserve">
<value>DatabaseManager is null at execution of {0}.</value>
</data>
</root>

Просмотреть файл

@ -194,38 +194,42 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Utils
return $"{firstRunId} & {secondRunId}";
}
public static string SidToName(IdentityReference SID)
public static string SidToName(IdentityReference? SID)
{
string sid = SID?.Value ?? string.Empty;
string identity = sid;
if (SidMap.TryGetValue(sid, out string? mappedIdentity))
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if (mappedIdentity != null)
string sid = SID?.Value ?? string.Empty;
string identity = sid;
if (SidMap.TryGetValue(sid, out string? mappedIdentity))
{
return mappedIdentity;
if (mappedIdentity != null)
{
return mappedIdentity;
}
else
{
SidMap.TryRemove(sid, out _);
}
}
else
// Only map NTAccounts, https://en.wikipedia.org/wiki/Security_Identifier
if (sid.StartsWith("S-1-5"))
{
SidMap.TryRemove(sid, out _);
try
{
identity = SID?.Translate(typeof(NTAccount))?.Value ?? sid;
}
catch (IdentityNotMappedException) //lgtm [cs/empty-catch-block]
{
}
}
SidMap.TryAdd(sid, identity);
return sid;
}
// Only map NTAccounts, https://en.wikipedia.org/wiki/Security_Identifier
if (sid.StartsWith("S-1-5"))
{
try
{
identity = SID?.Translate(typeof(NTAccount))?.Value ?? sid;
}
catch (IdentityNotMappedException) //lgtm [cs/empty-catch-block]
{
}
}
SidMap.TryAdd(sid, identity);
return sid;
return string.Empty;
}
private static readonly Random random = new Random();

Просмотреть файл

@ -1,4 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License.
using Serilog;
using System;
using System.IO;
using System.Linq;
@ -11,18 +12,42 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Utils
{
public static string CreateHash(string input)
{
byte[] hashOutput = sha512.ComputeHash(Encoding.UTF8.GetBytes(input));
return Convert.ToBase64String(hashOutput);
try
{
byte[] hashOutput = sha512.ComputeHash(Encoding.UTF8.GetBytes(input));
return Convert.ToBase64String(hashOutput);
}
catch (CryptographicException e)
{
Log.Warning(e, Strings.Get("Err_CreateHash"), "string");
return string.Empty;
}
}
public static byte[] CreateHash(byte[] input)
{
return sha512.ComputeHash(input);
try
{
return sha512.ComputeHash(input);
}
catch (CryptographicException e)
{
Log.Warning(e, Strings.Get("Err_CreateHash"), "bytes");
return Array.Empty<byte>();
}
}
public static string CreateHash(Stream stream)
{
return Convert.ToBase64String(sha512.ComputeHash(stream) ?? Array.Empty<byte>());
try
{
return Convert.ToBase64String(sha512.ComputeHash(stream) ?? Array.Empty<byte>());
}
catch (CryptographicException e)
{
Log.Warning(e, Strings.Get("Err_CreateHash"), "stream");
return string.Empty;
}
}
public static double GetRandomPositiveDouble(double max)

Просмотреть файл

@ -50,7 +50,7 @@ namespace Microsoft.CST.AttackSurfaceAnalyzer.Utils
var runOne = GetRun(baseId);
var runTwo = GetRun(compareId);
return runOne?.ResultTypes.Intersect(runTwo?.ResultTypes).ToList() ?? new List<RESULT_TYPE>();
return runOne?.ResultTypes.Intersect(runTwo?.ResultTypes ?? new List<RESULT_TYPE>()).ToList() ?? (runTwo?.ResultTypes ?? new List<RESULT_TYPE>());
}
public abstract bool GetComparisonCompleted(string? firstRunId, string secondRunId, string analysesHash);

Просмотреть файл

@ -14,8 +14,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.4" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.4" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.5" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.5" />
</ItemGroup>
<ItemGroup>
@ -49,7 +49,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Nerdbank.GitVersioning" Version="3.4.203">
<PackageReference Include="Nerdbank.GitVersioning" Version="3.4.231">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>