Skip to content

Using AsaLib

Gabe Stocco edited this page Aug 1, 2020 · 20 revisions

Getting Started

Getting AsaLib

Search Nuget for Microsoft.CST.AttackSurfaceAnalyzer.

API Documentation

API Documentation is available at https://microsoft.github.io/AttackSurfaceAnalyzer/.

Using AsaLib

Setting up for using the database (optional)

DatabaseManager.Setup(dbPath);

For logging messages (optional)

Logger.Setup(false, true);
Strings.Setup();

Disable telemetry (optional)

AsaTelemetry.Setup(test: true);

Collecting

Collecting gathers the current state of the system.

Collecting using a Delegate (recommended)

The recommended use pattern is to provide your own Change Handler that will be called on every CollectObject discovered by the Collector.

If you collect using a delegate the results will not be populated in the Results field of the Collector (thus reducing memory usage).

ConcurrentStack<CollectObject> stack = new ConcurrentStack<CollectObject>();

void MyFunction(CollectObject collectObject) { 
    // Do something with each CollectObject
    // For example, print it out and put it on a stack
    Console.WriteLine($"Found {collectObject.Identity}");
    stack.Push(collectObject);
}

var cc = new CertificateCollector(changeHandler: collectObject => MyFunction(collectObject));
cc.Execute();

In-Memory

You can also perform collections and store the results in the Collector.

For larger collections, for example, full File System or Registry collections, this will consume large amounts of memory. If you can perform actions as results are processed, you should use the Delegate declaration available for each Collector instead.

var cc = new CertificateCollector();
cc.Execute();
ConcurrentStack<CollectObject> results = cc.Results;

Collecting using the ASA Database API

Alternately, you can write the results to the database.

The call to DatabaseManager.Write actually adds the result into a queue to be written asynchronously. You must ensure that all results have been written before Committing the results to the database. You can use WaitUntilFlushed() to sleep the main thread until the queue has been flushed.

var cc = new CertificateCollector(
    changeHandler: collectObject => DatabaseManager.Write(collectObject, RunId));
cc.Execute();

DatabaseManager.WaitUntilFlushed();
DatabaseManager.Commit();

Monitoring

Monitoring gathers changes as they happen, but does not gather an underlying snapshot of the system.

Monitoring the File System

void PrintFileName(FileMonitorObject fmo)
{
    Console.WriteLine($"{fmo.NotifyFilters} type change was detected on {fmo.Path}");
}

MonitorCommandOptions opts = new MonitorCommandOptions() 
{ 
    MonitoredDirectories = "paths/to/monitor,separated/by/commas"
}

var monitor = new FileSystemMonitor(opts, x => PrintFileName(x)));
monitor.StartRun();

// Behavior under test

monitor.StopRun();

Comparing

From the database

BaseCompare bc = new BaseCompare();
if (bc.TryCompare(FirstRunId, SecondRunId))
{
    ConcurrentDictionary<(RESULT_TYPE, CHANGE_TYPE), List<CompareResult>> results = bc.Results;
}
else
{
    // There was some error while comparing
}

From memory

IEnumerable<CollectObject> FirstRunItems; // Your results from the first collection
IEnumerable<CollectObject> SecondRunItems; // Your results from the second collection

BaseCompare bc = new BaseCompare();
bc.TryCompare(FirstRunItems, FirstRunItems, FirstRunId, SecondRunId);

ConcurrentDictionary<(RESULT_TYPE, CHANGE_TYPE), List<CompareResult>> results = bc.Results;

Analyzing

Analysis is performed on CompareResult objects from BaseCompare.Compare. The sample code below updates the CompareResults with their analysis status in place.

BaseCompare bc = new BaseCompare();
bc.TryCompare(DifferentItems,ModifiedItems,FirstRunId,SecondRunId);
IEnumerable<Rule> rules; // Your rules
var analyzer = new AsaAnalyzer();

if (analyzer.EnumerateRuleIssues(rules).Any()){
   // Error With Rules
}
else {
    foreach (var key in bc.Results.Keys)
    {
        if (bc.Results[key] is List<CompareResult> queue)
        {
            queue.AsParallel().ForAll(res =>
            {
                res.Rules = analyzer.Analyze(rules, res);
                res.Analysis = res.Rules.Max(x => x.Flag);
            });
        }
    }
}