├── .editorconfig ├── .gitattributes ├── .github ├── CODE_OF_CONDUCT.md └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── rule.md ├── .gitignore ├── AttackSurfaceAnalyzer.sln ├── AttackSurfaceAnalyzer.sln.licenseheader ├── BUILD.md ├── Benchmarks ├── AsaDatabaseBenchmark.cs ├── Benchmarks.csproj ├── CommitTest.cs ├── CryptoTests.cs ├── InsertTestsWithIntermittentTransactions.cs ├── InsertTestsWithoutTransactions.cs ├── OpenTransactionTest.cs ├── Program.cs ├── QueryTests.cs ├── SetupTimeTest.cs ├── SystemSqliteDatabaseManager.cs ├── SystemSqliteInsertTests.cs └── SystemSqliteSqlConnectionHolder.cs ├── CONTRIBUTING.md ├── Cli ├── App.razor ├── AppData.cs ├── AttackSurfaceAnalyzerClient.cs ├── Cli.csproj ├── Components │ ├── AnalyzeOptionsRazor.razor │ ├── CollectorOptions │ │ ├── CertificateCollectorOptions.razor │ │ ├── ComObjectCollector.razor │ │ ├── CryptographicKeyCollectorOptions.razor │ │ ├── DriverCollectorOptions.razor │ │ ├── EventLogCollector.razor │ │ ├── FileCollectorOptions.razor │ │ ├── FilewallCollectorOptions.razor │ │ ├── OpenPortCollectorOptions.razor │ │ ├── ProcessCollectorOptions.razor │ │ ├── RegistryCollectorOptions.razor │ │ ├── ServiceCollectorOptions.Razor │ │ ├── TpmCollectorOptions.Razor │ │ ├── UserCollectorOptions.Razor │ │ └── WifiCollectorOptions.Razor │ ├── CollectorOptionsRazor.razor │ ├── MonitorOptions │ │ └── FileMonitorOptions.razor │ ├── MonitorOptionsRazor.razor │ └── States │ │ ├── Analyzing.razor │ │ ├── MonitorFlushing.razor │ │ ├── Monitoring.razor │ │ ├── Results.razor │ │ └── Scanning.razor ├── Helper.cs ├── Pages │ ├── Analyze.razor │ ├── Author.razor │ ├── Configure.razor │ ├── Error.cshtml │ ├── Guided.razor │ ├── Home.razor │ ├── Monitor.razor │ ├── Report.razor │ ├── Sandbox.razor │ ├── Scan.razor │ └── _Host.cshtml ├── Properties │ └── launchSettings.json ├── SandboxState.cs ├── Shared │ ├── MainLayout.razor │ └── NavMenu.razor ├── Startup.cs ├── _Imports.razor ├── appsettings.Development.json ├── appsettings.json └── wwwroot │ ├── css │ ├── asa.css │ ├── bootstrap │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ └── open-iconic │ │ ├── FONT-LICENSE │ │ ├── ICON-LICENSE │ │ ├── README.md │ │ └── font │ │ ├── css │ │ └── open-iconic-bootstrap.min.css │ │ └── fonts │ │ ├── open-iconic.eot │ │ ├── open-iconic.otf │ │ ├── open-iconic.svg │ │ ├── open-iconic.ttf │ │ └── open-iconic.woff │ ├── favicon.ico │ ├── images │ ├── box-seam-wh.png │ ├── box-seam.png │ ├── card-checklist-wh.png │ ├── card-checklist.png │ ├── github-32-wh.png │ ├── github-32.png │ ├── microsoft-sm.png │ ├── microsoft.png │ ├── pencil-square-wh.png │ └── pencil-square.png │ └── js │ ├── bootstrap.bundle.min.js │ ├── bootstrap.bundle.min.js.map │ ├── jquery-3.5.1.slim.min.js │ └── jquery-3.5.1.slim.min.map ├── Directory.Build.props ├── LICENSE.txt ├── Lib ├── Collectors │ ├── BaseCollector.cs │ ├── BaseCompare.cs │ ├── BaseMonitor.cs │ ├── CertificateCollector.cs │ ├── ComObjectCollector.cs │ ├── CryptographicKeyCollector.cs │ ├── DriverCollector.cs │ ├── EventLogCollector.cs │ ├── FileSystemCollector.cs │ ├── FileSystemMonitor.cs │ ├── FileSystemUtils.cs │ ├── FirewallCollector.cs │ ├── IPlatformRunnable.cs │ ├── OpenPortCollector.cs │ ├── ProcessCollector.cs │ ├── RegistryCollector.cs │ ├── RegistryMonitor.cs │ ├── ServiceCollector.cs │ ├── TpmCollector.cs │ ├── UserAccountCollector.cs │ ├── WifiCollector.cs │ └── WindowsFileSystemUtils.cs ├── GlobalSuppressions.cs ├── Lib.csproj ├── Objects │ ├── AsaNvIndex.cs │ ├── AsaRule.cs │ ├── AsaRun.cs │ ├── CertificateObject.cs │ ├── CollectObject.cs │ ├── ComObject.cs │ ├── CommandOptions.cs │ ├── CompareResult.cs │ ├── CryptographicKeyObject.cs │ ├── DataRun.cs │ ├── Diff.cs │ ├── DriverObject.cs │ ├── EventLogObject.cs │ ├── FileMonitorEvent.cs │ ├── FileMonitorObject.cs │ ├── FileSystemMonitorResult.cs │ ├── FileSystemObject.cs │ ├── FirewallObject.cs │ ├── MacSignature.cs │ ├── MonitorObject.cs │ ├── OpenPortObject.cs │ ├── OutputFileMonitorResult.cs │ ├── ProcessModuleObject.cs │ ├── ProcessObject.cs │ ├── RegistryObject.cs │ ├── RuleFile.cs │ ├── SerializableCertificate.cs │ ├── SerializableFileVersionInfo.cs │ ├── ServiceObject.cs │ ├── Settings.cs │ ├── Signature.cs │ ├── SkipCompareAttribute.cs │ ├── SqlConnectionHolder.cs │ ├── TpmObject.cs │ ├── Types.cs │ ├── UserAccountObject.cs │ ├── UserGroupObject.cs │ ├── WifiObject.cs │ └── WriteObject.cs ├── Properties │ ├── Resources.Designer.cs │ ├── Resources.resx │ └── launchSettings.json └── Utils │ ├── AsaAnalyzer.cs │ ├── AsaHelpers.cs │ ├── AssemblyInfo.cs │ ├── CryptoHelpers.cs │ ├── DatabaseManager.cs │ ├── Elevation.cs │ ├── ExternalCommandRunner.cs │ ├── FileWatcher.cs │ ├── JsonUtils.cs │ ├── Logger.cs │ ├── NativeMethods.cs │ ├── RegistryWalker.cs │ ├── RunManager.cs │ ├── SafeTokenHandle.cs │ ├── SqliteDatabaseManager.cs │ ├── Strings.cs │ └── Win32OpenPortListenerHelper.cs ├── NOTICE.txt ├── NuGet.Config.AzureArtifacts ├── NuGet.Config.Public ├── Pipelines ├── asa-release.yml ├── core-pipeline.yml └── templates │ ├── dotnet-publish-linux-mac-job.yml │ ├── dotnet-publish-win-netcore-job.yml │ ├── dotnet-test-job.yml │ ├── nbgv-set-version-steps.yml │ ├── nuget-build-job.yml │ └── sdl-job.yml ├── README.md ├── SECURITY.md ├── SUPPORT.md ├── Tests ├── AsaAnalyzerTests.cs ├── CollectorTests.cs ├── DatabaseManagerTests.cs ├── ExportTests.cs ├── HydrationTests.cs ├── InDatabaseComparatorTests.cs ├── InMemoryComparatorTests.cs ├── TestData │ └── ExportTests │ │ └── TestGenerateSarifLog │ │ ├── output.json │ │ └── rules.json ├── Tests.csproj ├── TpmSim.cs └── TpmSim │ ├── Simulator.exe │ ├── concrt140d.dll │ ├── msvcp140_1d.dll │ ├── msvcp140_2d.dll │ ├── msvcp140d.dll │ ├── tpm.dll │ ├── vccorlib140d.dll │ └── vcruntime140d.dll ├── Tools ├── Docker │ ├── AsaDetonatorLinux │ │ ├── Detonate.sh │ │ ├── Dockerfile │ │ └── docker-compose.yml │ └── AsaDetonatorWindows │ │ ├── Detonate.ps1 │ │ ├── Dockerfile │ │ ├── GetUniqueIdentitiesFromCollections.ps1 │ │ └── docker-compose.yml └── scripts │ ├── GetUniqueFilePathCounts.sql │ ├── GetUniqueRegkeyCounts.sql │ ├── LinuxCronGather.sh │ └── WindowsGatherer.ps1 ├── analyses.json ├── docfx ├── .gitignore ├── api │ ├── .gitignore │ └── index.md ├── docfx.json ├── index.md └── toc.yml ├── icon-128.png └── version.json /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | 3 | # CA2008: Do not create tasks without passing a TaskScheduler 4 | dotnet_diagnostic.CA2008.severity = none 5 | 6 | # CA2100: Review SQL queries for security vulnerabilities 7 | dotnet_diagnostic.CA2100.severity = none 8 | 9 | # CA1307: Specify StringComparison 10 | dotnet_diagnostic.CA1307.severity = none 11 | 12 | # CA1031: General Exceptions 13 | dotnet_diagnostic.CA1031.severity = none 14 | 15 | # CA1707: Remove the underscores from type name AttackSurfaceAnalyzer.Types.RUN_TYPE. 16 | dotnet_diagnostic.CA1707.severity = none 17 | 18 | # CA2227: Collection properties should be read only 19 | dotnet_diagnostic.CA2227.severity = none 20 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 2 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 3 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: Your Bug Title Here 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **System Configuration (please complete the following information):** 27 | - OS: [e.g. Windows] 28 | - OS Version: [e.g. Windows 10 1803] 29 | - Application Version: [e.g. 2.0.1-beta+50af283871] 30 | - CLI or GUI: 31 | 32 | **Additional Context** 33 | Add any other context about the problem here. 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: Your Cool Feature Name 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. E.g. `I'm always frustrated when I can't see what runs I already have collected in my database.` 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. E.g. `I want to be able to run a command to see what runs are in the database.` 15 | 16 | **Describe alternatives you've considered** 17 | I have thought of a work around or another way to do this but they don't solve all my needs. 18 | `I understand that I can view the database in sqlite but it would be more convenient to have this feature.` 19 | 20 | **System Configuration (please complete the following information):** 21 | * OS: [e.g. Windows] 22 | * OS Version: [e.g. Windows 10 1803] 23 | * Application Version: [e.g. 2.0.1-beta+50af283871] 24 | * CLI or GUI: 25 | 26 | **Additional context** 27 | Add any other context or screenshots about the feature request here. 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/rule.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Filter Request or Submission 3 | about: Request a filter be added to the default ruleset 4 | title: 5 | labels: filters 6 | assignees: '' 7 | 8 | --- 9 | **What does this rule detect?** 10 | 11 | **Why should this rule be added?** 12 | 13 | **Does this require the addition of a new [operation](https://microsoft.github.io/AttackSurfaceAnalyzer/api/AttackSurfaceAnalyzer.Types.OPERATION.html) to the parser?** 14 | 15 | If so, this should be filed as an feature request. 16 | 17 | **Rule Json (optional)** 18 | -------------------------------------------------------------------------------- /AttackSurfaceAnalyzer.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 16 3 | VisualStudioVersion = 16.0.28803.452 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0E30E3FA-AECD-4BF3-9EAA-9D6C16D5E991}" 6 | ProjectSection(SolutionItems) = preProject 7 | .editorconfig = .editorconfig 8 | analyses.json = analyses.json 9 | BUILD.md = BUILD.md 10 | CONTRIBUTING.md = CONTRIBUTING.md 11 | filters.json = filters.json 12 | LICENSE.txt = LICENSE.txt 13 | Pipelines\pr-validation.yml = Pipelines\pr-validation.yml 14 | PRIVACY.md = PRIVACY.md 15 | README.md = README.md 16 | Pipelines\release.yml = Pipelines\release.yml 17 | Pipelines\sdl.yml = Pipelines\sdl.yml 18 | version.json = version.json 19 | EndProjectSection 20 | EndProject 21 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lib", "Lib\Lib.csproj", "{1A23CFC7-0B8B-44C0-9EB6-5D39BC456CDC}" 22 | EndProject 23 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{115B2548-2164-44B6-B0C3-717DB1145550}" 24 | EndProject 25 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{084DAC81-7495-4BF5-A3BE-0DC61F177245}" 26 | EndProject 27 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cli", "Cli\Cli.csproj", "{0E5AE46A-897E-4FEC-897B-19ECEDD8BC88}" 28 | EndProject 29 | Global 30 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 31 | Debug|Any CPU = Debug|Any CPU 32 | Release|Any CPU = Release|Any CPU 33 | EndGlobalSection 34 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 35 | {1A23CFC7-0B8B-44C0-9EB6-5D39BC456CDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {1A23CFC7-0B8B-44C0-9EB6-5D39BC456CDC}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {1A23CFC7-0B8B-44C0-9EB6-5D39BC456CDC}.Release|Any CPU.ActiveCfg = Release|Any CPU 38 | {1A23CFC7-0B8B-44C0-9EB6-5D39BC456CDC}.Release|Any CPU.Build.0 = Release|Any CPU 39 | {115B2548-2164-44B6-B0C3-717DB1145550}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 40 | {115B2548-2164-44B6-B0C3-717DB1145550}.Debug|Any CPU.Build.0 = Debug|Any CPU 41 | {115B2548-2164-44B6-B0C3-717DB1145550}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {115B2548-2164-44B6-B0C3-717DB1145550}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {084DAC81-7495-4BF5-A3BE-0DC61F177245}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 44 | {084DAC81-7495-4BF5-A3BE-0DC61F177245}.Debug|Any CPU.Build.0 = Debug|Any CPU 45 | {084DAC81-7495-4BF5-A3BE-0DC61F177245}.Release|Any CPU.ActiveCfg = Release|Any CPU 46 | {084DAC81-7495-4BF5-A3BE-0DC61F177245}.Release|Any CPU.Build.0 = Release|Any CPU 47 | {0E5AE46A-897E-4FEC-897B-19ECEDD8BC88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 48 | {0E5AE46A-897E-4FEC-897B-19ECEDD8BC88}.Debug|Any CPU.Build.0 = Debug|Any CPU 49 | {0E5AE46A-897E-4FEC-897B-19ECEDD8BC88}.Release|Any CPU.ActiveCfg = Release|Any CPU 50 | {0E5AE46A-897E-4FEC-897B-19ECEDD8BC88}.Release|Any CPU.Build.0 = Release|Any CPU 51 | EndGlobalSection 52 | GlobalSection(SolutionProperties) = preSolution 53 | HideSolutionNode = FALSE 54 | EndGlobalSection 55 | GlobalSection(ExtensibilityGlobals) = postSolution 56 | SolutionGuid = {CF34C31E-FA0E-4FB8-B566-6907C5F6339E} 57 | EndGlobalSection 58 | GlobalSection(MonoDevelopProperties) = preSolution 59 | version = 2.1-alpha 60 | EndGlobalSection 61 | EndGlobal 62 | -------------------------------------------------------------------------------- /AttackSurfaceAnalyzer.sln.licenseheader: -------------------------------------------------------------------------------- 1 | extensions: .cs 2 | // Copyright (c) Microsoft Corporation. All rights reserved. 3 | // Licensed under the MIT License. 4 | extensions: .js 5 | // Copyright (c) Microsoft Corporation. All rights reserved. 6 | // Licensed under the MIT License. -------------------------------------------------------------------------------- /BUILD.md: -------------------------------------------------------------------------------- 1 | # Build How-to 2 | 3 | ## Pre-requisites 4 | 5 | ### All Components: 6 | - Latest .NET Core SDK 5.0 (https://dotnet.microsoft.com/download) 7 | - GitVersioning (```dotnet tool install -g nbgv```) 8 | 9 | ### GUI: 10 | - Make sure to select ```ASP.NET Components``` in Visual Studio (You will otherwise receive an error opening this project) 11 | 12 | ## Building 13 | 14 | Run these commands in the appropriate project directory. For example, ```Cli``` for the Cli and Gui. 15 | 16 | ### Building a Debug version 17 | Note that `dotnet build` is only supported with the Debug configuration. 18 | 19 | ``` 20 | dotnet build -c Debug 21 | ``` 22 | 23 | ### Publishing a Release version 24 | Note that `dotnet publish` is only supported with the Release configuration 25 | 26 | Windows 27 | ``` 28 | dotnet publish -c Release -r win-x86 29 | ``` 30 | 31 | Linux 32 | ``` 33 | dotnet publish -c Release -r linux-x64 34 | ``` 35 | 36 | Mac 37 | ``` 38 | dotnet publish -c Release -r osx-x64 39 | ``` 40 | 41 | Framework Dependent .NET Core App 42 | ``` 43 | dotnet publish -c Release 44 | ``` 45 | -------------------------------------------------------------------------------- /Benchmarks/AsaDatabaseBenchmark.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CST.AttackSurfaceAnalyzer.Objects; 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Utils; 3 | using System.Collections.Concurrent; 4 | 5 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Benchmarks 6 | { 7 | public class AsaDatabaseBenchmark 8 | { 9 | // Bag of reusable objects to write to the database. 10 | public static readonly ConcurrentBag BagOfObjects = new ConcurrentBag(); 11 | 12 | public static FileSystemObject GetRandomObject(int ObjectPadding = 0) 13 | { 14 | BagOfObjects.TryTake(out FileSystemObject? obj); 15 | 16 | if (obj != null) 17 | { 18 | obj.Path = CryptoHelpers.GetRandomString(32); 19 | return obj; 20 | } 21 | else 22 | { 23 | return new FileSystemObject(CryptoHelpers.GetRandomString(32)) 24 | { 25 | // Pad this field with extra data. 26 | FileType = CryptoHelpers.GetRandomString(ObjectPadding), 27 | }; 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Benchmarks/Benchmarks.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net5.0 6 | 2.1-alpha 7 | 8.0 8 | enable 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Benchmarks/CommitTest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CST.AttackSurfaceAnalyzer.Utils; 2 | using BenchmarkDotNet.Attributes; 3 | 4 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Benchmarks 5 | { 6 | [MarkdownExporterAttribute.GitHub] 7 | [JsonExporterAttribute.Full] 8 | public class CommitTest 9 | { 10 | #nullable disable 11 | 12 | public CommitTest() 13 | #nullable enable 14 | { 15 | Logger.Setup(true, true); 16 | Strings.Setup(); 17 | } 18 | 19 | [Params("OFF", "DELETE", "WAL", "MEMORY")] 20 | public string JournalMode { get; set; } 21 | 22 | //Rows to write in the open transaction before the commit 23 | [Params(10000, 20000, 40000)] 24 | public int N { get; set; } 25 | 26 | // The number of Shards/Threads to use for Database operations 27 | [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)] 28 | public int Shards { get; set; } 29 | 30 | [Benchmark] 31 | public void CommitTransaction() 32 | { 33 | dbManager.Commit(); 34 | } 35 | 36 | [IterationCleanup] 37 | public void IterationCleanup() 38 | { 39 | dbManager.Destroy(); 40 | } 41 | 42 | [IterationSetup] 43 | public void IterationSetup() 44 | { 45 | Setup(); 46 | dbManager.BeginTransaction(); 47 | InsertTestsWithoutTransactions.Insert_X_Objects(N, dbManager); 48 | } 49 | 50 | public void Setup() 51 | { 52 | dbManager = new SqliteDatabaseManager(filename: $"AsaBenchmark_{Shards}.sqlite", new DBSettings() 53 | { 54 | JournalMode = JournalMode, 55 | ShardingFactor = Shards 56 | }); 57 | dbManager.Setup(); 58 | } 59 | 60 | private DatabaseManager dbManager; 61 | 62 | #nullable disable 63 | } 64 | } -------------------------------------------------------------------------------- /Benchmarks/InsertTestsWithIntermittentTransactions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CST.AttackSurfaceAnalyzer.Utils; 2 | using BenchmarkDotNet.Attributes; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Benchmarks 7 | { 8 | [MarkdownExporterAttribute.GitHub] 9 | [JsonExporterAttribute.Full] 10 | public class InsertTestsWithIntermittentTransactions : AsaDatabaseBenchmark 11 | { 12 | #nullable disable 13 | 14 | public InsertTestsWithIntermittentTransactions() 15 | #nullable restore 16 | { 17 | Logger.Setup(true, true); 18 | Strings.Setup(); 19 | } 20 | 21 | // If not -1, how many records each writer should write before committing. When -1 don't do checkpoint commits. 22 | [Params(-1)] 23 | public int FlushCount { get; set; } 24 | 25 | // Journaling mode, options are 26 | //[Params("OFF","DELETE","WAL","MEMORY")] 27 | [Params("WAL")] 28 | public string JournalMode { get; set; } 29 | 30 | // The number of records to insert for the benchmark 31 | //[Params(25000,50000,100000)] 32 | [Params(100000, 1000000)] 33 | public int N { get; set; } 34 | 35 | // The amount of padding to add to the object in bytes Default size is approx 530 bytes serialized 36 | // Does not include SQL overhead 37 | [Params(0)] 38 | public int ObjectPadding { get; set; } 39 | 40 | // The number of Shards/Threads to use for Database operations 41 | [Params(6)] 42 | public int Shards { get; set; } 43 | 44 | // The number of records to populate the database with before the benchmark 45 | //[Params(0,100000,200000,400000,800000,1600000,3200000)] 46 | [Params(0)] 47 | public int StartingSize { get; set; } 48 | 49 | // Bag of reusable objects to write to the database. 50 | 51 | public static void Insert_X_Objects(int X, int ObjectPadding = 0, string runName = "Insert_X_Objects") 52 | { 53 | dbManager.BeginTransaction(); 54 | 55 | Parallel.For(0, X, i => 56 | { 57 | var obj = GetRandomObject(ObjectPadding); 58 | dbManager.Write(obj, runName); 59 | BagOfObjects.Add(obj); 60 | }); 61 | 62 | while (dbManager.HasElements) 63 | { 64 | Thread.Sleep(1); 65 | } 66 | 67 | dbManager.Commit(); 68 | } 69 | 70 | [GlobalCleanup] 71 | public void GlobalCleanup() 72 | { 73 | Setup(); 74 | dbManager.Destroy(); 75 | } 76 | 77 | [GlobalSetup] 78 | public void GlobalSetup() 79 | { 80 | PopulateDatabases(); 81 | } 82 | 83 | [Benchmark] 84 | public void Insert_N_Objects() => Insert_X_Objects(N, ObjectPadding, "Insert_N_Objects"); 85 | 86 | [IterationCleanup] 87 | public void IterationCleanup() 88 | { 89 | dbManager.BeginTransaction(); 90 | dbManager.DeleteRun("Insert_N_Objects"); 91 | dbManager.Commit(); 92 | dbManager.Vacuum(); 93 | dbManager.CloseDatabase(); 94 | } 95 | 96 | [IterationSetup] 97 | public void IterationSetup() 98 | { 99 | Setup(); 100 | } 101 | 102 | public void PopulateDatabases() 103 | { 104 | Setup(); 105 | 106 | Insert_X_Objects(StartingSize, ObjectPadding, "PopulateDatabase"); 107 | 108 | dbManager.CloseDatabase(); 109 | } 110 | 111 | public void Setup() 112 | { 113 | dbManager = new SqliteDatabaseManager(filename: $"AsaBenchmark_{Shards}.sqlite", new DBSettings() 114 | { 115 | ShardingFactor = Shards, 116 | FlushCount = FlushCount, 117 | JournalMode = JournalMode 118 | }); 119 | dbManager.Setup(); 120 | } 121 | 122 | private static DatabaseManager dbManager; 123 | } 124 | } -------------------------------------------------------------------------------- /Benchmarks/InsertTestsWithoutTransactions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CST.AttackSurfaceAnalyzer.Utils; 2 | using BenchmarkDotNet.Attributes; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Benchmarks 7 | { 8 | [MarkdownExporterAttribute.GitHub] 9 | [JsonExporterAttribute.Full] 10 | public class InsertTestsWithoutTransactions : AsaDatabaseBenchmark 11 | { 12 | #nullable disable 13 | 14 | public InsertTestsWithoutTransactions() 15 | #nullable restore 16 | { 17 | Logger.Setup(true, true); 18 | Strings.Setup(); 19 | } 20 | 21 | [Params(10)] 22 | public int BatchSize { get; set; } 23 | 24 | //[Params("OFF","DELETE","WAL","MEMORY")] 25 | [Params("DELETE")] 26 | public string JournalMode { get; set; } 27 | 28 | [Params("NORMAL")] 29 | public string LockingMode { get; set; } 30 | 31 | // The number of records to insert for the benchmark 32 | //[Params(25000,50000,100000)] 33 | [Params(10000)] 34 | public int N { get; set; } 35 | 36 | // The amount of padding to add to the object in bytes Default size is approx 530 bytes serialized 37 | // Does not include SQL overhead 38 | [Params(0, 4500)] 39 | public int ObjectPadding { get; set; } 40 | 41 | [Params(4096)] 42 | public int PageSize { get; set; } 43 | 44 | // The number of Shards/Threads to use for Database operations 45 | [Params(1)] 46 | public int Shards { get; set; } 47 | 48 | // The number of records to populate the database with before the benchmark 49 | //[Params(0,100000,200000,400000,800000,1600000,3200000)] 50 | [Params(0)] 51 | public int StartingSize { get; set; } 52 | 53 | [Params("OFF")] 54 | public string Synchronous { get; set; } 55 | 56 | public static void Insert_X_Objects(int X, DatabaseManager dbManager, int ObjectPadding = 0, string runName = "Insert_X_Objects") 57 | { 58 | Parallel.For(0, X, i => 59 | { 60 | var obj = GetRandomObject(ObjectPadding); 61 | dbManager.Write(obj, runName); 62 | BagOfObjects.Add(obj); 63 | }); 64 | 65 | while (dbManager.HasElements) 66 | { 67 | Thread.Sleep(1); 68 | } 69 | } 70 | 71 | [GlobalCleanup] 72 | public void GlobalCleanup() 73 | { 74 | Setup(); 75 | dbManager.Destroy(); 76 | } 77 | 78 | [GlobalSetup] 79 | public void GlobalSetup() 80 | { 81 | PopulateDatabases(); 82 | } 83 | 84 | [Benchmark] 85 | public void Insert_N_Objects() => Insert_X_Objects(N, dbManager, ObjectPadding, "Insert_N_Objects"); 86 | 87 | [IterationCleanup] 88 | public void IterationCleanup() 89 | { 90 | dbManager.CloseDatabase(); 91 | } 92 | 93 | [IterationSetup] 94 | public void IterationSetup() 95 | { 96 | Setup(); 97 | dbManager.BeginTransaction(); 98 | } 99 | 100 | public void PopulateDatabases() 101 | { 102 | Setup(); 103 | dbManager.BeginTransaction(); 104 | 105 | Insert_X_Objects(StartingSize, dbManager, ObjectPadding, "PopulateDatabase"); 106 | 107 | dbManager.Commit(); 108 | dbManager.CloseDatabase(); 109 | } 110 | 111 | private DatabaseManager dbManager; 112 | 113 | private void Setup() 114 | { 115 | dbManager = new SqliteDatabaseManager(filename: $"AsaBenchmark_{Shards}.sqlite", new DBSettings() 116 | { 117 | JournalMode = JournalMode, 118 | LockingMode = LockingMode, 119 | PageSize = PageSize, 120 | ShardingFactor = Shards, 121 | Synchronous = Synchronous, 122 | BatchSize = BatchSize 123 | }); 124 | 125 | dbManager.Setup(); 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /Benchmarks/OpenTransactionTest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CST.AttackSurfaceAnalyzer.Utils; 2 | using BenchmarkDotNet.Attributes; 3 | 4 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Benchmarks 5 | { 6 | [MarkdownExporterAttribute.GitHub] 7 | [JsonExporterAttribute.Full] 8 | public class OpenTransactionTest : AsaDatabaseBenchmark 9 | { 10 | #nullable disable 11 | 12 | public OpenTransactionTest() 13 | #nullable restore 14 | { 15 | Logger.Setup(true, true); 16 | Strings.Setup(); 17 | } 18 | 19 | [Params("OFF", "DELETE", "WAL", "MEMORY")] 20 | public string JournalMode { get; set; } 21 | 22 | // The number of Shards/Threads to use for Database operations 23 | [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)] 24 | public int Shards { get; set; } 25 | 26 | // The number of records to populate the database with before the benchmark 27 | //[Params(0,100000,200000,400000,800000,1600000,3200000)] 28 | [Params(0)] 29 | public int StartingSize { get; set; } 30 | 31 | [Benchmark] 32 | public void BeginTransaction() 33 | { 34 | dbManager.BeginTransaction(); 35 | } 36 | 37 | [GlobalCleanup] 38 | public void GlobalCleanup() 39 | { 40 | Setup(); 41 | dbManager.Destroy(); 42 | } 43 | 44 | [GlobalSetup] 45 | public void GlobalSetup() 46 | { 47 | PopulateDatabases(); 48 | } 49 | 50 | [IterationCleanup] 51 | public void IterationCleanup() 52 | { 53 | dbManager.CloseDatabase(); 54 | } 55 | 56 | [IterationSetup] 57 | public void IterationSetup() 58 | { 59 | Setup(); 60 | } 61 | 62 | public void PopulateDatabases() 63 | { 64 | Setup(); 65 | dbManager.BeginTransaction(); 66 | 67 | InsertTestsWithoutTransactions.Insert_X_Objects(StartingSize, dbManager, 0, "Insert_X_Objects"); 68 | 69 | dbManager.Commit(); 70 | dbManager.CloseDatabase(); 71 | } 72 | 73 | public void Setup() 74 | { 75 | dbManager = new SqliteDatabaseManager(filename: $"AsaBenchmark_{Shards}.sqlite", new DBSettings() 76 | { 77 | JournalMode = JournalMode, 78 | ShardingFactor = Shards 79 | }); 80 | dbManager.Setup(); 81 | } 82 | 83 | private DatabaseManager dbManager; 84 | } 85 | } -------------------------------------------------------------------------------- /Benchmarks/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | 3 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Benchmarks 4 | { 5 | public class Program 6 | { 7 | public static void Main(string[] args) 8 | { 9 | var summary = BenchmarkRunner.Run(); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Benchmarks/SetupTimeTest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CST.AttackSurfaceAnalyzer.Utils; 2 | using BenchmarkDotNet.Attributes; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Benchmarks 7 | { 8 | [MarkdownExporterAttribute.GitHub] 9 | [JsonExporterAttribute.Full] 10 | public class SetupTimeTest : AsaDatabaseBenchmark 11 | { 12 | #nullable disable 13 | 14 | public SetupTimeTest() 15 | #nullable restore 16 | { 17 | Logger.Setup(true, true); 18 | Strings.Setup(); 19 | } 20 | 21 | //[Params("OFF","DELETE","WAL","MEMORY")] 22 | [Params("OFF", "DELETE", "WAL", "MEMORY")] 23 | public string JournalMode { get; set; } 24 | 25 | [Params("NORMAL", "EXCLUSIVE")] 26 | public string LockingMode { get; set; } 27 | 28 | // The amount of padding to add to the object in bytes Default size is approx 530 bytes serialized 29 | // Does not include SQL overhead 30 | [Params(0)] 31 | public int ObjectPadding { get; set; } 32 | 33 | [Params(4096)] 34 | public int PageSize { get; set; } 35 | 36 | // The number of Shards/Threads to use for Database operations 37 | [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)] 38 | public int Shards { get; set; } 39 | 40 | // The number of records to populate the database with before the benchmark 41 | //[Params(0,100000,200000,400000,800000,1600000,3200000)] 42 | [Params(0, 10000000)] 43 | public int StartingSize { get; set; } 44 | 45 | [Params("OFF", "NORMAL")] 46 | public string Synchronous { get; set; } 47 | 48 | [GlobalCleanup] 49 | public void GlobalCleanup() 50 | { 51 | Setup(); 52 | dbManager.Destroy(); 53 | } 54 | 55 | [GlobalSetup] 56 | public void GlobalSetup() 57 | { 58 | PopulateDatabases(); 59 | } 60 | 61 | public void Insert_X_Objects(int X, int ObjectPadding = 0, string runName = "Insert_X_Objects") 62 | { 63 | Parallel.For(0, X, i => 64 | { 65 | var obj = GetRandomObject(ObjectPadding); 66 | dbManager.Write(obj, runName); 67 | BagOfObjects.Add(obj); 68 | }); 69 | 70 | while (dbManager.HasElements) 71 | { 72 | Thread.Sleep(1); 73 | } 74 | } 75 | 76 | [IterationCleanup] 77 | public void IterationCleanup() 78 | { 79 | dbManager.CloseDatabase(); 80 | } 81 | 82 | [IterationSetup] 83 | public void IterationSetup() 84 | { 85 | } 86 | 87 | public void PopulateDatabases() 88 | { 89 | Setup(); 90 | dbManager.BeginTransaction(); 91 | 92 | Insert_X_Objects(StartingSize, ObjectPadding, "PopulateDatabase"); 93 | 94 | dbManager.Commit(); 95 | dbManager.CloseDatabase(); 96 | } 97 | 98 | private DatabaseManager dbManager; 99 | 100 | [Benchmark] 101 | private void Setup() 102 | { 103 | dbManager = new SqliteDatabaseManager(filename: $"AsaBenchmark_{Shards}.sqlite", new DBSettings() 104 | { 105 | JournalMode = JournalMode, 106 | LockingMode = LockingMode, 107 | PageSize = PageSize, 108 | ShardingFactor = Shards, 109 | Synchronous = Synchronous 110 | }); 111 | 112 | dbManager.Setup(); 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /Benchmarks/SystemSqliteInsertTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CST.AttackSurfaceAnalyzer.Utils; 2 | using BenchmarkDotNet.Attributes; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Benchmarks 7 | { 8 | [MarkdownExporterAttribute.GitHub] 9 | [JsonExporterAttribute.Full] 10 | public class SystemSqliteInsertTestsWithoutTransactions : AsaDatabaseBenchmark 11 | { 12 | #nullable disable 13 | 14 | public SystemSqliteInsertTestsWithoutTransactions() 15 | #nullable restore 16 | { 17 | Logger.Setup(true, true); 18 | Strings.Setup(); 19 | } 20 | 21 | //[Params("OFF","DELETE","WAL","MEMORY")] 22 | [Params("WAL")] 23 | public string JournalMode { get; set; } 24 | 25 | [Params("NORMAL")] 26 | public string LockingMode { get; set; } 27 | 28 | // The number of records to insert for the benchmark 29 | //[Params(25000,50000,100000)] 30 | [Params(10000)] 31 | public int N { get; set; } 32 | 33 | // The amount of padding to add to the object in bytes Default size is approx 530 bytes serialized 34 | // Does not include SQL overhead 35 | [Params(0)] 36 | public int ObjectPadding { get; set; } 37 | 38 | [Params(4096)] 39 | public int PageSize { get; set; } 40 | 41 | // The number of Shards/Threads to use for Database operations 42 | [Params(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)] 43 | public int Shards { get; set; } 44 | 45 | // The number of records to populate the database with before the benchmark 46 | //[Params(0,100000,200000,400000,800000,1600000,3200000)] 47 | [Params(0)] 48 | public int StartingSize { get; set; } 49 | 50 | [Params("OFF")] 51 | public string Synchronous { get; set; } 52 | 53 | public static void Insert_X_Objects(int X, int ObjectPadding = 0, string runName = "Insert_X_Objects") 54 | { 55 | Parallel.For(0, X, i => 56 | { 57 | var obj = GetRandomObject(ObjectPadding); 58 | SystemSQLiteDatabaseManager.Write(obj, runName); 59 | BagOfObjects.Add(obj); 60 | }); 61 | 62 | while (SystemSQLiteDatabaseManager.HasElements()) 63 | { 64 | Thread.Sleep(1); 65 | } 66 | } 67 | 68 | [GlobalCleanup] 69 | public void GlobalCleanup() 70 | { 71 | Setup(); 72 | SystemSQLiteDatabaseManager.Destroy(); 73 | } 74 | 75 | [GlobalSetup] 76 | public void GlobalSetup() 77 | { 78 | PopulateDatabases(); 79 | } 80 | 81 | [Benchmark] 82 | public void Insert_N_Objects() => Insert_X_Objects(N, ObjectPadding, "Insert_N_Objects"); 83 | 84 | [IterationCleanup] 85 | public void IterationCleanup() 86 | { 87 | SystemSQLiteDatabaseManager.CloseDatabase(); 88 | } 89 | 90 | [IterationSetup] 91 | public void IterationSetup() 92 | { 93 | Setup(); 94 | SystemSQLiteDatabaseManager.BeginTransaction(); 95 | } 96 | 97 | public void PopulateDatabases() 98 | { 99 | Setup(); 100 | SystemSQLiteDatabaseManager.BeginTransaction(); 101 | 102 | Insert_X_Objects(StartingSize, ObjectPadding, "PopulateDatabase"); 103 | 104 | SystemSQLiteDatabaseManager.Commit(); 105 | SystemSQLiteDatabaseManager.CloseDatabase(); 106 | } 107 | 108 | private void Setup() 109 | { 110 | SystemSQLiteDatabaseManager.Setup(filename: $"AsaBenchmark_{Shards}.sqlite", new DBSettings() 111 | { 112 | JournalMode = JournalMode, 113 | LockingMode = LockingMode, 114 | PageSize = PageSize, 115 | ShardingFactor = Shards, 116 | Synchronous = Synchronous 117 | }); 118 | } 119 | } 120 | } -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com. 2 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. 3 | This project has adopted the [Microsoft Open Source Code of Conduct] (https://opensource.microsoft.com/codeofconduct/). 4 | For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments. -------------------------------------------------------------------------------- /Cli/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 |

Sorry, there's nothing at this address.

8 |
9 |
10 |
-------------------------------------------------------------------------------- /Cli/AppData.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CST.AttackSurfaceAnalyzer.Objects; 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | using System.Collections.Generic; 4 | 5 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli 6 | { 7 | public class AppData 8 | { 9 | public CollectCommandOptions CollectOptions { get; set; } = new CollectCommandOptions(); 10 | public MonitorCommandOptions MonitorOptions { get; set; } = new MonitorCommandOptions(); 11 | public ExportCollectCommandOptions ExportCollectCommandOptions { get; set; } = new ExportCollectCommandOptions(); 12 | public string FirstRunId 13 | { 14 | get 15 | { 16 | return $"{RunId}-before"; 17 | } 18 | } 19 | 20 | public string SecondRunId 21 | { 22 | get 23 | { 24 | return $"{RunId}-after"; 25 | } 26 | } 27 | 28 | public string MonitorRunId 29 | { 30 | get 31 | { 32 | return $"{RunId}-monitoring"; 33 | } 34 | } 35 | 36 | public Dictionary DefaultLevels = new Dictionary(); 37 | public List Rules { get; set; } = new List(); 38 | public List TestObjects { get; set; } = new List(); 39 | 40 | public string RunId { get; set; } = string.Empty; 41 | public CompareCommandOptions CompareCommandOptions { 42 | get 43 | { 44 | return new CompareCommandOptions(ExportCollectCommandOptions.FirstRunId, ExportCollectCommandOptions.SecondRunId) 45 | { 46 | ApplySubObjectRulesToMonitor = true, 47 | AnalysesFile = RuleFile.LoadEmbeddedFilters(), 48 | DatabaseFilename = ExportCollectCommandOptions.DatabaseFilename, 49 | DisableAnalysis = ExportCollectCommandOptions.DisableAnalysis, 50 | SaveToDatabase = ExportCollectCommandOptions.SaveToDatabase, 51 | RunScripts = ExportCollectCommandOptions.RunScripts 52 | }; 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /Cli/Cli.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | InProcess 6 | Exe 7 | 2.1-alpha 8 | 9.0 9 | enable 10 | Asa 11 | Microsoft.CST.AttackSurfaceAnalyzer.Cli 12 | © Microsoft Corporation. All rights reserved. 13 | Microsoft 14 | Microsoft 15 | Microsoft Attack Surface Analyzer is an open source security tool that analyzes the attack surface of a target system and reports on potential security vulnerabilities introduced during the installation of software or system misconfiguration. This is a Dotnet Tool package. For the library package, see Microsoft.CST.AttackSurfaceAnalyzer. 16 | false 17 | true 18 | true 19 | Microsoft.CST.AttackSurfaceAnalyzer.CLI 20 | 0.0.0 21 | https://github.com/Microsoft/AttackSurfaceAnalyzer 22 | Security Scanner 23 | asa 24 | LICENSE.txt 25 | icon-128.png 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Cli/Components/AnalyzeOptionsRazor.razor: -------------------------------------------------------------------------------- 1 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData 2 | @using Microsoft.CST.AttackSurfaceAnalyzer.Cli 3 | 4 |
5 |
6 |
7 | 8 | 9 |
10 |
11 |
12 | 13 | @code{ 14 | bool EnableAnalysis 15 | { 16 | get 17 | { 18 | return !appData.ExportCollectCommandOptions.DisableAnalysis; 19 | } 20 | set 21 | { 22 | appData.ExportCollectCommandOptions.DisableAnalysis = !value; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Cli/Components/CollectorOptions/CertificateCollectorOptions.razor: -------------------------------------------------------------------------------- 1 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData 2 | 3 |
4 |
5 |
6 | 7 | 8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /Cli/Components/CollectorOptions/ComObjectCollector.razor: -------------------------------------------------------------------------------- 1 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData 2 | 3 |
4 |
5 |
6 | 7 | 8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /Cli/Components/CollectorOptions/CryptographicKeyCollectorOptions.razor: -------------------------------------------------------------------------------- 1 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData 2 | 3 |
4 |
5 |
6 | 7 | 8 |
9 |
10 |
-------------------------------------------------------------------------------- /Cli/Components/CollectorOptions/DriverCollectorOptions.razor: -------------------------------------------------------------------------------- 1 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData 2 | 3 |
4 |
5 |
6 | 7 | 8 |
9 |
10 |
-------------------------------------------------------------------------------- /Cli/Components/CollectorOptions/EventLogCollector.razor: -------------------------------------------------------------------------------- 1 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData 2 | 3 |
4 |
5 |
6 | 7 | 8 |
9 |
10 |
11 |
12 | 13 | 14 |
15 |
16 |
-------------------------------------------------------------------------------- /Cli/Components/CollectorOptions/FilewallCollectorOptions.razor: -------------------------------------------------------------------------------- 1 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData 2 | 3 |
4 |
5 |
6 | 7 | 8 |
9 |
10 |
-------------------------------------------------------------------------------- /Cli/Components/CollectorOptions/OpenPortCollectorOptions.razor: -------------------------------------------------------------------------------- 1 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData 2 | 3 |
4 |
5 |
6 | 7 | 8 |
9 |
10 |
-------------------------------------------------------------------------------- /Cli/Components/CollectorOptions/ProcessCollectorOptions.razor: -------------------------------------------------------------------------------- 1 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData 2 | 3 |
4 |
5 |
6 | 7 | 8 |
9 |
10 |
-------------------------------------------------------------------------------- /Cli/Components/CollectorOptions/RegistryCollectorOptions.razor: -------------------------------------------------------------------------------- 1 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData 2 | 3 |
4 |
5 |
6 | 7 | 8 |
9 |
10 |
11 | 12 |
13 |
14 | 15 |
16 |
17 | 18 |
19 |
20 |
21 |
22 | 23 |
24 |
25 | 31 |
32 |
33 | 34 |
35 |
36 |
37 |
38 | 39 | @code{ 40 | Helper.GlowClass directorySelectElementGlowClass = new Helper.GlowClass(); 41 | 42 | string SelectedHiveInput = string.Empty; 43 | int SelectedHiveTop; 44 | 45 | void RemoveInputFromList() 46 | { 47 | appData.CollectOptions.SelectedHives = appData.CollectOptions.SelectedDirectories.Except(appData.CollectOptions.SelectedDirectories.Skip(SelectedHiveTop-1).Take(1)); 48 | Helper.ToggleGlow(() => InvokeAsync(StateHasChanged), directorySelectElementGlowClass, false); 49 | } 50 | 51 | void PushInputToList() 52 | { 53 | appData.CollectOptions.SelectedHives = appData.CollectOptions.SelectedHives.Union(new string[] { SelectedHiveInput }); 54 | SelectedHiveTop = appData.CollectOptions.SelectedHives.Count() - 1; 55 | Helper.ToggleGlow(() => InvokeAsync(StateHasChanged), directorySelectElementGlowClass, true); 56 | SelectedHiveInput = string.Empty; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Cli/Components/CollectorOptions/ServiceCollectorOptions.Razor: -------------------------------------------------------------------------------- 1 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData 2 | 3 |
4 |
5 |
6 | 7 | 8 |
9 |
10 |
-------------------------------------------------------------------------------- /Cli/Components/CollectorOptions/TpmCollectorOptions.Razor: -------------------------------------------------------------------------------- 1 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData 2 | 3 |
4 |
5 |
6 | 7 | 8 |
9 |
10 |
-------------------------------------------------------------------------------- /Cli/Components/CollectorOptions/UserCollectorOptions.Razor: -------------------------------------------------------------------------------- 1 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData 2 | 3 |
4 |
5 |
6 | 7 | 8 |
9 |
10 |
-------------------------------------------------------------------------------- /Cli/Components/CollectorOptions/WifiCollectorOptions.Razor: -------------------------------------------------------------------------------- 1 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData 2 | 3 |
4 |
5 |
6 | 7 | 8 |
9 |
10 |
11 |
12 | 13 | 14 |
15 |
16 |
-------------------------------------------------------------------------------- /Cli/Components/CollectorOptionsRazor.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.CST.AttackSurfaceAnalyzer.Cli.Components.CollectorOptions 2 | 3 |
4 |
5 | 6 |
7 |
8 | 9 |
10 |
11 |
12 |
13 |
14 | 15 | 16 | 17 | 18 |
19 |
20 | 21 | 22 | 23 | 24 |
25 |
26 | 27 | 28 | 29 | 30 |
31 |
32 | -------------------------------------------------------------------------------- /Cli/Components/MonitorOptions/FileMonitorOptions.razor: -------------------------------------------------------------------------------- 1 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData 2 | @using Microsoft.CST.AttackSurfaceAnalyzer.Cli 3 | 4 |
5 |
6 |
7 | 8 | 9 |
10 |
11 |
12 |
13 | 14 | 15 |
16 |
17 |
18 | 19 |
20 |
21 | 22 |
23 |
24 | 25 |
26 |
27 |
28 |
29 | 30 |
31 |
32 | 38 |
39 |
40 | 41 |
42 |
43 |
44 |
45 | 46 | @code{ 47 | Helper.GlowClass directorySelectElementGlowClass = new Helper.GlowClass(); 48 | 49 | string SelectedDirectoryInput = string.Empty; 50 | int SelectedDirectoryTop; 51 | 52 | void RemoveInputFromList() 53 | { 54 | appData.MonitorOptions.MonitoredDirectories = appData.MonitorOptions.MonitoredDirectories.Except(appData.MonitorOptions.MonitoredDirectories.Skip(SelectedDirectoryTop-1).Take(1)); 55 | Helper.ToggleGlow(() => InvokeAsync(StateHasChanged), directorySelectElementGlowClass, false); 56 | } 57 | 58 | void PushInputToList() 59 | { 60 | appData.MonitorOptions.MonitoredDirectories = appData.MonitorOptions.MonitoredDirectories.Union(new string[] { SelectedDirectoryInput }); 61 | SelectedDirectoryTop = appData.MonitorOptions.MonitoredDirectories.Count() - 1; 62 | Helper.ToggleGlow(() => InvokeAsync(StateHasChanged), directorySelectElementGlowClass, true); 63 | SelectedDirectoryInput = string.Empty; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Cli/Components/MonitorOptionsRazor.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.CST.AttackSurfaceAnalyzer.Cli.Components.MonitorOptions 2 | 3 | -------------------------------------------------------------------------------- /Cli/Components/States/Analyzing.razor: -------------------------------------------------------------------------------- 1 | 

Running Analysis...

2 |
-------------------------------------------------------------------------------- /Cli/Components/States/MonitorFlushing.razor: -------------------------------------------------------------------------------- 1 | 

Flushing monitors. Please wait.

-------------------------------------------------------------------------------- /Cli/Components/States/Monitoring.razor: -------------------------------------------------------------------------------- 1 | 

Running Monitoring. Perform desired system changes and press 'Stop' when finished.

2 | 3 | 4 | @code{ 5 | [Parameter] 6 | public Action Continue { get; set; } = delegate () { }; 7 | } -------------------------------------------------------------------------------- /Cli/Components/States/Scanning.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.CST.AttackSurfaceAnalyzer.Collectors 2 |

Running Scan...

3 |
4 | @foreach (BaseCollector collector in AttackSurfaceAnalyzerClient.GetCollectors()) 5 | { 6 |
@collector.GetType().ToString(): @collector.RunStatus
7 | } 8 | -------------------------------------------------------------------------------- /Cli/Helper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Components; 6 | 7 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli 8 | { 9 | public static class Helper 10 | { 11 | /// 12 | /// This class just serves to make a reference type version of the class name to use 13 | /// 14 | public class GlowClass 15 | { 16 | public string ClassName { get; set; } = string.Empty; 17 | } 18 | 19 | public static string GetGlowClass(bool value) 20 | { 21 | return value ? "glowBlue" : "glowRed"; 22 | } 23 | 24 | public static void ToggleGlow(Action RefreshCallback, GlowClass Variable, bool GlowType, int Duration = 500) 25 | { 26 | Variable.ClassName = GetGlowClass(GlowType); 27 | RefreshCallback(); 28 | Task.Run(() => 29 | { 30 | WaitAndResetGlow(RefreshCallback, Variable, Duration); 31 | }); 32 | } 33 | 34 | static void WaitAndResetGlow(Action RefreshCallback, GlowClass Variable, int Duration) 35 | { 36 | Task.Delay(Duration).Wait(); 37 | Variable.ClassName = string.Empty; 38 | RefreshCallback(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Cli/Pages/Configure.razor: -------------------------------------------------------------------------------- 1 | @page "/configure" 2 | 3 |

Manage Runs

4 | 5 |
6 |
7 | 8 | 14 | 15 |
16 |
17 | 18 | 24 | 25 |
26 |
27 | 28 | 29 | 30 | 31 | @code { 32 | public int SelectedRun { get; set; } 33 | 34 | public int SelectedCompareRun { get; set; } 35 | 36 | public List Runs = AttackSurfaceAnalyzerClient.DatabaseManager.GetRuns(); 37 | 38 | public List<(string firstRunId, string secondRunId, string analysesHash, RUN_STATUS runStatus)> CompareRuns = AttackSurfaceAnalyzerClient.DatabaseManager.GetCompareRuns(); 39 | 40 | public void DeleteSelected() 41 | { 42 | AttackSurfaceAnalyzerClient.DatabaseManager.DeleteRun(Runs[SelectedRun]); 43 | Runs = AttackSurfaceAnalyzerClient.DatabaseManager.GetRuns(); 44 | this.StateHasChanged(); 45 | } 46 | 47 | public void DeleteSelectedCompare() 48 | { 49 | AttackSurfaceAnalyzerClient.DatabaseManager.DeleteCompareRun(CompareRuns[SelectedCompareRun].firstRunId, CompareRuns[SelectedCompareRun].secondRunId, CompareRuns[SelectedCompareRun].analysesHash); 50 | CompareRuns = AttackSurfaceAnalyzerClient.DatabaseManager.GetCompareRuns(); 51 | this.StateHasChanged(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Cli/Pages/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | 3 | 4 |

Error.

5 |

An error occurred while processing your request.

6 | 7 |

Development Mode

8 |

9 | Swapping to Development environment will display more detailed information about the error that occurred. 10 |

11 |

12 | The Development environment shouldn't be enabled for deployed applications. 13 | It can result in displaying sensitive information from exceptions to end users. 14 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 15 | and restarting the app. 16 |

17 | -------------------------------------------------------------------------------- /Cli/Pages/Home.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.CST.AttackSurfaceAnalyzer.Utils 2 | 3 | @page "/" 4 | 5 |
6 |
7 |

Welcome to Attack Surface Analyzer (ASA)!

8 |

ASA is an open source security tool that analyzes the attack surface of a target system and reports on potential security vulnerabilities introduced during the installation of software or system misconfiguration.

9 |

Documentation is available on the Github Wiki.

10 |

Learn about writing rules on the Authoring Rules page.

11 |

@version

12 |
13 |
14 |
15 |
16 |
17 |

Guided Mode

18 |

Follow a simple guide to run collectors, monitor changes, and analyze results.

19 |

Try it!

20 |
21 |
22 |

Author

23 |

Write, validate, and import/export rules.

24 |

Try it!

25 |
26 |
27 |

Sandbox

28 |

Create objects and test authored rules against them.

29 |

Try it!

30 |
31 |
32 |
33 | 34 | @code{ 35 | string version = "v" + AsaHelpers.GetVersionString(); 36 | } -------------------------------------------------------------------------------- /Cli/Pages/Monitor.razor: -------------------------------------------------------------------------------- 1 | @page "/monitor" 2 | 3 |

Monitor

4 | 5 |
6 | @switch (pageState) 7 | { 8 | case PageState.Options: 9 |
10 |
11 | 12 | 13 |
14 | 15 | 16 |
17 | 18 |
19 |
20 | 21 | break; 22 | case PageState.Monitoring: 23 | 24 | break; 25 | case PageState.MonitorFlushing: 26 | 27 | break; 28 | case PageState.Finished: 29 |

Monitoring complete.

30 | 31 | break; 32 | case PageState.Error: 33 |

An Error Occured while monitoring.

34 | break; 35 | } 36 |
37 | 38 | @code { 39 | enum PageState 40 | { 41 | Options, 42 | Monitoring, 43 | MonitorFlushing, 44 | Finished, 45 | Error 46 | } 47 | 48 | bool UseTimestamp = true; 49 | string RunIdInput = ""; 50 | 51 | PageState pageState = PageState.Options; 52 | 53 | System.Threading.Timer timer; 54 | 55 | async void BeginMonitor() 56 | { 57 | appData.RunId = UseTimestamp ? DateTime.Now.ToString() : RunIdInput; 58 | timer = new System.Threading.Timer((_) => InvokeAsync(() => StateHasChanged()), null, 0, 100); 59 | appData.MonitorOptions.RunId = appData.MonitorRunId; 60 | 61 | pageState = PageState.Monitoring; 62 | this.StateHasChanged(); 63 | 64 | if (await Task.Factory.StartNew(() => AttackSurfaceAnalyzerClient.RunGuiMonitorCommand(appData.MonitorOptions)) != Microsoft.CST.AttackSurfaceAnalyzer.Types.ASA_ERROR.NONE) 65 | { 66 | pageState = PageState.Error; 67 | } 68 | 69 | this.StateHasChanged(); 70 | } 71 | 72 | void FinishMonitor() 73 | { 74 | pageState = PageState.MonitorFlushing; 75 | this.StateHasChanged(); 76 | AttackSurfaceAnalyzerClient.StopMonitors(); 77 | pageState = PageState.Finished; 78 | this.StateHasChanged(); 79 | } 80 | 81 | void GoToOptions() 82 | { 83 | pageState = PageState.Options; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Cli/Pages/Report.razor: -------------------------------------------------------------------------------- 1 | @page "/report" 2 | 3 |

Report

4 |
5 | @if (Runs.Count > 0) 6 | { 7 |
8 |
9 | 10 | 22 |
23 |
24 | 25 | } 26 | else 27 | { 28 |

No results available.

29 |

Please run comparisons before viewing results.

30 | } 31 |
32 | 33 | @code { 34 | 35 | List<(string firstRunId, string secondRunId, string analysesHash, RUN_STATUS runStatus)> Runs = AttackSurfaceAnalyzerClient.DatabaseManager.GetCompareRuns(); 36 | 37 | private int _runIdInput; 38 | 39 | int RunIdInput 40 | { 41 | get 42 | { 43 | return _runIdInput; 44 | } 45 | set 46 | { 47 | appData.ExportCollectCommandOptions.FirstRunId = Runs[value].firstRunId; 48 | appData.ExportCollectCommandOptions.SecondRunId = Runs[value].secondRunId; 49 | _runIdInput = value; 50 | this.StateHasChanged(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Cli/Pages/Scan.razor: -------------------------------------------------------------------------------- 1 | @page "/scan" 2 | 3 |

Scan

4 |
5 | @switch (pageState) 6 | { 7 | case PageState.Options: 8 |
9 |
10 | 11 | 12 |
13 | 14 | 15 |
16 | 17 |
18 |
19 | 20 | break; 21 | case PageState.Scanning: 22 | 23 | break; 24 | case PageState.Finished: 25 |

Scanning complete.

26 | 27 | break; 28 | case PageState.Error: 29 |

An Error Occured while collecting.

30 | break; 31 | } 32 |
33 | 34 | @code { 35 | enum PageState 36 | { 37 | Options, 38 | Scanning, 39 | Finished, 40 | Error 41 | } 42 | bool UseTimestamp = true; 43 | string RunIdInput = ""; 44 | 45 | PageState pageState = PageState.Options; 46 | 47 | System.Threading.Timer timer; 48 | 49 | async void BeginScan() 50 | { 51 | appData.RunId = UseTimestamp ? DateTime.Now.ToString() : RunIdInput; 52 | timer = new System.Threading.Timer((_) => InvokeAsync(() => StateHasChanged()), null, 0, 100); 53 | appData.CollectOptions.RunId = appData.FirstRunId; 54 | pageState = PageState.Scanning; 55 | this.StateHasChanged(); 56 | if (await Task.Factory.StartNew(() => AttackSurfaceAnalyzerClient.RunCollectCommand(appData.CollectOptions)) == Microsoft.CST.AttackSurfaceAnalyzer.Types.ASA_ERROR.NONE) 57 | { 58 | pageState = PageState.Finished; 59 | } 60 | else 61 | { 62 | pageState = PageState.Error; 63 | } 64 | AttackSurfaceAnalyzerClient.ClearCollectors(); 65 | } 66 | 67 | void GoToOptions() 68 | { 69 | pageState = PageState.Options; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Cli/Pages/_Host.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | @{ 5 | Layout = null; 6 | } 7 | 8 | 9 | 10 | 11 | 12 | 13 | Attack Surface Analyzer 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | An error has occurred. This application may no longer respond until reloaded. 28 | 29 | 30 | An unhandled exception has occurred. See browser dev tools for details. 31 | 32 | Reload 33 | 🗙 34 |
35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Cli/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:50108", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "Project", 13 | "commandLineArgs": "gui --nolaunch", 14 | "launchBrowser": true, 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "Blazor": { 20 | "commandName": "IISExpress", 21 | "commandLineArgs": "gui --nolaunch", 22 | "launchBrowser": true, 23 | "applicationUrl": "http://localhost:5000", 24 | "environmentVariables": { 25 | "ASPNETCORE_ENVIRONMENT": "Development" 26 | } 27 | }, 28 | "Microsoft.CST.AttackSurfaceAnalyzer.Cli": { 29 | "commandName": "Project", 30 | "commandLineArgs": "gui", 31 | "launchBrowser": true, 32 | "applicationUrl": "http://localhost:46312", 33 | "environmentVariables": { 34 | "ASPNETCORE_ENVIRONMENT": "Development" 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Cli/SandboxState.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli 4 | { 5 | public class SandboxState 6 | { 7 | /// 8 | /// A Dictionary of FullName of object (with namespace) 9 | /// to list of that objects of that Type 10 | /// 11 | public Dictionary> Objects { get; set; } = new Dictionary>(); 12 | 13 | public SandboxState() 14 | { 15 | } 16 | 17 | public SandboxState(Dictionary> objects) 18 | { 19 | Objects = objects; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Cli/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | @using Microsoft.CST.AttackSurfaceAnalyzer.Utils 3 | 4 | 5 |
6 |
7 | @Body 8 |
9 |
-------------------------------------------------------------------------------- /Cli/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Components; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using Microsoft.Extensions.Hosting; 11 | using Tewr.Blazor.FileReader; 12 | 13 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Cli 14 | { 15 | public class Startup 16 | { 17 | public Startup(IConfiguration configuration) 18 | { 19 | Configuration = configuration; 20 | } 21 | 22 | public IConfiguration Configuration { get; } 23 | 24 | // This method gets called by the runtime. Use this method to add services to the container. 25 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 26 | public void ConfigureServices(IServiceCollection services) 27 | { 28 | services.AddRazorPages(); 29 | services.AddServerSideBlazor(); 30 | services.AddSingleton(); 31 | services.AddFileReaderService(); 32 | } 33 | 34 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 35 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 36 | { 37 | if (env.IsDevelopment()) 38 | { 39 | app.UseDeveloperExceptionPage(); 40 | } 41 | else 42 | { 43 | app.UseExceptionHandler("/Error"); 44 | } 45 | 46 | app.UseStaticFiles(); 47 | 48 | app.UseRouting(); 49 | 50 | app.UseEndpoints(endpoints => 51 | { 52 | endpoints.MapBlazorHub(); 53 | endpoints.MapFallbackToPage("/_Host"); 54 | }); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Cli/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Authorization 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.JSInterop 8 | @using Microsoft.CST.AttackSurfaceAnalyzer.Cli.Shared 9 | @using Microsoft.CST.AttackSurfaceAnalyzer.Types 10 | @using Microsoft.CST.OAT.Blazor.Components 11 | @using Microsoft.CST.OAT.Blazor 12 | @using Microsoft.CST.AttackSurfaceAnalyzer.Cli.Components 13 | @using Microsoft.CST.AttackSurfaceAnalyzer.Cli.Components.States 14 | @using System.Threading; 15 | @using Microsoft.CST.AttackSurfaceAnalyzer.Objects 16 | @using Microsoft.CST.AttackSurfaceAnalyzer.Collectors 17 | @inject Microsoft.CST.AttackSurfaceAnalyzer.Cli.AppData appData -------------------------------------------------------------------------------- /Cli/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Cli/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /Cli/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /Cli/wwwroot/css/open-iconic/README.md: -------------------------------------------------------------------------------- 1 | [Open Iconic v1.1.1](http://useiconic.com/open) 2 | =========== 3 | 4 | ### Open Iconic is the open source sibling of [Iconic](http://useiconic.com). It is a hyper-legible collection of 223 icons with a tiny footprint—ready to use with Bootstrap and Foundation. [View the collection](http://useiconic.com/open#icons) 5 | 6 | 7 | 8 | ## What's in Open Iconic? 9 | 10 | * 223 icons designed to be legible down to 8 pixels 11 | * Super-light SVG files - 61.8 for the entire set 12 | * SVG sprite—the modern replacement for icon fonts 13 | * Webfont (EOT, OTF, SVG, TTF, WOFF), PNG and WebP formats 14 | * Webfont stylesheets (including versions for Bootstrap and Foundation) in CSS, LESS, SCSS and Stylus formats 15 | * PNG and WebP raster images in 8px, 16px, 24px, 32px, 48px and 64px. 16 | 17 | 18 | ## Getting Started 19 | 20 | #### For code samples and everything else you need to get started with Open Iconic, check out our [Icons](http://useiconic.com/open#icons) and [Reference](http://useiconic.com/open#reference) sections. 21 | 22 | ### General Usage 23 | 24 | #### Using Open Iconic's SVGs 25 | 26 | We like SVGs and we think they're the way to display icons on the web. Since Open Iconic are just basic SVGs, we suggest you display them like you would any other image (don't forget the `alt` attribute). 27 | 28 | ``` 29 | icon name 30 | ``` 31 | 32 | #### Using Open Iconic's SVG Sprite 33 | 34 | Open Iconic also comes in a SVG sprite which allows you to display all the icons in the set with a single request. It's like an icon font, without being a hack. 35 | 36 | Adding an icon from an SVG sprite is a little different than what you're used to, but it's still a piece of cake. *Tip: To make your icons easily style able, we suggest adding a general class to the* `` *tag and a unique class name for each different icon in the* `` *tag.* 37 | 38 | ``` 39 | 40 | 41 | 42 | ``` 43 | 44 | Sizing icons only needs basic CSS. All the icons are in a square format, so just set the `` tag with equal width and height dimensions. 45 | 46 | ``` 47 | .icon { 48 | width: 16px; 49 | height: 16px; 50 | } 51 | ``` 52 | 53 | Coloring icons is even easier. All you need to do is set the `fill` rule on the `` tag. 54 | 55 | ``` 56 | .icon-account-login { 57 | fill: #f00; 58 | } 59 | ``` 60 | 61 | To learn more about SVG Sprites, read [Chris Coyier's guide](http://css-tricks.com/svg-sprites-use-better-icon-fonts/). 62 | 63 | #### Using Open Iconic's Icon Font... 64 | 65 | 66 | ##### …with Bootstrap 67 | 68 | You can find our Bootstrap stylesheets in `font/css/open-iconic-bootstrap.{css, less, scss, styl}` 69 | 70 | 71 | ``` 72 | 73 | ``` 74 | 75 | 76 | ``` 77 | 78 | ``` 79 | 80 | ##### …with Foundation 81 | 82 | You can find our Foundation stylesheets in `font/css/open-iconic-foundation.{css, less, scss, styl}` 83 | 84 | ``` 85 | 86 | ``` 87 | 88 | 89 | ``` 90 | 91 | ``` 92 | 93 | ##### …on its own 94 | 95 | You can find our default stylesheets in `font/css/open-iconic.{css, less, scss, styl}` 96 | 97 | ``` 98 | 99 | ``` 100 | 101 | ``` 102 | 103 | ``` 104 | 105 | 106 | ## License 107 | 108 | ### Icons 109 | 110 | All code (including SVG markup) is under the [MIT License](http://opensource.org/licenses/MIT). 111 | 112 | ### Fonts 113 | 114 | All fonts are under the [SIL Licensed](http://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web). 115 | -------------------------------------------------------------------------------- /Cli/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Cli/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /Cli/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Cli/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /Cli/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Cli/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /Cli/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Cli/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /Cli/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Cli/wwwroot/favicon.ico -------------------------------------------------------------------------------- /Cli/wwwroot/images/box-seam-wh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Cli/wwwroot/images/box-seam-wh.png -------------------------------------------------------------------------------- /Cli/wwwroot/images/box-seam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Cli/wwwroot/images/box-seam.png -------------------------------------------------------------------------------- /Cli/wwwroot/images/card-checklist-wh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Cli/wwwroot/images/card-checklist-wh.png -------------------------------------------------------------------------------- /Cli/wwwroot/images/card-checklist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Cli/wwwroot/images/card-checklist.png -------------------------------------------------------------------------------- /Cli/wwwroot/images/github-32-wh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Cli/wwwroot/images/github-32-wh.png -------------------------------------------------------------------------------- /Cli/wwwroot/images/github-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Cli/wwwroot/images/github-32.png -------------------------------------------------------------------------------- /Cli/wwwroot/images/microsoft-sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Cli/wwwroot/images/microsoft-sm.png -------------------------------------------------------------------------------- /Cli/wwwroot/images/microsoft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Cli/wwwroot/images/microsoft.png -------------------------------------------------------------------------------- /Cli/wwwroot/images/pencil-square-wh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Cli/wwwroot/images/pencil-square-wh.png -------------------------------------------------------------------------------- /Cli/wwwroot/images/pencil-square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Cli/wwwroot/images/pencil-square.png -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 3.4.231 6 | all 7 | 8 | 9 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) Microsoft Corporation. All rights reserved. 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Lib/Collectors/BaseCollector.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Objects; 3 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 4 | using Microsoft.CST.AttackSurfaceAnalyzer.Utils; 5 | using Serilog; 6 | using System; 7 | using System.Collections.Concurrent; 8 | using System.Collections.Generic; 9 | using System.Diagnostics; 10 | using System.Globalization; 11 | using System.Threading; 12 | 13 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Collectors 14 | { 15 | /// 16 | /// Base class for all collectors. 17 | /// 18 | public abstract class BaseCollector : IPlatformRunnable 19 | { 20 | public ConcurrentStack Results { get; } = new ConcurrentStack(); 21 | 22 | public RUN_STATUS RunStatus 23 | { 24 | get; private set; 25 | } 26 | 27 | public abstract bool CanRunOnPlatform(); 28 | 29 | public void Start() 30 | { 31 | RunStatus = RUN_STATUS.RUNNING; 32 | watch = Stopwatch.StartNew(); 33 | Log.Information(Strings.Get("Starting"), GetType().Name); 34 | } 35 | 36 | public void Stop() 37 | { 38 | RunStatus = RUN_STATUS.COMPLETED; 39 | watch?.Stop(); 40 | TimeSpan t = TimeSpan.FromMilliseconds(watch?.ElapsedMilliseconds ?? 0); 41 | string answer = string.Format(CultureInfo.InvariantCulture, "{0:D2}h:{1:D2}m:{2:D2}s:{3:D3}ms", 42 | t.Hours, 43 | t.Minutes, 44 | t.Seconds, 45 | t.Milliseconds); 46 | Log.Information(Strings.Get("Completed"), GetType().Name, answer); 47 | } 48 | 49 | public void TryExecute(CancellationToken? token = null) 50 | { 51 | var cancellationToken = token is CancellationToken cancelToken ? cancelToken : GetPlaceholderToken(); 52 | Start(); 53 | if (!CanRunOnPlatform()) 54 | { 55 | Log.Warning(Strings.Get("Err_PlatIncompat"), GetType().ToString()); 56 | } 57 | else 58 | { 59 | try 60 | { 61 | ExecuteInternal(cancellationToken); 62 | } 63 | catch (Exception e) 64 | { 65 | Log.Debug("Failed to run {0} ({1}:{2})", GetType(), e.GetType(), e.Message); 66 | } 67 | } 68 | Stop(); 69 | } 70 | 71 | internal CollectorOptions opts = new CollectorOptions(); 72 | 73 | internal abstract void ExecuteInternal(CancellationToken cancellationToken); 74 | 75 | internal void HandleChange(CollectObject collectObject) 76 | { 77 | if (changeHandler != null) 78 | { 79 | changeHandler(collectObject); 80 | } 81 | else 82 | { 83 | Results.Push(collectObject); 84 | } 85 | } 86 | 87 | protected BaseCollector(CollectorOptions? opts, Action? changeHandler) 88 | { 89 | this.opts = opts ?? new CollectorOptions(); 90 | this.changeHandler = changeHandler; 91 | } 92 | 93 | private readonly Action? changeHandler; 94 | 95 | private Stopwatch? watch; 96 | 97 | private static CancellationToken GetPlaceholderToken() 98 | { 99 | using var source = new CancellationTokenSource(); 100 | return source.Token; 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /Lib/Collectors/BaseMonitor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | 4 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Collectors 5 | { 6 | public abstract class BaseMonitor : IPlatformRunnable 7 | { 8 | #nullable disable 9 | 10 | public string RunId { get; set; } 11 | #nullable restore 12 | 13 | public RUN_STATUS RunStatus { get; set; } 14 | 15 | public abstract bool CanRunOnPlatform(); 16 | 17 | public abstract void StartRun(); 18 | 19 | public abstract void StopRun(); 20 | } 21 | } -------------------------------------------------------------------------------- /Lib/Collectors/CryptographicKeyCollector.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Objects; 3 | using System; 4 | using System.Runtime.InteropServices; 5 | using System.Threading; 6 | 7 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Collectors 8 | { 9 | public class CryptographicKeyCollector : BaseCollector 10 | { 11 | public CryptographicKeyCollector(CollectorOptions? opts = null, Action? changeHandler = null) : base(opts, changeHandler) 12 | { 13 | } 14 | 15 | public override bool CanRunOnPlatform() 16 | { 17 | return RuntimeInformation.IsOSPlatform(OSPlatform.Windows); 18 | } 19 | 20 | internal override void ExecuteInternal(CancellationToken cancellationToken) 21 | { 22 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 23 | { 24 | // Foreach (var ksp in ksps){ enumeratekeys(ksp) } 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Lib/Collectors/IPlatformRunnable.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Collectors 3 | { 4 | public interface IPlatformRunnable 5 | { 6 | bool CanRunOnPlatform(); 7 | } 8 | } -------------------------------------------------------------------------------- /Lib/Collectors/ProcessCollector.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Objects; 3 | using System; 4 | using System.Diagnostics; 5 | using System.Runtime.InteropServices; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Collectors 10 | { 11 | /// 12 | /// Collects metadata about processes on the local computer. 13 | /// 14 | public class ProcessCollector : BaseCollector 15 | { 16 | /// 17 | /// 18 | /// 19 | /// 20 | public ProcessCollector(CollectorOptions? opts = null, Action? changeHandler = null) : base(opts, changeHandler) { } 21 | 22 | public override bool CanRunOnPlatform() 23 | { 24 | return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX); 25 | } 26 | 27 | /// 28 | /// Execute the Process collector. 29 | /// 30 | internal override void ExecuteInternal(CancellationToken cancellationToken) 31 | { 32 | Parallel.ForEach(Process.GetProcesses(), new ParallelOptions() { CancellationToken = cancellationToken }, process => 33 | { 34 | if (ProcessObject.FromProcess(process) is ProcessObject po) 35 | HandleChange(po); 36 | }); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Lib/Collectors/RegistryMonitor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Utils; 3 | using Serilog; 4 | using System; 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Runtime.InteropServices; 8 | 9 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Collectors 10 | { 11 | public class RegistryMonitor : BaseMonitor, IDisposable 12 | { 13 | public RegistryMonitor() 14 | { 15 | } 16 | 17 | public override bool CanRunOnPlatform() 18 | { 19 | return RuntimeInformation.IsOSPlatform(OSPlatform.Windows); 20 | } 21 | 22 | public void Dispose() 23 | { 24 | Dispose(true); 25 | GC.SuppressFinalize(this); 26 | } 27 | 28 | public void MyOnEntryWritten(object source, EntryWrittenEventArgs e) 29 | { 30 | if (e != null) 31 | { 32 | Log.Information(e.Entry.Source); 33 | } 34 | } 35 | 36 | public override void StartRun() 37 | { 38 | // backup the current auditpolicy 39 | ExternalCommandRunner.RunExternalCommand("auditpol", $"/backup /file:{tmpFileName}"); 40 | 41 | // start listening to the event log 42 | log.EntryWritten += new EntryWrittenEventHandler(MyOnEntryWritten); 43 | log.EnableRaisingEvents = true; 44 | 45 | // Enable auditing for registry events GUID for Registry subcategory of audit policy https://msdn.microsoft.com/en-us/library/dd973928.aspx 46 | ExternalCommandRunner.RunExternalCommand("auditpol", "/set /subcategory:{0CCE921E-69AE-11D9-BED3-505054503030} /success:enable /failure:enable"); 47 | } 48 | 49 | public override void StopRun() 50 | { 51 | // restore the old auditpolicy 52 | ExternalCommandRunner.RunExternalCommand("auditpol", $"/restore /file:{tmpFileName}"); 53 | 54 | //delete temporary file 55 | ExternalCommandRunner.RunExternalCommand("del", tmpFileName); 56 | 57 | log.EnableRaisingEvents = false; 58 | } 59 | 60 | protected virtual void Dispose(bool disposing) 61 | { 62 | if (disposing) 63 | { 64 | log.Dispose(); 65 | } 66 | } 67 | 68 | // I believe auditpol results will go into the system log 69 | private readonly EventLog log = new EventLog("System"); 70 | 71 | private readonly string tmpFileName = Path.GetTempFileName(); 72 | } 73 | } -------------------------------------------------------------------------------- /Lib/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | 3 | // This file is used by Code Analysis to maintain SuppressMessage attributes that are applied to this project. 4 | // Project-level suppressions either have no target or are given a specific target and scoped to a namespace, 5 | // type, member, etc. 6 | 7 | using System.Diagnostics.CodeAnalysis; 8 | 9 | [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Preferred format.", Scope = "namespace", Target = "AttackSurfaceAnalyzer")] 10 | [assembly: SuppressMessage("Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "", Scope = "member", Target = "~M:AttackSurfaceAnalyzer.Collectors.TpmCollector.GetLoadedEntities(Tpm2Lib.Tpm2,Tpm2Lib.Ht)~Tpm2Lib.TpmHandle[]")] -------------------------------------------------------------------------------- /Lib/Objects/AsaRule.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 2 | using Microsoft.CST.OAT; 3 | using System.Collections.Generic; 4 | 5 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 6 | { 7 | public class AsaRule : Rule 8 | { 9 | public AsaRule(string Name) : base(Name) 10 | { 11 | } 12 | 13 | public List ChangeTypes { get; set; } = new List() { CHANGE_TYPE.CREATED, CHANGE_TYPE.DELETED, CHANGE_TYPE.MODIFIED }; 14 | 15 | public ANALYSIS_RESULT_TYPE Flag 16 | { 17 | get 18 | { 19 | return _flag; 20 | } 21 | set 22 | { 23 | _flag = value; 24 | Severity = (int)value; 25 | } 26 | } 27 | 28 | public List Platforms { get; set; } = new List() { PLATFORM.LINUX, PLATFORM.MACOS, PLATFORM.WINDOWS }; 29 | 30 | public RESULT_TYPE ResultType 31 | { 32 | get 33 | { 34 | return _resultType; 35 | } 36 | set 37 | { 38 | _resultType = value; 39 | Target = ResultTypeToTargetName(value); 40 | } 41 | } 42 | 43 | private ANALYSIS_RESULT_TYPE _flag; 44 | 45 | private RESULT_TYPE _resultType; 46 | 47 | private static string? ResultTypeToTargetName(RESULT_TYPE value) 48 | { 49 | switch (value) 50 | { 51 | case RESULT_TYPE.CERTIFICATE: 52 | return typeof(CertificateObject).Name; 53 | 54 | case RESULT_TYPE.COM: 55 | return typeof(ComObject).Name; 56 | 57 | case RESULT_TYPE.DRIVER: 58 | return typeof(DriverObject).Name; 59 | 60 | case RESULT_TYPE.FILE: 61 | return typeof(FileSystemObject).Name; 62 | 63 | case RESULT_TYPE.FILEMONITOR: 64 | return typeof(FileMonitorObject).Name; 65 | 66 | case RESULT_TYPE.FIREWALL: 67 | return typeof(FirewallObject).Name; 68 | 69 | case RESULT_TYPE.GROUP: 70 | return typeof(GroupAccountObject).Name; 71 | 72 | case RESULT_TYPE.KEY: 73 | return typeof(CryptographicKeyObject).Name; 74 | 75 | case RESULT_TYPE.LOG: 76 | return typeof(EventLogObject).Name; 77 | 78 | case RESULT_TYPE.PORT: 79 | return typeof(OpenPortObject).Name; 80 | 81 | case RESULT_TYPE.PROCESS: 82 | return typeof(ProcessObject).Name; 83 | 84 | case RESULT_TYPE.REGISTRY: 85 | return typeof(RegistryObject).Name; 86 | 87 | case RESULT_TYPE.SERVICE: 88 | return typeof(ServiceObject).Name; 89 | 90 | case RESULT_TYPE.TPM: 91 | return typeof(TpmObject).Name; 92 | 93 | case RESULT_TYPE.USER: 94 | return typeof(UserAccountObject).Name; 95 | 96 | case RESULT_TYPE.WIFI: 97 | return typeof(WifiObject).Name; 98 | 99 | default: 100 | return null; 101 | } 102 | } 103 | } 104 | } -------------------------------------------------------------------------------- /Lib/Objects/AsaRun.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 7 | { 8 | public class AsaRun 9 | { 10 | public AsaRun(string RunId, DateTime Timestamp, string Version, PLATFORM Platform, List ResultTypes, RUN_TYPE Type) 11 | { 12 | this.RunId = RunId; 13 | this.Timestamp = Timestamp; 14 | this.Version = Version; 15 | this.Platform = Platform; 16 | this.ResultTypes = ResultTypes; 17 | this.Type = Type; 18 | } 19 | 20 | public PLATFORM Platform { get; set; } 21 | public List ResultTypes { get; set; } 22 | public string RunId { get; set; } 23 | public DateTime Timestamp { get; set; } 24 | public RUN_TYPE Type { get; set; } 25 | public string Version { get; set; } 26 | } 27 | } -------------------------------------------------------------------------------- /Lib/Objects/CertificateObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | 4 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 5 | { 6 | public class CertificateObject : CollectObject 7 | { 8 | public CertificateObject(string StoreLocation, string StoreName, SerializableCertificate Certificate) 9 | { 10 | this.StoreLocation = StoreLocation; 11 | this.StoreName = StoreName; 12 | this.Certificate = Certificate; 13 | ResultType = RESULT_TYPE.CERTIFICATE; 14 | } 15 | 16 | /// 17 | /// A serializable representation of the Certificate. 18 | /// 19 | public SerializableCertificate Certificate { get; set; } 20 | 21 | /// 22 | /// See Certificate.CertHashString 23 | /// 24 | public string CertificateHashString { get { return Certificate.CertHashString; } } 25 | 26 | /// 27 | /// The identity of a CertificateObject is based on the StoreLocation, StoreName and 28 | /// CertificateHashString of the CertificateObject 29 | /// 30 | public override string Identity 31 | { 32 | get 33 | { 34 | return $"{StoreLocation}{StoreName}{CertificateHashString}"; 35 | } 36 | } 37 | 38 | /// 39 | /// The exported Pkcs7 of the certificate. Not guaranteed to be non-null. 40 | /// 41 | public string? Pkcs7 { get { return Certificate.Pkcs7; } } 42 | 43 | /// 44 | /// The Store Location or Location on Disk where the Certificate was found 45 | /// 46 | public string StoreLocation { get; set; } 47 | 48 | /// 49 | /// The Name of an X509 Store or another source (like the filesystem) 50 | /// 51 | public string StoreName { get; set; } 52 | 53 | /// 54 | /// See Certificate.Subject 55 | /// 56 | public string Subject { get { return Certificate.Subject; } } 57 | } 58 | } -------------------------------------------------------------------------------- /Lib/Objects/CollectObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | using Microsoft.CST.AttackSurfaceAnalyzer.Utils; 4 | using Newtonsoft.Json; 5 | using System.Globalization; 6 | 7 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 8 | { 9 | /// 10 | /// Abstract parent class that all Collected data inherits from. 11 | /// 12 | public abstract class CollectObject 13 | { 14 | public abstract string Identity { get; } 15 | public RESULT_TYPE ResultType { get; set; } 16 | 17 | [SkipCompare] 18 | [JsonIgnore] 19 | public string RowKey 20 | { 21 | get 22 | { 23 | return Serialized.GetHashCode().ToString(CultureInfo.InvariantCulture); 24 | } 25 | } 26 | 27 | [SkipCompare] 28 | [JsonIgnore] 29 | public string Serialized 30 | { 31 | get 32 | { 33 | if (_serialized == null) 34 | { 35 | _serialized = JsonUtils.Dehydrate(this); 36 | } 37 | 38 | return _serialized; 39 | } 40 | } 41 | 42 | private string? _serialized = null; 43 | } 44 | } -------------------------------------------------------------------------------- /Lib/Objects/ComObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | 4 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 5 | { 6 | public class ComObject : CollectObject 7 | { 8 | /// 9 | /// This is the correct constructor to use to create a ComObject. 10 | /// 11 | /// The RegistryObject this ComObject is based on. 12 | public ComObject(RegistryObject Key) : base() 13 | { 14 | this.Key = Key; 15 | ResultType = RESULT_TYPE.COM; 16 | } 17 | 18 | /// 19 | /// A COM Object's identity is the same as the Registry Key which specifies it 20 | /// 21 | public override string Identity 22 | { 23 | get 24 | { 25 | return Key.Identity; 26 | } 27 | } 28 | 29 | /// 30 | /// The Registry Key which specifies this COM object 31 | /// 32 | public RegistryObject Key { get; set; } 33 | 34 | /// 35 | /// The associated binary found (if any) in the x64 view of the registry 36 | /// 37 | public FileSystemObject? x64_Binary { get; set; } 38 | 39 | /// 40 | /// The associated binary found (if any) in the x86 view of the registry 41 | /// 42 | public FileSystemObject? x86_Binary { get; set; } 43 | } 44 | } -------------------------------------------------------------------------------- /Lib/Objects/CompareResult.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | using Microsoft.CST.OAT; 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 7 | { 8 | public class CompareResult 9 | { 10 | public CompareResult() 11 | { 12 | } 13 | 14 | public ANALYSIS_RESULT_TYPE Analysis { get; set; } 15 | 16 | public CollectObject? Base { get; set; } 17 | 18 | public string? BaseRunId { get; set; } 19 | 20 | public CHANGE_TYPE ChangeType 21 | { 22 | get 23 | { 24 | if (Base != null) 25 | { 26 | if (Compare != null) 27 | { 28 | return CHANGE_TYPE.MODIFIED; 29 | } 30 | else 31 | { 32 | return CHANGE_TYPE.DELETED; 33 | } 34 | } 35 | else 36 | { 37 | if (Compare != null) 38 | { 39 | return CHANGE_TYPE.CREATED; 40 | } 41 | else 42 | { 43 | return CHANGE_TYPE.INVALID; 44 | } 45 | } 46 | } 47 | } 48 | 49 | public CollectObject? Compare { get; set; } 50 | 51 | public string? CompareRunId { get; set; } 52 | 53 | public List Diffs { get; set; } = new List(); 54 | 55 | public string Identity 56 | { 57 | get 58 | { 59 | if (Base is CollectObject colObj) 60 | { 61 | return colObj.Identity; 62 | } 63 | else if (Compare is CollectObject colObj2) 64 | { 65 | return colObj2.Identity; 66 | } 67 | else 68 | { 69 | return string.Empty; 70 | } 71 | } 72 | } 73 | 74 | public RESULT_TYPE ResultType 75 | { 76 | get 77 | { 78 | if (Base is CollectObject colObj) 79 | { 80 | return colObj.ResultType; 81 | } 82 | else if (Compare is CollectObject colObj2) 83 | { 84 | return colObj2.ResultType; 85 | } 86 | else 87 | { 88 | return RESULT_TYPE.UNKNOWN; 89 | } 90 | } 91 | } 92 | 93 | public List Rules { get; set; } = new List(); 94 | public string AnalysesHash { get; set; } = string.Empty; 95 | 96 | public bool ShouldSerializeDiffs() 97 | { 98 | return Diffs?.Count > 0; 99 | } 100 | 101 | public bool ShouldSerializeRules() 102 | { 103 | return Rules?.Count > 0; 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /Lib/Objects/CryptographicKeyObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | 3 | using Newtonsoft.Json; 4 | using System; 5 | using System.Security.Cryptography; 6 | using Tpm2Lib; 7 | 8 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 9 | { 10 | public class CryptographicKeyObject : CollectObject 11 | { 12 | public CryptographicKeyObject(string Source, TpmAlgId tpmAlgId) 13 | { 14 | this.ResultType = Types.RESULT_TYPE.KEY; 15 | this.Source = Source; 16 | this.tpmAlgId = tpmAlgId; 17 | } 18 | 19 | public override string Identity 20 | { 21 | get 22 | { 23 | return Source; 24 | } 25 | } 26 | 27 | public RsaKeyDetails? RsaDetails { get; set; } 28 | public string Source { get; set; } 29 | 30 | public TpmAlgId tpmAlgId { get; set; } = TpmAlgId.Null; 31 | } 32 | 33 | public class KeyDetailObject 34 | { 35 | } 36 | 37 | public class RsaKeyDetails : KeyDetailObject 38 | { 39 | public RsaKeyDetails(byte[] modulus, byte[] d, byte[]? p = null, byte[]? q = null) 40 | { 41 | var parameters = new RSAParameters() 42 | { 43 | D = d, 44 | Modulus = modulus 45 | }; 46 | 47 | if (p != null && q != null) 48 | { 49 | parameters.P = p; 50 | parameters.Q = q; 51 | ContainsPrivate = true; 52 | } 53 | 54 | //parameters.InverseQ; 55 | //parameters.Exponent; 56 | //parameters.DP; 57 | //parameters.DQ; 58 | 59 | rsa = RSA.Create(parameters); 60 | } 61 | 62 | [JsonConstructor] 63 | public RsaKeyDetails(string? PublicString = null, string? FullString = null) 64 | { 65 | rsa = RSA.Create(); 66 | if (FullString != null) 67 | { 68 | rsa.ImportRSAPrivateKey(Convert.FromBase64String(FullString), out _); 69 | } 70 | else if (PublicString != null) 71 | { 72 | rsa.ImportRSAPublicKey(Convert.FromBase64String(PublicString), out _); 73 | } 74 | } 75 | 76 | public string? FullString 77 | { 78 | get 79 | { 80 | if (ContainsPrivate) 81 | { 82 | return Convert.ToBase64String(rsa.ExportRSAPrivateKey()); 83 | } 84 | return null; 85 | } 86 | } 87 | 88 | public string PublicString 89 | { 90 | get 91 | { 92 | return Convert.ToBase64String(rsa.ExportRSAPublicKey()); 93 | } 94 | } 95 | 96 | public bool ShouldSerializeFullString() 97 | { 98 | return ContainsPrivate; 99 | } 100 | 101 | public bool ShouldSerializePublicString() 102 | { 103 | return !ContainsPrivate; 104 | } 105 | 106 | private bool ContainsPrivate = false; 107 | private RSA rsa; 108 | } 109 | } -------------------------------------------------------------------------------- /Lib/Objects/DataRun.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using System.Collections.Generic; 3 | 4 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 5 | { 6 | public class DataRunListModel 7 | { 8 | public IEnumerable? MonitorRuns { get; set; } 9 | public IEnumerable? Runs { get; set; } 10 | public string? SelectedBaseRunId { get; set; } 11 | public string? SelectedCompareRunId { get; set; } 12 | public string? SelectedMonitorRunId { get; set; } 13 | } 14 | 15 | public class DataRunModel 16 | { 17 | public DataRunModel(string KeyIn, string TextIn) 18 | { 19 | Key = KeyIn; 20 | Text = TextIn; 21 | } 22 | 23 | public string Key { get; } 24 | public string Text { get; } 25 | } 26 | } -------------------------------------------------------------------------------- /Lib/Objects/Diff.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 3 | { 4 | public class Diff 5 | { 6 | public Diff(string FieldIn, object? BeforeIn = null, object? AfterIn = null) 7 | { 8 | Field = FieldIn; 9 | Before = BeforeIn; 10 | After = AfterIn; 11 | } 12 | 13 | public object? After { get; } 14 | public object? Before { get; } 15 | public string Field { get; } 16 | } 17 | } -------------------------------------------------------------------------------- /Lib/Objects/DriverObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 7 | { 8 | public class DriverObject : CollectObject 9 | { 10 | public DriverObject(string Name) 11 | { 12 | this.Name = Name; 13 | ResultType = RESULT_TYPE.DRIVER; 14 | } 15 | 16 | public bool? AcceptPause { get; set; } 17 | public bool? AcceptStop { get; set; } 18 | public string? Address { get; set; } 19 | public string? Architecture { get; set; } 20 | public long? BSS { get; set; } 21 | public long? Code { get; set; } 22 | public string? Description { get; set; } 23 | public string? DisplayName { get; set; } 24 | public string? DriverType { get; set; } 25 | 26 | public override string Identity 27 | { 28 | get 29 | { 30 | return Name; 31 | } 32 | } 33 | 34 | public int? Index { get; set; } 35 | public long? Init { get; set; } 36 | public DateTime? LinkDate { get; set; } 37 | public List? LinkedAgainst { get; set; } 38 | public string Name { get; set; } 39 | public long? PagedPool { get; set; } 40 | public string? Path { get; set; } 41 | public Dictionary? Properties { get; set; } 42 | public int? Refs { get; set; } 43 | public Signature? Signature { get; set; } 44 | public string? Size { get; set; } 45 | 46 | public string? StartMode { get; set; } 47 | public string? State { get; set; } 48 | public string? Status { get; set; } 49 | public string? UUID { get; set; } 50 | public string? Version { get; set; } 51 | public string? Wired { get; set; } 52 | } 53 | } -------------------------------------------------------------------------------- /Lib/Objects/EventLogObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 6 | { 7 | public class EventLogObject : CollectObject 8 | { 9 | public EventLogObject(string Event) 10 | { 11 | this.Event = Event; 12 | ResultType = Types.RESULT_TYPE.LOG; 13 | Data = new List(); 14 | } 15 | 16 | /// 17 | /// Additional associated data 18 | /// 19 | public List? Data { get; set; } 20 | 21 | /// 22 | /// The raw event text 23 | /// 24 | public string Event { get; set; } 25 | 26 | /// 27 | /// The raw event text 28 | /// 29 | public override string Identity 30 | { 31 | get 32 | { 33 | return Event; 34 | } 35 | } 36 | 37 | /// 38 | /// The severity level of the event message (availability platform dependent) 39 | /// 40 | public string? Level { get; set; } 41 | 42 | /// 43 | /// The process that the event log is from. 44 | /// 45 | public string? Process { get; set; } 46 | 47 | /// 48 | /// The Event Log source 49 | /// 50 | public string? Source { get; set; } 51 | 52 | /// 53 | /// A summary description of the event message (availability platform dependent) 54 | /// 55 | public string? Summary { get; set; } 56 | 57 | /// 58 | /// The recorded Timestamp in the log file 59 | /// 60 | public DateTime? Timestamp { get; set; } 61 | } 62 | } -------------------------------------------------------------------------------- /Lib/Objects/FileMonitorEvent.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | 4 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 5 | { 6 | public class FileMonitorEvent 7 | { 8 | public FileMonitorEvent(string PathIn) 9 | { 10 | Path = PathIn; 11 | } 12 | 13 | public CHANGE_TYPE ChangeType { get; set; } 14 | public string? Name { get; set; } 15 | public string? OldName { get; set; } 16 | public string? OldPath { get; set; } 17 | public string Path { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /Lib/Objects/FileMonitorObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | using System.IO; 4 | 5 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 6 | { 7 | public class FileMonitorObject : MonitorObject 8 | { 9 | public FileMonitorObject(string PathIn) 10 | { 11 | Path = PathIn; 12 | ResultType = RESULT_TYPE.FILEMONITOR; 13 | } 14 | 15 | public string? ExtendedResults { get; set; } 16 | public FileSystemObject? FileSystemObject { get; set; } 17 | 18 | public override string Identity 19 | { 20 | get 21 | { 22 | return Path; 23 | } 24 | } 25 | 26 | public string? Name { get; set; } 27 | public NotifyFilters? NotifyFilters { get; set; } 28 | public string? OldName { get; set; } 29 | public string? OldPath { get; set; } 30 | public string Path { get; set; } 31 | public string? Timestamp { get; set; } 32 | } 33 | } -------------------------------------------------------------------------------- /Lib/Objects/FileSystemMonitorResult.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using System.IO; 3 | 4 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 5 | { 6 | public class FileSystemMonitorResult 7 | { 8 | public FileSystemMonitorResult(FileSystemEventArgs evtIn) 9 | { 10 | evt = evtIn; 11 | } 12 | 13 | public FileSystemEventArgs evt { get; set; } 14 | public NotifyFilters filter { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /Lib/Objects/FirewallObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | using System.Collections.Generic; 4 | using WindowsFirewallHelper; 5 | 6 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 7 | { 8 | public class FirewallObject : CollectObject 9 | { 10 | public FirewallObject(string Name) 11 | { 12 | ResultType = RESULT_TYPE.FIREWALL; 13 | this.Name = Name; 14 | } 15 | 16 | /// 17 | /// Gets or sets the action that the rules defines 18 | /// 19 | public FirewallAction? Action { get; set; } 20 | 21 | /// 22 | /// Gets or sets the name of the application that this rule is about 23 | /// 24 | public string? ApplicationName { get; set; } 25 | 26 | /// 27 | /// Gets or sets the data direction that the rule applies to 28 | /// 29 | public FirewallDirection? Direction { get; set; } 30 | 31 | /// 32 | /// Gets or sets the resolved name of the rule 33 | /// 34 | public string? FriendlyName { get; set; } 35 | 36 | /// 37 | /// $"{FriendlyName} - {Direction} - {Protocol} - {ApplicationName} - {Profiles} - {Name} 38 | /// 39 | public override string Identity 40 | { 41 | get 42 | { 43 | return $"{FriendlyName} - {Direction} - {Protocol} - {ApplicationName} - {Profiles} - {Name}"; 44 | } 45 | } 46 | 47 | /// 48 | /// Gets or sets a Boolean value indicating if this rule is active 49 | /// 50 | public bool? IsEnable { get; set; } 51 | 52 | /// 53 | /// Gets or sets the local addresses that the rule applies to 54 | /// 55 | public List? LocalAddresses { get; set; } 56 | 57 | /// 58 | /// Gets or sets the local ports that the rule applies to 59 | /// 60 | public List? LocalPorts { get; set; } 61 | 62 | /// 63 | /// Gets or sets the type of local ports that the rules applies to 64 | /// 65 | public FirewallPortType? LocalPortType { get; set; } 66 | 67 | /// 68 | /// Gets or sets the name of the rule in native format w/o auto string resolving 69 | /// 70 | public string Name { get; set; } 71 | 72 | /// 73 | /// Gets the profiles that this rule belongs to 74 | /// 75 | public FirewallProfiles? Profiles { get; set; } 76 | 77 | /// 78 | /// Gets or sets the protocol that the rule applies to 79 | /// 80 | public string? Protocol { get; set; } 81 | 82 | /// 83 | /// Gets or sets the remote addresses that the rule applies to 84 | /// 85 | public List? RemoteAddresses { get; set; } 86 | 87 | /// 88 | /// Gets or sets the remote ports that the rule applies to 89 | /// 90 | public List? RemotePorts { get; set; } 91 | 92 | /// 93 | /// Gets or sets the scope that the rule applies to 94 | /// 95 | public FirewallScope? Scope { get; set; } 96 | 97 | /// 98 | /// Gets or sets the name of the service that this rule is about 99 | /// 100 | public string? ServiceName { get; set; } 101 | } 102 | } -------------------------------------------------------------------------------- /Lib/Objects/MacSignature.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 6 | { 7 | public class MacSignature 8 | { 9 | //Executable=/Applications/1Password 7.app/Contents/MacOS/1Password 7 10 | //Identifier=com.agilebits.onepassword7 11 | //Format=app bundle with Mach-O thin (x86_64) 12 | //CodeDirectory v=20500 size=43910 flags=0x10000(runtime) hashes=1363+5 location=embedded 13 | //VersionPlatform=1 14 | //VersionMin=658438 15 | //VersionSDK=659200 16 | //Hash type=sha256 size=32 17 | //CandidateCDHash sha256=c01b95b3f3138c2f868bfe9b6772463fb4c4d989 18 | //CandidateCDHashFull sha256=c01b95b3f3138c2f868bfe9b6772463fb4c4d98939ea9de67480622558dbff92 19 | //Hash choices=sha256 20 | //CMSDigest=c01b95b3f3138c2f868bfe9b6772463fb4c4d98939ea9de67480622558dbff92 21 | //CMSDigestType=2 22 | //Page size=4096 23 | //CDHash=c01b95b3f3138c2f868bfe9b6772463fb4c4d989 24 | //Signature size=8928 25 | //Authority=Developer ID Application: AgileBits Inc. (2BUA8C4S2C) 26 | //Authority=Developer ID Certification Authority 27 | //Authority=Apple Root CA 28 | //Timestamp=May 5, 2020 at 9:21:50 AM 29 | //Info.plist entries=36 30 | //TeamIdentifier=2BUA8C4S2C 31 | //Runtime Version=10.15.0 32 | //Sealed Resources version=2 rules=13 files=2909 33 | //Internal requirements count=1 size=220 34 | 35 | public List? Authorities { get; set; } 36 | public string? CandidateCDHashFull { get; set; } 37 | public string? CMSDigest { get; set; } 38 | public string? HashChoices { get; set; } 39 | public string? HashType { get; set; } 40 | public string? TeamIdentifier { get; set; } 41 | public DateTime Timestamp { get; set; } 42 | } 43 | } -------------------------------------------------------------------------------- /Lib/Objects/MonitorObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | 4 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 5 | { 6 | /// 7 | /// Abstract parent class that all Collected data inherits from. 8 | /// 9 | public abstract class MonitorObject : CollectObject 10 | { 11 | public CHANGE_TYPE ChangeType { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Lib/Objects/OpenPortObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | using Newtonsoft.Json; 4 | 5 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 6 | { 7 | public class OpenPortObject : CollectObject 8 | { 9 | [JsonConstructor] 10 | public OpenPortObject(int Port, TRANSPORT Type) : this(Port, Type, ADDRESS_FAMILY.Unspecified) { } 11 | 12 | public OpenPortObject(int Port, TRANSPORT Type, ADDRESS_FAMILY AddressFamily) 13 | { 14 | ResultType = RESULT_TYPE.PORT; 15 | this.Port = Port; 16 | this.Type = Type; 17 | this.AddressFamily = AddressFamily; 18 | } 19 | 20 | public string? Address { get; set; } 21 | 22 | /// 23 | /// InterNetwork is IPv4 InterNetworkV6 is IPv6 24 | /// 25 | public ADDRESS_FAMILY AddressFamily { get; set; } 26 | 27 | /// 28 | /// $"{Address}:{Family}:{Type}:{Port}:{ProcessName}" 29 | /// 30 | public override string Identity 31 | { 32 | get 33 | { 34 | return $"{Address}:{AddressFamily}:{Type}:{Port}:{ProcessName}"; 35 | } 36 | } 37 | 38 | /// 39 | /// The port number 40 | /// 41 | public int Port { get; set; } 42 | 43 | public string? ProcessName { get; set; } 44 | 45 | /// 46 | /// TCP or UDP 47 | /// 48 | public TRANSPORT Type { get; set; } 49 | } 50 | } -------------------------------------------------------------------------------- /Lib/Objects/OutputFileMonitorResult.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | 4 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 5 | { 6 | public class OutputFileMonitorResult 7 | { 8 | public OutputFileMonitorResult(string PathIn) 9 | { 10 | Path = PathIn; 11 | } 12 | 13 | public CHANGE_TYPE ChangeType { get; set; } 14 | public string? Name { get; set; } 15 | public string? OldName { get; set; } 16 | public string? OldPath { get; set; } 17 | public string Path { get; set; } 18 | public string? RowKey { get; set; } 19 | public string? Timestamp { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /Lib/Objects/ProcessModuleObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | 5 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 6 | { 7 | public class ProcessModuleObject 8 | { 9 | public ProcessModuleObject(string? FileName, string? ModuleName, SerializableFileVersionInfo? FileVersionInfo) 10 | { 11 | this.FileName = FileName; 12 | this.ModuleName = ModuleName; 13 | this.FileVersionInfo = FileVersionInfo; 14 | } 15 | 16 | public ProcessModuleObject() { } 17 | 18 | public string? FileName { get; set; } 19 | public SerializableFileVersionInfo? FileVersionInfo { get; set; } 20 | public string? ModuleName { get; set; } 21 | 22 | internal static ProcessModuleObject FromProcessModule(ProcessModule mainModule) 23 | { 24 | return new ProcessModuleObject(mainModule.FileName, mainModule.ModuleName, SerializableFileVersionInfo.FromFileVersionInfo(mainModule.FileVersionInfo)); 25 | } 26 | 27 | internal static List FromProcessModuleCollection(ProcessModuleCollection modules) 28 | { 29 | var output = new List(); 30 | foreach (var processModule in modules) 31 | { 32 | if (processModule is ProcessModule pm) 33 | output.Add(FromProcessModule(pm)); 34 | } 35 | return output; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Lib/Objects/ProcessObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Serilog; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | 7 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 8 | { 9 | public class ProcessObject : CollectObject 10 | { 11 | public ProcessObject(int Id, string ProcessName) 12 | { 13 | this.Id = Id; 14 | this.ProcessName = ProcessName; 15 | ResultType = Types.RESULT_TYPE.PROCESS; 16 | } 17 | 18 | public int BasePriority { get; set; } 19 | 20 | public bool HasExited { get; set; } 21 | 22 | public int Id { get; } 23 | 24 | /// 25 | /// The identity of a ProcessObject is just the PID. 26 | /// 27 | public override string Identity 28 | { 29 | get 30 | { 31 | return $"{Id}:{ProcessName}"; 32 | } 33 | } 34 | 35 | public ProcessModuleObject? MainModule { get; set; } 36 | 37 | public List Modules { get; set; } = new List(); 38 | 39 | public ProcessPriorityClass PriorityClass { get; set; } 40 | 41 | public string ProcessName { get; set; } 42 | 43 | public DateTime StartTime { get; set; } 44 | 45 | public static ProcessObject? FromProcess(Process process) 46 | { 47 | if (process == null) return null; 48 | var obj = new ProcessObject(process.Id, process.ProcessName); 49 | 50 | try 51 | { 52 | obj.BasePriority = process.BasePriority; 53 | } 54 | catch (Exception e) 55 | { 56 | Log.Verbose($"Failed to fetch BasePriority from {obj.ProcessName} ({e.GetType()}:{e.Message})"); 57 | } 58 | 59 | try 60 | { 61 | obj.PriorityClass = process.PriorityClass; 62 | } 63 | catch (Exception e) 64 | { 65 | Log.Verbose($"Failed to fetch PriorityClass from {obj.ProcessName} ({e.GetType()}:{e.Message})"); 66 | } 67 | 68 | try 69 | { 70 | obj.StartTime = process.StartTime; 71 | } 72 | catch (Exception e) 73 | { 74 | Log.Verbose($"Failed to fetch StartTime from {obj.ProcessName} ({e.GetType()}:{e.Message})"); 75 | } 76 | 77 | try 78 | { 79 | obj.HasExited = process.HasExited; 80 | } 81 | catch (Exception e) 82 | { 83 | Log.Verbose($"Failed to fetch HasExited from {obj.ProcessName} ({e.GetType()}:{e.Message})"); 84 | } 85 | 86 | try 87 | { 88 | obj.Modules = ProcessModuleObject.FromProcessModuleCollection(process.Modules); 89 | } 90 | catch (Exception e) 91 | { 92 | Log.Verbose($"Failed to fetch Modules from {obj.ProcessName} ({e.GetType()}:{e.Message})"); 93 | } 94 | 95 | try 96 | { 97 | if (process.MainModule is { }) 98 | { 99 | obj.MainModule = ProcessModuleObject.FromProcessModule(process.MainModule); 100 | } 101 | } 102 | catch (Exception e) 103 | { 104 | Log.Verbose($"Failed to fetch MainModule from {obj.ProcessName} ({e.GetType()}:{e.Message})"); 105 | } 106 | 107 | return obj; 108 | } 109 | } 110 | } -------------------------------------------------------------------------------- /Lib/Objects/RegistryObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | using Microsoft.Win32; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Runtime.InteropServices; 7 | 8 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 9 | { 10 | public class RegistryObject : CollectObject 11 | { 12 | public RegistryObject(string Key, RegistryView View) 13 | { 14 | ResultType = RESULT_TYPE.REGISTRY; 15 | this.View = View; 16 | this.Key = Key; 17 | } 18 | 19 | public override string Identity 20 | { 21 | get 22 | { 23 | return $"{View}_{Key}"; 24 | } 25 | } 26 | 27 | /// 28 | /// The Full Path to the Key in the Registry 29 | /// 30 | public string Key { get; set; } 31 | 32 | public Dictionary> Permissions { get; set; } = new Dictionary>(); 33 | public string? PermissionsString { get; set; } 34 | 35 | public int SubkeyCount 36 | { 37 | get { return Subkeys?.Count ?? 0; } 38 | } 39 | 40 | public List? Subkeys { get; set; } 41 | 42 | public int ValueCount 43 | { 44 | get { return Values?.Count ?? 0; } 45 | } 46 | 47 | public Dictionary? Values { get; set; } 48 | public RegistryView View { get; private set; } 49 | 50 | public static Dictionary GetValues(RegistryKey key) 51 | { 52 | if (key is null) 53 | { 54 | throw new ArgumentNullException(nameof(key)); 55 | } 56 | Dictionary values = new Dictionary(); 57 | 58 | if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 59 | { 60 | return values; 61 | } 62 | // Write values under key and commit 63 | foreach (var value in key.GetValueNames()) 64 | { 65 | RegistryValueKind rvk = key.GetValueKind(value); 66 | string str; 67 | 68 | switch (rvk) 69 | { 70 | case RegistryValueKind.MultiString: 71 | str = string.Join(Environment.NewLine, (string[]?)key.GetValue(value) ?? new string[] { }); 72 | break; 73 | 74 | case RegistryValueKind.Binary: 75 | str = Convert.ToBase64String((byte[]?)key.GetValue(value) ?? new byte[] { }); 76 | break; 77 | 78 | case RegistryValueKind.ExpandString: 79 | case RegistryValueKind.String: 80 | str = (string?)key.GetValue(value) ?? string.Empty; 81 | break; 82 | 83 | case RegistryValueKind.DWord: 84 | case RegistryValueKind.QWord: 85 | default: 86 | str = key.GetValue(value)?.ToString() ?? string.Empty; 87 | break; 88 | } 89 | values.Add(value, str); 90 | } 91 | return values; 92 | } 93 | 94 | public void AddSubKeys(string[] subkeysIn) 95 | { 96 | if (Subkeys == null) 97 | { 98 | Subkeys = new List(); 99 | } 100 | Subkeys.AddRange(subkeysIn); 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /Lib/Objects/SerializableCertificate.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Newtonsoft.Json; 3 | using System; 4 | using System.Security.Cryptography.X509Certificates; 5 | 6 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 7 | { 8 | public class SerializableCertificate 9 | { 10 | public SerializableCertificate(X509Certificate2 certificate) 11 | { 12 | Thumbprint = certificate?.Thumbprint ?? throw new ArgumentNullException(nameof(certificate)); 13 | Subject = certificate.Subject; 14 | PublicKey = certificate.PublicKey.EncodedKeyValue.Format(true); 15 | NotAfter = certificate.NotAfter; 16 | NotBefore = certificate.NotBefore; 17 | Issuer = certificate.Issuer; 18 | SerialNumber = certificate.SerialNumber; 19 | CertHashString = certificate.GetCertHashString(); 20 | Pkcs7 = Convert.ToBase64String(certificate.Export(X509ContentType.Cert)); 21 | } 22 | 23 | [JsonConstructor] 24 | public SerializableCertificate(string Thumbprint, string Subject, string PublicKey, DateTime NotAfter, DateTime NotBefore, string Issuer, string SerialNumber, string CertHashString, string Pkcs7) 25 | { 26 | this.Thumbprint = Thumbprint; 27 | this.Subject = Subject; 28 | this.PublicKey = PublicKey; 29 | this.NotAfter = NotAfter; 30 | this.NotBefore = NotBefore; 31 | this.Issuer = Issuer; 32 | this.SerialNumber = SerialNumber; 33 | this.CertHashString = CertHashString; 34 | this.Pkcs7 = Pkcs7; 35 | } 36 | 37 | public string CertHashString { get; set; } 38 | public string Issuer { get; set; } 39 | public DateTime NotAfter { get; set; } 40 | public DateTime NotBefore { get; set; } 41 | public string Pkcs7 { get; set; } 42 | public string PublicKey { get; set; } 43 | public string SerialNumber { get; set; } 44 | public string Subject { get; set; } 45 | public string Thumbprint { get; set; } 46 | } 47 | } -------------------------------------------------------------------------------- /Lib/Objects/ServiceObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | using Newtonsoft.Json; 4 | using System; 5 | 6 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 7 | { 8 | public class ServiceObject : CollectObject 9 | { 10 | [JsonConstructor] 11 | public ServiceObject(string Name) 12 | { 13 | this.Name = Name; 14 | ResultType = RESULT_TYPE.SERVICE; 15 | } 16 | 17 | public bool? AcceptPause { get; set; } 18 | public bool? AcceptStop { get; set; } 19 | public string? Caption { get; set; } 20 | public uint? CheckPoint { get; set; } 21 | public string? CreationClassName { get; set; } 22 | public bool? DelayedAutoStart { get; set; } 23 | public string? Description { get; set; } 24 | public bool? DesktopInteract { get; set; } 25 | public string? DisplayName { get; set; } 26 | public string? ErrorControl { get; set; } 27 | public uint? ExitCode { get; set; } 28 | 29 | public override string Identity 30 | { 31 | get 32 | { 33 | return Name; 34 | } 35 | } 36 | 37 | public DateTime InstallDate { get; set; } 38 | public string Name { get; set; } 39 | public string? PathName { get; set; } 40 | public uint? ProcessId { get; set; } 41 | public uint? ServiceSpecificExitCode { get; set; } 42 | public string? ServiceType { get; set; } 43 | public bool? Started { get; set; } 44 | public string? StartMode { get; set; } 45 | public string? StartName { get; set; } 46 | public string? State { get; set; } 47 | public string? Status { get; set; } 48 | public string? SystemCreationClassName { get; set; } 49 | public string? SystemName { get; set; } 50 | public uint? TagId { get; set; } 51 | public uint? WaitHint { get; set; } 52 | } 53 | } -------------------------------------------------------------------------------- /Lib/Objects/Settings.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 3 | { 4 | public class Settings 5 | { 6 | /// 7 | /// Schema Version of the database 8 | /// 9 | public int SchemaVersion { get; set; } 10 | 11 | /// 12 | /// How many database files to use/shard data across. 13 | /// 14 | public int ShardingFactor { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /Lib/Objects/Signature.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Newtonsoft.Json; 3 | using PeNet.Header.Authenticode; 4 | using System; 5 | using System.Security.Cryptography.X509Certificates; 6 | 7 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 8 | { 9 | public class Signature 10 | { 11 | public Signature(AuthenticodeInfo authenticodeInfo) 12 | { 13 | if (authenticodeInfo != null) 14 | { 15 | IsAuthenticodeValid = authenticodeInfo.IsAuthenticodeValid; 16 | if (authenticodeInfo.SignedHash is byte[] hash) 17 | { 18 | SignedHash = Convert.ToBase64String(hash); 19 | } 20 | SignerSerialNumber = authenticodeInfo.SignerSerialNumber; 21 | if (authenticodeInfo.SigningCertificate is X509Certificate2 cert) 22 | { 23 | SigningCertificate = new SerializableCertificate(cert); 24 | } 25 | } 26 | else 27 | { 28 | IsAuthenticodeValid = false; 29 | } 30 | } 31 | 32 | /// 33 | /// This constructor is for deserialization. 34 | /// 35 | /// 36 | [JsonConstructor] 37 | public Signature() 38 | { 39 | } 40 | 41 | public bool IsTimeValid 42 | { 43 | get 44 | { 45 | if (SigningCertificate != null) 46 | { 47 | return DateTime.Now > SigningCertificate.NotBefore && DateTime.Now < SigningCertificate.NotAfter; 48 | } 49 | return false; 50 | } 51 | } 52 | 53 | public bool IsAuthenticodeValid { get; set; } 54 | public string? SignedHash { get; set; } 55 | public string? SignerSerialNumber { get; set; } 56 | public SerializableCertificate? SigningCertificate { get; set; } 57 | } 58 | } -------------------------------------------------------------------------------- /Lib/Objects/SkipCompareAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 4 | { 5 | [AttributeUsage(AttributeTargets.All) 6 | ] 7 | public class SkipCompareAttribute : Attribute 8 | { 9 | public SkipCompareAttribute() 10 | { 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Lib/Objects/TpmObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using System; 3 | using System.Collections.Generic; 4 | using Tpm2Lib; 5 | 6 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 7 | { 8 | public class TpmObject : CollectObject 9 | { 10 | public TpmObject(string Location) 11 | { 12 | ResultType = Types.RESULT_TYPE.TPM; 13 | this.Location = Location; 14 | } 15 | 16 | public List Algorithms { get; set; } = new List(); 17 | public List Commands { get; set; } = new List(); 18 | 19 | public override string Identity 20 | { 21 | get 22 | { 23 | return Location; 24 | } 25 | } 26 | 27 | public string Location { get; } 28 | public string? Manufacturer { get; set; } 29 | public List NV { get; set; } = new List(); 30 | public Dictionary<(TpmAlgId, uint), byte[]> PCRs { get; set; } = new Dictionary<(TpmAlgId, uint), byte[]>(); 31 | public List PersistentKeys { get; set; } = new List(); 32 | public List RandomKeys { get; set; } = new List(); 33 | public DateTime TpmSpecDate { get; set; } 34 | public string? Version { get; set; } 35 | } 36 | } -------------------------------------------------------------------------------- /Lib/Objects/UserAccountObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | using System.Collections.Generic; 4 | using System.Globalization; 5 | 6 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 7 | { 8 | public class UserAccountObject : CollectObject 9 | { 10 | public UserAccountObject(string Name) 11 | { 12 | this.Name = Name; 13 | ResultType = RESULT_TYPE.USER; 14 | } 15 | 16 | public string? AccountType { get; set; } 17 | public string? Caption { get; set; } 18 | public string? Description { get; set; } 19 | public string? Disabled { get; set; } 20 | public string? Domain { get; set; } 21 | public string? FullName { get; set; } 22 | public string? GID { get; set; } 23 | public List Groups { get; set; } = new List(); 24 | public bool? Hidden { get; set; } 25 | public string? HomeDirectory { get; set; } 26 | 27 | public override string Identity 28 | { 29 | get 30 | { 31 | return string.Format(CultureInfo.InvariantCulture, "{0}{1}", "User: ", (Domain == null) ? Name : $"{Domain}\\{Name}"); 32 | } 33 | } 34 | 35 | public string? Inactive { get; set; } 36 | public string? InstallDate { get; set; } 37 | public string? LocalAccount { get; set; } 38 | public string? Lockout { get; set; } 39 | public string Name { get; set; } 40 | public string? PasswordChangeable { get; set; } 41 | public string? PasswordExpires { get; set; } 42 | public string? PasswordRequired { get; set; } 43 | public string? PasswordStorageAlgorithm { get; set; } 44 | public bool? Privileged { get; set; } 45 | public Dictionary? Properties { get; set; } 46 | public string? Shell { get; set; } 47 | public string? SID { get; set; } 48 | public string? UID { get; set; } 49 | } 50 | } -------------------------------------------------------------------------------- /Lib/Objects/UserGroupObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | using System.Collections.Generic; 4 | 5 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 6 | { 7 | public class GroupAccountObject : CollectObject 8 | { 9 | public GroupAccountObject(string Name) 10 | { 11 | this.Name = Name; 12 | ResultType = RESULT_TYPE.GROUP; 13 | } 14 | 15 | public string? Caption { get; set; } 16 | public string? Description { get; set; } 17 | public string? Domain { get; set; } 18 | 19 | public override string Identity 20 | { 21 | get 22 | { 23 | return (Domain == null) ? Name : $"{Domain}\\{Name}"; 24 | } 25 | } 26 | 27 | public string? InstallDate { get; set; } 28 | public bool? LocalAccount { get; set; } 29 | public string Name { get; set; } 30 | public Dictionary? Properties { get; set; } 31 | public string? SID { get; set; } 32 | public int? SIDType { get; set; } 33 | public string? Status { get; set; } 34 | public List Users { get; set; } = new List(); 35 | } 36 | } -------------------------------------------------------------------------------- /Lib/Objects/WifiObject.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 2 | { 3 | public class WifiObject : CollectObject 4 | { 5 | public WifiObject(string SSID) 6 | { 7 | this.SSID = SSID; 8 | this.ResultType = Types.RESULT_TYPE.WIFI; 9 | } 10 | 11 | public string? Authentication { get; set; } 12 | 13 | public string? Encryption { get; set; } 14 | 15 | public override string Identity 16 | { 17 | get 18 | { 19 | return SSID; 20 | } 21 | } 22 | 23 | public string? Password { get; set; } 24 | public string SSID { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /Lib/Objects/WriteObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 3 | using Microsoft.CST.AttackSurfaceAnalyzer.Utils; 4 | using Serilog; 5 | using System; 6 | 7 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Objects 8 | { 9 | public class WriteObject 10 | { 11 | public WriteObject(CollectObject ColObjIn, string RunIdIn) 12 | { 13 | ColObj = ColObjIn ?? throw new ArgumentNullException(nameof(ColObjIn)); 14 | RunId = RunIdIn; 15 | Serialized = ColObj.Serialized; 16 | RowKey = ColObj.RowKey; 17 | } 18 | 19 | public CollectObject ColObj { get; } 20 | 21 | public string Identity 22 | { 23 | get 24 | { 25 | return ColObj?.Identity ?? string.Empty; 26 | } 27 | } 28 | 29 | public string RowKey { get; } 30 | public string RunId { get; } 31 | public string Serialized { get; } 32 | 33 | public static WriteObject? FromString(string SerializedIn, RESULT_TYPE ResultTypeIn, string RunIdIn) 34 | { 35 | var deserialized = JsonUtils.Hydrate(SerializedIn, ResultTypeIn); 36 | 37 | if (deserialized is CollectObject) 38 | { 39 | return new WriteObject(deserialized, RunIdIn); 40 | } 41 | else 42 | { 43 | Log.Debug($"Couldn't hydrate {SerializedIn} Failed to make a WriteObject."); 44 | return null; 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /Lib/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "AttackSurfaceAnalyzerCli": { 4 | "commandName": "Project", 5 | "commandLineArgs": "export-collect --databasefilename C:\\Users\\Gstoc\\Documents\\GitHub\\AttackSurfaceAnalyzer\\Cli\\asa.sqlite" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /Lib/Utils/AsaAnalyzer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CST.AttackSurfaceAnalyzer.Objects; 2 | using Microsoft.CST.OAT; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Globalization; 6 | using System.Linq; 7 | using Tpm2Lib; 8 | 9 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Utils 10 | { 11 | public class AsaAnalyzer : Analyzer 12 | { 13 | public AsaAnalyzer(AnalyzerOptions? opts = null) : base(opts) 14 | { 15 | CustomPropertyExtractionDelegates.Add(ParseCustomAsaProperties); 16 | CustomObjectToValuesDelegates.Add(ParseCustomAsaObjectValues); 17 | } 18 | 19 | public static (bool Processed, IEnumerable valsExtracted, IEnumerable> dictExtracted) ParseCustomAsaObjectValues(object? obj) 20 | { 21 | if (obj is Dictionary<(TpmAlgId, uint), byte[]> algDict) 22 | { 23 | return (true, Array.Empty(), algDict.ToList().Select(x => new KeyValuePair(x.Key.ToString(), Convert.ToBase64String(x.Value))).ToList()); 24 | } 25 | return (false, Array.Empty(), Array.Empty>()); 26 | } 27 | 28 | public static (bool, object?) ParseCustomAsaProperties(object? obj, string index) 29 | { 30 | switch (obj) 31 | { 32 | case Dictionary<(TpmAlgId, uint), byte[]> algDict: 33 | var elements = Convert.ToString(index, CultureInfo.InvariantCulture)?.Trim('(').Trim(')').Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); 34 | if (Enum.TryParse(typeof(TpmAlgId), elements.First(), out object? result) && 35 | result is TpmAlgId Algorithm && uint.TryParse(elements.Last(), out uint Index) && 36 | algDict.TryGetValue((Algorithm, Index), out byte[]? byteArray)) 37 | { 38 | return (true, byteArray); 39 | } 40 | else 41 | { 42 | return (true, null); 43 | } 44 | } 45 | return (false, null); 46 | } 47 | 48 | public IEnumerable Analyze(IEnumerable rules, CompareResult compareResult) 49 | { 50 | if (compareResult == null) 51 | { 52 | return Array.Empty(); 53 | } 54 | 55 | return Analyze(rules, compareResult.Base, compareResult.Compare); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /Lib/Utils/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using System.Resources; 3 | 4 | [assembly: NeutralResourcesLanguage("en")] 5 | 6 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Utils 7 | { 8 | } -------------------------------------------------------------------------------- /Lib/Utils/CryptoHelpers.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Serilog; 3 | using System; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Security.Cryptography; 7 | using System.Text; 8 | 9 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Utils 10 | { 11 | public static class CryptoHelpers 12 | { 13 | /// 14 | /// Perform a hash of a string. 15 | /// 16 | /// 17 | /// 18 | public static string CreateHash(string input) 19 | { 20 | try 21 | { 22 | byte[] hashOutput = sha512.ComputeHash(Encoding.UTF8.GetBytes(input)); 23 | return Convert.ToBase64String(hashOutput); 24 | } 25 | catch (CryptographicException e) 26 | { 27 | Log.Warning(e, Strings.Get("Err_CreateHash"), input is null ? "null string" : $"'{input}'"); 28 | return string.Empty; 29 | } 30 | } 31 | 32 | public static string CreateHash(Stream stream) 33 | { 34 | try 35 | { 36 | return Convert.ToBase64String(sha512.ComputeHash(stream) ?? Array.Empty()); 37 | } 38 | catch (CryptographicException e) 39 | { 40 | Log.Warning(e, Strings.Get("Err_CreateHash"), "stream"); 41 | return string.Empty; 42 | } 43 | } 44 | 45 | public static double GetRandomPositiveDouble(double max) 46 | { 47 | var bytes = new byte[8]; 48 | crypto.GetBytes(bytes); 49 | return (BitConverter.ToUInt64(bytes, 0) >> 11) / (double)ulong.MaxValue * max; 50 | } 51 | 52 | public static int GetRandomPositiveIndex(int max) 53 | { 54 | var randomInteger = UInt32.MaxValue; 55 | while (randomInteger == UInt32.MaxValue) 56 | { 57 | byte[] data = new byte[4]; 58 | crypto.GetBytes(data); 59 | randomInteger = BitConverter.ToUInt32(data, 0); 60 | } 61 | 62 | return (int)(max * (randomInteger / (double)uint.MaxValue)); 63 | } 64 | 65 | public static string GetRandomString(int characters) => new string(Enumerable.Range(1, characters).Select(_ => chars[GetRandomPositiveIndex(chars.Length)]).ToArray()); 66 | 67 | private const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 68 | 69 | private static readonly RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider(); 70 | 71 | private static readonly HashAlgorithm sha512 = SHA512Managed.Create(); 72 | } 73 | } -------------------------------------------------------------------------------- /Lib/Utils/Logger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Serilog; 3 | using Serilog.Events; 4 | 5 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Utils 6 | { 7 | public static class Logger 8 | { 9 | public static bool Debug { get; set; } 10 | public static bool Quiet { get; set; } 11 | public static bool Verbose { get; set; } 12 | 13 | public static void Setup() 14 | { 15 | Setup(false, false); 16 | } 17 | 18 | public static void Setup(bool debug, bool verbose) 19 | { 20 | Setup(debug, verbose, false); 21 | } 22 | 23 | public static void Setup(bool debug, bool verbose, bool quiet) 24 | { 25 | (Verbose, Debug, Quiet) = (verbose, debug, quiet); 26 | if (quiet) 27 | { 28 | Log.Logger = new LoggerConfiguration() 29 | .MinimumLevel.Warning() 30 | .WriteTo.Console() 31 | .CreateLogger(); 32 | } 33 | else if (verbose) 34 | { 35 | Log.Logger = new LoggerConfiguration() 36 | .MinimumLevel.Verbose() 37 | .WriteTo.File("asa.log.txt") 38 | .WriteTo.Console() 39 | .CreateLogger(); 40 | } 41 | else if (debug) 42 | { 43 | Log.Logger = new LoggerConfiguration() 44 | .MinimumLevel.Debug() 45 | .WriteTo.File("asa.log.txt") 46 | .WriteTo.Console() 47 | .CreateLogger(); 48 | } 49 | else 50 | { 51 | Log.Logger = new LoggerConfiguration() 52 | .MinimumLevel.Information() 53 | .WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Information) 54 | .CreateLogger(); 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /Lib/Utils/RunManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Utils 3 | { 4 | public class RunManager 5 | { 6 | public RunManager() 7 | { 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /Lib/Utils/SafeTokenHandle.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.Win32.SafeHandles; 3 | using System; 4 | 5 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Utils 6 | { 7 | /// 8 | /// Represents a wrapper class for a token handle. 9 | /// 10 | internal class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid 11 | { 12 | internal SafeTokenHandle(IntPtr handle) : base(true) 13 | { 14 | base.SetHandle(handle); 15 | } 16 | 17 | protected override bool ReleaseHandle() 18 | { 19 | return NativeMethods.CloseHandle(base.handle); 20 | } 21 | 22 | private SafeTokenHandle() : base(true) 23 | { 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Lib/Utils/Strings.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Objects; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Resources; 7 | 8 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Utils 9 | { 10 | public static class Strings 11 | { 12 | public static string Get(string key) 13 | { 14 | if (stringList.ContainsKey(key)) 15 | { 16 | return stringList[key]; 17 | } 18 | return key; 19 | } 20 | 21 | public static void Setup(string locale = "") 22 | { 23 | if (string.IsNullOrEmpty(locale)) 24 | { 25 | using Stream? stream = typeof(FileSystemObject).Assembly.GetManifestResourceStream("AttackSurfaceAnalyzer.Properties.Resources.resources"); 26 | if (stream is Stream) 27 | { 28 | stringList.Clear(); 29 | using ResourceReader reader = new ResourceReader(stream); 30 | foreach (DictionaryEntry? entry in reader) 31 | { 32 | if (entry is DictionaryEntry dictionaryEntry) 33 | { 34 | var keyStr = dictionaryEntry.Key.ToString(); 35 | var valueStr = dictionaryEntry.Value?.ToString(); 36 | if (!string.IsNullOrEmpty(keyStr) && !string.IsNullOrEmpty(valueStr)) 37 | stringList.TryAdd(keyStr, valueStr); 38 | } 39 | } 40 | } 41 | } 42 | } 43 | 44 | /// 45 | /// Internal member structure holding string resources 46 | /// 47 | private static readonly Dictionary stringList = new Dictionary(); 48 | } 49 | } -------------------------------------------------------------------------------- /NuGet.Config.AzureArtifacts: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /NuGet.Config.Public: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Pipelines/asa-release.yml: -------------------------------------------------------------------------------- 1 | name: ASA_Release_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r) 2 | trigger: none 3 | pr: 4 | - main 5 | 6 | resources: 7 | repositories: 8 | - repository: 1esPipelines 9 | type: git 10 | name: 1ESPipelineTemplates/1ESPipelineTemplates 11 | ref: refs/tags/release 12 | 13 | variables: 14 | BuildConfiguration: 'Release' 15 | DotnetVersion: '8.0.x' 16 | DotnetTargetFramework: 'net8.0' 17 | 18 | extends: 19 | template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines 20 | parameters: 21 | pool: 22 | name: MSSecurity-1ES-Build-Agents-Pool 23 | image: MSSecurity-1ES-Windows-2022 24 | os: windows 25 | stages: 26 | - stage: NoOp 27 | dependsOn: [] 28 | jobs: 29 | - job: NoOp 30 | displayName: NoOp 31 | steps: 32 | - script: echo Placeholder -------------------------------------------------------------------------------- /Pipelines/core-pipeline.yml: -------------------------------------------------------------------------------- 1 | # Azure Pipelines 2 | # https://aka.ms/yaml 3 | 4 | name: ASA_PR_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r) 5 | trigger: none 6 | pr: 7 | - main 8 | 9 | resources: 10 | repositories: 11 | - repository: 1esPipelines 12 | type: git 13 | name: 1ESPipelineTemplates/1ESPipelineTemplates 14 | ref: refs/tags/release 15 | 16 | variables: 17 | BuildConfiguration: 'Release' 18 | DotnetVersion: '8.0.x' 19 | DotnetTargetFramework: 'net8.0' 20 | 21 | extends: 22 | template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines 23 | parameters: 24 | pool: 25 | name: MSSecurity-1ES-Build-Agents-Pool 26 | image: MSSecurity-1ES-Windows-2022 27 | os: windows 28 | stages: 29 | - stage: NoOp 30 | dependsOn: [] 31 | jobs: 32 | - job: NoOp 33 | displayName: NoOp 34 | steps: 35 | - script: echo Placeholder -------------------------------------------------------------------------------- /Pipelines/templates/dotnet-publish-linux-mac-job.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | # Job Name 3 | - name: jobName 4 | type: string 5 | default: 'publish_linux_mac' 6 | # Optional Pre-Build Steps 7 | - name: 'preBuild' 8 | type: stepList 9 | default: [] 10 | # Version of Dotnet SDK to use 11 | - name: dotnetVersion 12 | type: string 13 | default: '5.x' 14 | # Version of NuGet Tool to use 15 | - name: nugetVersion 16 | type: string 17 | default: '5.x' 18 | # Path to .csproj or .sln 19 | - name: projectPath 20 | type: string 21 | default: '' 22 | # Build Configuration 23 | - name: buildConfiguration 24 | type: string 25 | default: 'Release' 26 | # Project Name 27 | - name: projectName 28 | type: string 29 | default: '' 30 | # Release Version 31 | - name: releaseVersion 32 | type: string 33 | default: '' 34 | # Pipeline Artifact Name 35 | - name: artifactName 36 | type: string 37 | default: 'Unsigned_Binaries' 38 | 39 | jobs: 40 | - job: ${{ parameters.jobName }} 41 | displayName: Dotnet Publish Linux/Mac 42 | pool: 43 | vmImage: 'ubuntu-latest' 44 | steps: 45 | - task: NuGetAuthenticate@1 46 | - task: UseDotNet@2 47 | displayName: Install Dotnet SDK 48 | inputs: 49 | packageType: 'sdk' 50 | version: ${{ parameters.dotnetVersion }} 51 | - task: NuGetToolInstaller@1 52 | displayName: Install Nuget Tool 53 | inputs: 54 | versionSpec: ${{ parameters.nugetVersion }} 55 | - ${{ parameters.preBuild }} 56 | - task: DotNetCoreCLI@2 57 | displayName: Restore 58 | inputs: 59 | command: 'restore' 60 | feedsToUse: config 61 | nugetConfigPath: NuGet.Config.AzureArtifacts 62 | projects: ${{ parameters.projectPath }} 63 | verbosityRestore: 'Normal' 64 | - task: DotNetCoreCLI@2 65 | displayName: Publish Linux x64 66 | inputs: 67 | command: 'publish' 68 | arguments: '${{ parameters.projectPath }} -c ${{ parameters.buildConfiguration }} -o bin/linux/${{ parameters.projectName }}_linux_$(ReleaseVersion) -r linux-x64' 69 | publishWebProjects: false 70 | zipAfterPublish: false 71 | - task: DotNetCoreCLI@2 72 | displayName: Publish MacOS x64 73 | inputs: 74 | command: 'publish' 75 | arguments: '${{ parameters.projectPath }} -c ${{ parameters.buildConfiguration }} -o bin/macos/${{ parameters.projectName }}_macos_$(ReleaseVersion) -r osx-x64' 76 | publishWebProjects: false 77 | zipAfterPublish: false 78 | - task: ArchiveFiles@2 79 | displayName: Archive Builds 80 | inputs: 81 | rootFolderOrFile: 'bin' 82 | includeRootFolder: false 83 | archiveType: 'zip' 84 | archiveFile: 'Archives/${{ parameters.projectName }}_Nix.zip' 85 | replaceExistingArchive: true 86 | - task: PublishBuildArtifacts@1 87 | displayName: Pipeline Publish Archive 88 | inputs: 89 | PathtoPublish: 'Archives' 90 | ArtifactName: '${{ parameters.artifactName }}' 91 | publishLocation: 'Container' -------------------------------------------------------------------------------- /Pipelines/templates/dotnet-publish-win-netcore-job.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | # Job Name 3 | - name: jobName 4 | type: string 5 | default: 'publish_win' 6 | # Optional Pre-Build Steps 7 | - name: 'preBuild' 8 | type: stepList 9 | default: [] 10 | # Version of Dotnet SDK to use 11 | - name: dotnetVersion 12 | type: string 13 | default: '5.x' 14 | # Version of NuGet Tool to use 15 | - name: nugetVersion 16 | type: string 17 | default: '5.x' 18 | # Path to .csproj or .sln 19 | - name: projectPath 20 | type: string 21 | default: '' 22 | # Build Configuration 23 | - name: buildConfiguration 24 | type: string 25 | default: 'Release' 26 | # Project Name 27 | - name: projectName 28 | type: string 29 | default: '' 30 | # Release Version 31 | - name: releaseVersion 32 | type: string 33 | default: '' 34 | # Pipeline Artifact Name 35 | - name: artifactName 36 | type: string 37 | default: 'Unsigned_Binaries' 38 | 39 | jobs: 40 | - job: ${{ parameters.jobName }} 41 | displayName: Dotnet Publish Win/NetCoreApp 42 | pool: 43 | vmImage: 'windows-latest' 44 | steps: 45 | - task: NuGetAuthenticate@1 46 | - task: UseDotNet@2 47 | displayName: Install Dotnet SDK 48 | inputs: 49 | packageType: 'sdk' 50 | version: ${{ parameters.dotnetVersion }} 51 | - task: NuGetToolInstaller@1 52 | displayName: Install Nuget Tool 53 | inputs: 54 | versionSpec: ${{ parameters.nugetVersion }} 55 | - ${{ parameters.preBuild }} 56 | - task: DotNetCoreCLI@2 57 | displayName: Restore 58 | inputs: 59 | command: 'restore' 60 | feedsToUse: config 61 | nugetConfigPath: NuGet.Config.AzureArtifacts 62 | projects: ${{ parameters.projectPath }} 63 | verbosityRestore: 'Normal' 64 | - task: DotNetCoreCLI@2 65 | displayName: Publish Win x64 66 | inputs: 67 | command: 'publish' 68 | arguments: '${{ parameters.projectPath }} -c ${{ parameters.buildConfiguration }} -o bin/win/${{ parameters.projectName }}_win_$(ReleaseVersion) -r win-x64' 69 | publishWebProjects: false 70 | zipAfterPublish: false 71 | - task: DotNetCoreCLI@2 72 | displayName: Build .NET Core App 73 | inputs: 74 | command: 'publish' 75 | arguments: '${{ parameters.projectPath }} -c ${{ parameters.buildConfiguration }} -o bin/netcoreapp/${{ parameters.projectName }}_netcoreapp_$(ReleaseVersion)' 76 | publishWebProjects: false 77 | zipAfterPublish: false 78 | - task: AntiMalware@3 79 | displayName: Anti-Malware Scan 80 | inputs: 81 | InputType: 'Basic' 82 | ScanType: 'CustomScan' 83 | FileDirPath: 'bin' 84 | EnableServices: true 85 | SupportLogOnError: true 86 | TreatSignatureUpdateFailureAs: 'Warning' 87 | SignatureFreshness: 'UpToDate' 88 | TreatStaleSignatureAs: 'Warning' 89 | - task: ArchiveFiles@2 90 | displayName: Archive Builds 91 | inputs: 92 | rootFolderOrFile: 'bin' 93 | includeRootFolder: false 94 | archiveType: 'zip' 95 | archiveFile: 'Archives\${{ parameters.projectName }}_Win_NetCoreApp.zip' 96 | replaceExistingArchive: true 97 | - task: PublishBuildArtifacts@1 98 | displayName: Pipeline Publish Archive 99 | inputs: 100 | PathtoPublish: 'Archives' 101 | ArtifactName: '${{ parameters.artifactName }}' 102 | publishLocation: 'Container' -------------------------------------------------------------------------------- /Pipelines/templates/dotnet-test-job.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | # Job Name 3 | - name: jobName 4 | type: string 5 | default: 'dotnet_test' 6 | # Version of Dotnet SDK to use 7 | - name: dotnetVersion 8 | type: string 9 | default: '5.x' 10 | # Version of NuGet Tool to use 11 | - name: nugetVersion 12 | type: string 13 | default: '5.x' 14 | # List of paths to .csproj 15 | - name: projectPath 16 | type: string 17 | default: '' 18 | 19 | jobs: 20 | - job: ${{ parameters.jobName }} 21 | displayName: Dotnet Test 22 | pool: 23 | vmImage: 'windows-latest' 24 | steps: 25 | - task: NuGetAuthenticate@1 26 | - task: UseDotNet@2 27 | displayName: Install Dotnet SDK 28 | inputs: 29 | packageType: 'sdk' 30 | version: ${{ parameters.dotnetVersion }} 31 | - task: NuGetToolInstaller@1 32 | displayName: Install Nuget Tool 33 | inputs: 34 | versionSpec: ${{ parameters.nugetVersion }} 35 | - task: DotNetCoreCLI@2 36 | displayName: Dotnet Restore 37 | inputs: 38 | command: 'restore' 39 | feedsToUse: config 40 | nugetConfigPath: NuGet.Config.AzureArtifacts 41 | projects: ${{ parameters.projectPath }} 42 | verbosityRestore: 'Normal' 43 | - task: DotNetCoreCLI@2 44 | displayName: Dotnet Test 45 | inputs: 46 | command: 'test' 47 | projects: ${{ parameters.projectPath }} -------------------------------------------------------------------------------- /Pipelines/templates/nbgv-set-version-steps.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - script: 'dotnet tool update -g nbgv --configfile NuGet.Config.Public' 3 | displayName: 'Update GitVersioning' 4 | - task: PowerShell@2 5 | displayName: Set Release Version 6 | inputs: 7 | targetType: 'inline' 8 | script: | 9 | $version = (nbgv get-version -v AssemblyInformationalVersion).split('+')[0] 10 | Write-Host "##vso[task.setvariable variable=releaseVersion;]$version" -------------------------------------------------------------------------------- /Pipelines/templates/nuget-build-job.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | # Job Name 3 | - name: jobName 4 | type: string 5 | default: 'nuget_pack' 6 | # Version of Dotnet SDK to use 7 | - name: dotnetVersion 8 | type: string 9 | default: '5.x' 10 | # Version of NuGet Tool to use 11 | - name: nugetVersion 12 | type: string 13 | default: '5.x' 14 | # Path to .csproj or .sln 15 | - name: projectPath 16 | type: string 17 | default: '' 18 | # Build Configuration 19 | - name: buildConfiguration 20 | type: string 21 | default: 'Release' 22 | # Project Name 23 | - name: projectName 24 | type: string 25 | default: '' 26 | # Pipeline Artifact Name 27 | - name: artifactName 28 | type: string 29 | default: 'Unsigned_Binaries' 30 | 31 | jobs: 32 | - job: ${{ parameters.jobName }} 33 | displayName: NuGet Package 34 | pool: 35 | vmImage: 'windows-latest' 36 | steps: 37 | - task: NuGetAuthenticate@1 38 | - task: UseDotNet@2 39 | displayName: Install Dotnet SDK 40 | inputs: 41 | packageType: 'sdk' 42 | version: ${{ parameters.dotnetVersion }} 43 | - task: NuGetToolInstaller@1 44 | displayName: Install Nuget Tool 45 | inputs: 46 | versionSpec: ${{ parameters.nugetVersion }} 47 | - task: DotNetCoreCLI@2 48 | displayName: Dotnet Restore 49 | inputs: 50 | command: 'restore' 51 | feedsToUse: config 52 | nugetConfigPath: NuGet.Config.AzureArtifacts 53 | projects: ${{ parameters.projectPath }} 54 | verbosityRestore: 'Normal' 55 | - task: DotNetCoreCLI@2 56 | displayName: Pack Nupkg 57 | inputs: 58 | command: 'custom' 59 | custom: 'pack' 60 | arguments: '${{ parameters.projectPath }} -c ${{ parameters.buildConfiguration }} -o Packages' 61 | - task: AntiMalware@3 62 | displayName: Anti-Malware Scan 63 | inputs: 64 | InputType: 'Basic' 65 | ScanType: 'CustomScan' 66 | FileDirPath: 'Packages' 67 | EnableServices: true 68 | SupportLogOnError: true 69 | TreatSignatureUpdateFailureAs: 'Warning' 70 | SignatureFreshness: 'UpToDate' 71 | TreatStaleSignatureAs: 'Warning' 72 | - task: ArchiveFiles@2 73 | displayName: Archive Packages 74 | inputs: 75 | rootFolderOrFile: 'Packages' 76 | includeRootFolder: false 77 | archiveType: 'zip' 78 | archiveFile: 'Archives\${{ parameters.projectName }}_NuGet.zip' 79 | replaceExistingArchive: true 80 | - task: PublishBuildArtifacts@1 81 | displayName: Pipeline Publish Archive 82 | inputs: 83 | PathtoPublish: 'Archives' 84 | ArtifactName: '${{ parameters.artifactName }}' 85 | publishLocation: 'Container' -------------------------------------------------------------------------------- /Pipelines/templates/sdl-job.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | # Service Tree ID of application 3 | - name: serviceTreeID 4 | type: string 5 | default: '' 6 | 7 | jobs: 8 | - job: sdl_tools 9 | displayName: SDL Tools 10 | pool: 11 | vmImage: 'windows-latest' 12 | steps: 13 | - task: CodeInspector@2 14 | continueOnError: true 15 | inputs: 16 | ProductId: ${{ parameters.serviceTreeID }} 17 | - task: CredScan@3 18 | inputs: 19 | verboseOutput: true 20 | - task: notice@0 21 | enabled: false 22 | continueOnError: true 23 | inputs: 24 | outputformat: 'text' 25 | - task: SdtReport@2 26 | inputs: 27 | GdnExportAllTools: true -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 2.3 | :white_check_mark: | 11 | | 2.2 | :x: | 12 | | 2.1 | :x: | 13 | | 2.0 | :x: | 14 | | < 2.0 | :x: | 15 | 16 | ## Reporting a Vulnerability 17 | 18 | Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) at secure@microsoft.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the MSRC PGP key, can be found in the Security TechCenter. 19 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | ## Getting Help 2 | 3 | This project uses GitHub issues to track bugs and take feature requests. Please 4 | search for existing issues before filing new ones to avoid duplicates. To 5 | open a new issue, click on [Issues](https://github.com/Microsoft/AttackSurfaceAnalyzer/issues) 6 | and then [New issue](https://github.com/microsoft/AttackSurfaceAnalyzer/issues/new/choose). 7 | 8 | If you need help in how to use this project, please review our [Wiki](https://github.com/Microsoft/AttackSurfaceAnalyzer/wiki) 9 | before opening an issue. 10 | 11 | ## Security Issues 12 | 13 | If you discover a security vulnerability in this project, please see [SECURITY.md](https://github.com/microsoft/AttackSurfaceAnalyzer/blob/master/SECURITY.md) for information on how to report it privately. 14 | 15 | ## Microsoft Support Policy 16 | 17 | Support for this project is limited to the resources listed above. 18 | -------------------------------------------------------------------------------- /Tests/AsaAnalyzerTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CST.AttackSurfaceAnalyzer.Cli; 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Objects; 3 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 4 | using Microsoft.CST.AttackSurfaceAnalyzer.Utils; 5 | using Microsoft.CST.OAT; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | 10 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Tests 11 | { 12 | [TestClass] 13 | public class AsaAnalyzerTests 14 | { 15 | public AsaAnalyzerTests() 16 | { 17 | } 18 | 19 | [ClassInitialize] 20 | public static void ClassSetup(TestContext _) 21 | { 22 | Logger.Setup(false, true); 23 | Strings.Setup(); 24 | } 25 | 26 | [TestMethod] 27 | public void VerifyEmbeddedRulesAreValid() 28 | { 29 | var analyzer = new AsaAnalyzer(); 30 | var ruleFile = RuleFile.LoadEmbeddedFilters(); 31 | Assert.IsTrue(!analyzer.EnumerateRuleIssues(ruleFile.Rules).Any()); 32 | } 33 | 34 | [TestMethod] 35 | public void VerifyFileMonitorAsFile() 36 | { 37 | var RuleName = "AndRule"; 38 | var andRule = new AsaRule(RuleName) 39 | { 40 | Expression = "0 AND 1", 41 | ResultType = RESULT_TYPE.FILE, 42 | Flag = ANALYSIS_RESULT_TYPE.FATAL, 43 | Clauses = new List() 44 | { 45 | new Clause(Operation.Equals,"Path") 46 | { 47 | Label = "0", 48 | Data = new List() 49 | { 50 | "TestPath1" 51 | } 52 | }, 53 | new Clause(Operation.IsTrue,"IsExecutable") 54 | { 55 | Label = "1" 56 | } 57 | } 58 | }; 59 | 60 | var analyzer = new AsaAnalyzer(); 61 | 62 | var opts = new CompareCommandOptions(null, "SecondRun") { ApplySubObjectRulesToMonitor = true }; 63 | 64 | var ruleFile = new RuleFile(new AsaRule[] { andRule }); 65 | var results = AttackSurfaceAnalyzerClient.AnalyzeMonitored(opts, analyzer, new MonitorObject[] { testPathOneObject }, ruleFile); 66 | 67 | Assert.IsTrue(results.Any(x => x.Value.Any(y => y.Identity == testPathOneObject.Identity && y.Rules.Contains(andRule)))); 68 | 69 | opts = new CompareCommandOptions(null, "SecondRun") { ApplySubObjectRulesToMonitor = false }; 70 | 71 | results = AttackSurfaceAnalyzerClient.AnalyzeMonitored(opts, analyzer, new MonitorObject[] { testPathOneObject }, ruleFile); 72 | 73 | Assert.IsFalse(results.Any(x => x.Value.Any(y => y.Identity == testPathOneObject.Identity && y.Rules.Contains(andRule)))); 74 | } 75 | 76 | private const string TestPathOne = "TestPath1"; 77 | 78 | private readonly FileMonitorObject testPathOneObject = new FileMonitorObject(TestPathOne) { FileSystemObject = new FileSystemObject(TestPathOne) { IsExecutable = true } }; 79 | } 80 | } -------------------------------------------------------------------------------- /Tests/ExportTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Cli; 3 | using Microsoft.CST.AttackSurfaceAnalyzer.Objects; 4 | using Microsoft.CST.AttackSurfaceAnalyzer.Utils; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using Newtonsoft.Json; 7 | using System.Collections.Generic; 8 | using System.IO; 9 | using System.Linq; 10 | 11 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Tests 12 | { 13 | [TestClass] 14 | public class ExportTests 15 | { 16 | [ClassInitialize] 17 | public static void ClassSetup(TestContext _) 18 | { 19 | Logger.Setup(false, true); 20 | Strings.Setup(); 21 | } 22 | 23 | /// 24 | /// Does not require admin. 25 | /// 26 | [TestMethod] 27 | public void TestGenerateSarifLog() 28 | { 29 | JsonSerializerSettings jsonSettings = new JsonSerializerSettings() 30 | { 31 | Formatting = Formatting.Indented, 32 | TypeNameHandling = TypeNameHandling.None, 33 | NullValueHandling = NullValueHandling.Ignore, 34 | DefaultValueHandling = DefaultValueHandling.Ignore, 35 | DateFormatHandling = DateFormatHandling.IsoDateFormat 36 | }; 37 | 38 | var outputJson = File.ReadAllText(@"TestData\ExportTests\TestGenerateSarifLog\output.json"); 39 | var rulesJson = File.ReadAllText(@"TestData\ExportTests\TestGenerateSarifLog\rules.json"); 40 | var outputDictionary = JsonConvert.DeserializeObject>(outputJson, jsonSettings); 41 | var rulesList = JsonConvert.DeserializeObject>(rulesJson, jsonSettings); 42 | 43 | var sarif = AttackSurfaceAnalyzerClient.GenerateSarifLog(outputDictionary, rulesList); 44 | 45 | Assert.AreEqual(sarif.Runs[0].Artifacts.Count, 3); 46 | Assert.IsTrue(sarif.Runs[0].Artifacts.Any(a => a.Location.Description.Text == "C:\\Test\\Scan2\\TestAddText.txt")); 47 | Assert.IsTrue(sarif.Runs[0].Artifacts.Any(a => a.Location.Description.Text == "C:\\Test\\Scan2\\TestAddExe.exe")); 48 | Assert.IsTrue(sarif.Runs[0].Artifacts.Any(a => a.Location.Description.Text == "C:\\Test\\Scan2\\TestModifyExe.exe")); 49 | Assert.AreEqual(sarif.Runs[0].Results.Count, 6); 50 | Assert.IsTrue(sarif.Runs[0].Results.Any(r => r.Message.Text == "Missing DEP: C:\\Test\\Scan2\\TestAddExe.exe (CREATED)")); 51 | Assert.IsTrue(sarif.Runs[0].Results.Any(r => r.Message.Text == "Missing ASLR: C:\\Test\\Scan2\\TestAddExe.exe (CREATED)")); 52 | Assert.IsTrue(sarif.Runs[0].Results.Any(r => r.Message.Text == "Unsigned binaries: C:\\Test\\Scan2\\TestAddExe.exe (CREATED)")); 53 | Assert.IsFalse(sarif.Runs[0].Results.Any(r => r.Message.Text.Contains("TestAddText.txt"))); 54 | Assert.AreEqual(sarif.Runs[0].Tool.Driver.Rules.Count, 41); 55 | Assert.IsTrue(sarif.Runs[0].Tool.Driver.Rules.Any(r => r.FullDescription.Text == "Flag when privileged ports are opened.")); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Tests/InDatabaseComparatorTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using AttackSurfaceAnalyzer.Collectors; 3 | using AttackSurfaceAnalyzer.Objects; 4 | using AttackSurfaceAnalyzer.Types; 5 | using AttackSurfaceAnalyzer.Utils; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | using System; 8 | using System.Linq; 9 | using System.Threading; 10 | 11 | namespace AttackSurfaceAnalyzer.Tests 12 | { 13 | [TestClass] 14 | public class InDatabaseComparatorTests 15 | { 16 | [ClassInitialize] 17 | public static void ClassSetup(TestContext _) 18 | { 19 | Logger.Setup(false, true); 20 | Strings.Setup(); 21 | AsaTelemetry.Setup(test: true); 22 | } 23 | 24 | [TestMethod] 25 | public void TestAddedInDatabase() 26 | { 27 | var elo2 = new EventLogObject("Entry") 28 | { 29 | Timestamp = DateTime.Now.AddYears(1) 30 | }; 31 | 32 | DatabaseManager.Write(elo2, "SecondRun"); 33 | 34 | // Let Database Finish Writing 35 | Thread.Sleep(1); 36 | 37 | BaseCompare bc = new BaseCompare(); 38 | bc.Compare("FirstRun", "SecondRun"); 39 | 40 | var results = bc.Results; 41 | 42 | Assert.IsTrue(results[(RESULT_TYPE.LOG, CHANGE_TYPE.CREATED)].Any(x => x.Compare is EventLogObject)); 43 | } 44 | 45 | [TestCleanup] 46 | public void TestCleanup() 47 | { 48 | DatabaseManager.Destroy(); 49 | } 50 | 51 | [TestMethod] 52 | public void TestModifiedInDatabase() 53 | { 54 | var elo = new EventLogObject("Entry") 55 | { 56 | Timestamp = DateTime.Now 57 | }; 58 | var elo2 = new EventLogObject("Entry") 59 | { 60 | Timestamp = DateTime.Now.AddYears(1) 61 | }; 62 | 63 | DatabaseManager.Write(elo, "FirstRun"); 64 | DatabaseManager.Write(elo2, "SecondRun"); 65 | 66 | // Let Database Finish Writing 67 | Thread.Sleep(1); 68 | 69 | BaseCompare bc = new BaseCompare(); 70 | bc.Compare("FirstRun", "SecondRun"); 71 | 72 | var results = bc.Results; 73 | 74 | Assert.IsTrue(results[(RESULT_TYPE.LOG, CHANGE_TYPE.MODIFIED)].Any(x => x.Compare is EventLogObject)); 75 | } 76 | 77 | [TestMethod] 78 | public void TestRemovedInDatabase() 79 | { 80 | var elo = new EventLogObject("Entry") 81 | { 82 | Timestamp = DateTime.Now 83 | }; 84 | 85 | DatabaseManager.Write(elo, "FirstRun"); 86 | 87 | // Let Database Finish Writing 88 | Thread.Sleep(1); 89 | 90 | BaseCompare bc = new BaseCompare(); 91 | bc.Compare("FirstRun", "SecondRun"); 92 | 93 | var results = bc.Results; 94 | 95 | Assert.IsTrue(results[(RESULT_TYPE.LOG, CHANGE_TYPE.DELETED)].Any(x => x.Base is EventLogObject)); 96 | } 97 | 98 | [TestInitialize] 99 | public void TestSetup() 100 | { 101 | DatabaseManager.Setup("db.name", new DBSettings() { ShardingFactor = 1 }); 102 | } 103 | } 104 | } -------------------------------------------------------------------------------- /Tests/InMemoryComparatorTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. 2 | using Microsoft.CST.AttackSurfaceAnalyzer.Collectors; 3 | using Microsoft.CST.AttackSurfaceAnalyzer.Objects; 4 | using Microsoft.CST.AttackSurfaceAnalyzer.Types; 5 | using Microsoft.CST.AttackSurfaceAnalyzer.Utils; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | 11 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Tests 12 | { 13 | [TestClass] 14 | public class InMemoryComparatorTests 15 | { 16 | [ClassInitialize] 17 | public static void ClassSetup(TestContext _) 18 | { 19 | Logger.Setup(false, true); 20 | Strings.Setup(); 21 | } 22 | 23 | [TestMethod] 24 | public void TestAddedInMemory() 25 | { 26 | var elo2 = new EventLogObject("Entry") 27 | { 28 | Timestamp = DateTime.Now.AddYears(1) 29 | }; 30 | 31 | BaseCompare bc = new BaseCompare(); 32 | bc.Compare(new List() { }, new List() { elo2 }, "FirstRun", "SecondRun"); 33 | 34 | var results = bc.Results; 35 | 36 | Assert.IsTrue(results[(RESULT_TYPE.LOG, CHANGE_TYPE.CREATED)].Any(x => x.Compare is EventLogObject)); 37 | } 38 | 39 | [TestMethod] 40 | public void TestModifiedInMemory() 41 | { 42 | var elo = new EventLogObject("Entry") 43 | { 44 | Timestamp = DateTime.Now 45 | }; 46 | var elo2 = new EventLogObject("Entry") 47 | { 48 | Timestamp = DateTime.Now.AddYears(1) 49 | }; 50 | 51 | BaseCompare bc = new BaseCompare(); 52 | bc.Compare(new List() { elo }, new List() { elo2 }, "FirstRun", "SecondRun"); 53 | 54 | var results = bc.Results; 55 | 56 | Assert.IsTrue(results[(RESULT_TYPE.LOG, CHANGE_TYPE.MODIFIED)].Any(x => x.Compare is EventLogObject)); 57 | } 58 | 59 | [TestMethod] 60 | public void TestRemovedInMemory() 61 | { 62 | var elo = new EventLogObject("Entry") 63 | { 64 | Timestamp = DateTime.Now 65 | }; 66 | 67 | BaseCompare bc = new BaseCompare(); 68 | bc.Compare(new List() { elo }, new List() { }, "FirstRun", "SecondRun"); 69 | 70 | var results = bc.Results; 71 | 72 | Assert.IsTrue(results[(RESULT_TYPE.LOG, CHANGE_TYPE.DELETED)].Any(x => x.Base is EventLogObject)); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /Tests/Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net5.0 4 | true 5 | false 6 | AsaTests 7 | 2.1-alpha 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | PreserveNewest 24 | 25 | 26 | PreserveNewest 27 | 28 | 29 | PreserveNewest 30 | 31 | 32 | PreserveNewest 33 | 34 | 35 | PreserveNewest 36 | 37 | 38 | PreserveNewest 39 | 40 | 41 | PreserveNewest 42 | 43 | 44 | PreserveNewest 45 | 46 | 47 | PreserveNewest 48 | 49 | 50 | PreserveNewest 51 | 52 | 53 | PreserveNewest 54 | 55 | 56 | 57 | 58 | 59 | all 60 | runtime; build; native; contentfiles; analyzers; buildtransitive 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /Tests/TpmSim.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Runtime.InteropServices; 3 | using System.Threading.Tasks; 4 | using Tpm2Lib; 5 | 6 | namespace Microsoft.CST.AttackSurfaceAnalyzer.Utils 7 | { 8 | public class TpmSim 9 | { 10 | public TpmSim(int Port = 2321) 11 | { 12 | this.Port = Port; 13 | } 14 | 15 | public int Port { get; } 16 | 17 | public static Process GetTpmSimulator() 18 | { 19 | return new Process() 20 | { 21 | StartInfo = new ProcessStartInfo 22 | { 23 | FileName = "TpmSim\\Simulator.exe", 24 | RedirectStandardOutput = true, 25 | RedirectStandardError = true, 26 | UseShellExecute = false, 27 | CreateNoWindow = true, 28 | WindowStyle = ProcessWindowStyle.Hidden 29 | } 30 | }; 31 | } 32 | 33 | [DllImport("Tpm")] 34 | public static extern int StartTcpServer(int port); 35 | 36 | public void Start() 37 | { 38 | Task.Run(() => StartTcpServer(Port)); 39 | } 40 | 41 | public void Stop() 42 | { 43 | TcpTpmDevice tpmDevice = new TcpTpmDevice("127.0.0.1", Port); 44 | 45 | if (tpmDevice is TcpTpmDevice) 46 | { 47 | tpmDevice.Connect(); 48 | tpmDevice.Close(); 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Tests/TpmSim/Simulator.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Tests/TpmSim/Simulator.exe -------------------------------------------------------------------------------- /Tests/TpmSim/concrt140d.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Tests/TpmSim/concrt140d.dll -------------------------------------------------------------------------------- /Tests/TpmSim/msvcp140_1d.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Tests/TpmSim/msvcp140_1d.dll -------------------------------------------------------------------------------- /Tests/TpmSim/msvcp140_2d.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Tests/TpmSim/msvcp140_2d.dll -------------------------------------------------------------------------------- /Tests/TpmSim/msvcp140d.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Tests/TpmSim/msvcp140d.dll -------------------------------------------------------------------------------- /Tests/TpmSim/tpm.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Tests/TpmSim/tpm.dll -------------------------------------------------------------------------------- /Tests/TpmSim/vccorlib140d.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Tests/TpmSim/vccorlib140d.dll -------------------------------------------------------------------------------- /Tests/TpmSim/vcruntime140d.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/Tests/TpmSim/vcruntime140d.dll -------------------------------------------------------------------------------- /Tools/Docker/AsaDetonatorLinux/Detonate.sh: -------------------------------------------------------------------------------- 1 | # Default timeout 30 minutes 2 | $Timeout = 1800 3 | 4 | cat /input/RunName | $RunName 5 | 6 | timeout --signal=SIGINT $Timeout /Asa/Asa collect -a --runid "$($RunName):BeforeInstall" --databasefilename "$($RunName).sqlite" 7 | timeout --signal=SIGINT $Timeout /input/Install.sh 8 | timeout --signal=SIGINT $Timeout /Asa/Asa collect -a --runid "$($RunName):AfterInstall" --databasefilename "$($RunName).sqlite" 9 | timeout --signal=SIGINT $Timeout /input/Uninstall.sh 10 | timeout --signal=SIGINT $Timeout /Asa/Asa collect -a --runid "$($RunName):AfterUninstall" --databasefilename "$($RunName).sqlite" 11 | timeout --signal=SIGINT $Timeout /Asa/Asa export-collect --firstrunid "$($RunName):BeforeInstall" --secondrunid "$($RunName):AfterInstall" --databasefilename "$($RunName).sqlite" --outputpath /output 12 | timeout --signal=SIGINT $Timeout /Asa/Asa export-collect --firstrunid "$($RunName):BeforeInstall" --secondrunid "$($RunName):AfterUninstall" --databasefilename "$($RunName).sqlite" --outputpath /output 13 | timeout --signal=SIGINT $Timeout /Asa/Asa export-collect --firstrunid "$($RunName):AfterInstall" --secondrunid "$($RunName):AfterUninstall" --databasefilename "$($RunName).sqlite" --outputpath /output -------------------------------------------------------------------------------- /Tools/Docker/AsaDetonatorLinux/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/mirror/docker/library/ubuntu:22.04 2 | 3 | COPY Detonate.sh /Detonate.sh 4 | 5 | COPY publish /asa 6 | 7 | RUN chmod +x /Asa/Asa 8 | 9 | RUN apt-get update && apt-get install -y \ 10 | coreutils \ 11 | iproute2 12 | 13 | ENTRYPOINT ["sh", "/Detonate.sh"] -------------------------------------------------------------------------------- /Tools/Docker/AsaDetonatorLinux/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | 3 | services: 4 | chocotester: 5 | container_name: AsaDetonator 6 | build: 7 | context: . 8 | dockerfile: Dockerfile 9 | volumes: 10 | - type: bind 11 | source: D:/output 12 | target: /output 13 | - type: bind 14 | source: D:/input 15 | target: /input -------------------------------------------------------------------------------- /Tools/Docker/AsaDetonatorWindows/Detonate.ps1: -------------------------------------------------------------------------------- 1 | # Default timeout 30 minutes 2 | $Timeout = 1800 3 | 4 | $RunName = Get-Content C:\input\RunName 5 | 6 | $ScriptBlock = { 7 | param($RunName) 8 | C:\Asa\Asa.exe collect - --runid "$($RunName):BeforeInstall" --databasefilename "$($RunName).sqlite" 9 | C:\input\Install.ps1 10 | C:\Asa\Asa.exe collect -a --runid "$($RunName):AfterInstall" --databasefilename "$($RunName).sqlite" 11 | C:\input\Uninstall.ps1 12 | C:\Asa\Asa.exe collect -a --runid "$($RunName):AfterUninstall" --databasefilename "$($RunName).sqlite" 13 | C:\Asa\Asa.exe export-collect --firstrunid "$($RunName):BeforeInstall" --secondrunid "$($RunName):AfterInstall" --databasefilename "$($RunName).sqlite" --outputpath C:\output 14 | C:\Asa\Asa.exe export-collect --firstrunid "$($RunName):BeforeInstall" --secondrunid "$($RunName):AfterUninstall" --databasefilename "$($RunName).sqlite" --outputpath C:\output 15 | C:\Asa\Asa.exe export-collect --firstrunid "$($RunName):AfterInstall" --secondrunid "$($RunName):AfterUninstall" --databasefilename "$($RunName).sqlite" --outputpath C:\output 16 | } 17 | 18 | Write-Host "Starting $RunName" 19 | $job = Start-Job -ScriptBlock $ScriptBlock -ArgumentList $RunName 20 | $jobTimer = [Diagnostics.Stopwatch]::StartNew() 21 | 22 | # Sleep a second to let the job get started 23 | Start-Sleep -Seconds 1 24 | 25 | # Sleep until finished or timeout 26 | while ($job.State -eq "Running" -and $jobTimer.Elapsed.TotalSeconds -le $Timeout) { 27 | Start-Sleep -Seconds 1 28 | $logEntry = Receive-Job $job 29 | if ($logEntry.length -gt 0){ 30 | foreach($line in $logEntry){ 31 | Write-Host $line 32 | } 33 | $logEntry | Out-File C:\logs\$RunName.log -Append 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /Tools/Docker/AsaDetonatorWindows/Dockerfile: -------------------------------------------------------------------------------- 1 | # escape=` 2 | FROM mcr.microsoft.com/windows:1903 3 | 4 | SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] 5 | RUN Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) 6 | 7 | COPY publish C:\asa 8 | 9 | COPY Detonate.ps1 C:\Detonate.ps1 10 | 11 | ENTRYPOINT ["powershell", "Set-ExecutionPolicy Bypass -Scope Process -Force; C:\\Detonate.ps1"] -------------------------------------------------------------------------------- /Tools/Docker/AsaDetonatorWindows/GetUniqueIdentitiesFromCollections.ps1: -------------------------------------------------------------------------------- 1 | $numJobs = 0 2 | $maxNumJobs = 12 3 | Get-ChildItem D:\output | %{ 4 | 5 | $ScriptBlock = { 6 | param($name) 7 | Get-Content $name.FullName | awk '/Identity.:/{ gsub(\",\",\"\"); gsub(\"\\\"\",\"\"); gsub(\" \",\"\"); sub(\"Identity:\",\"\"); print }' | Sort-Object -Unique | Out-File -FilePath "D:\parsing\${name}" 8 | } 9 | 10 | Write-Host "processing $_..." 11 | while($numJobs -ge $maxNumJobs){ 12 | Start-Sleep 1 13 | $numJobs = (Get-Job -state "Running" | Measure-Object).Count 14 | } 15 | Start-Job $ScriptBlock -ArgumentList $_ 16 | $numJobs = (Get-Job -state "Running" | Measure-Object).Count 17 | } -------------------------------------------------------------------------------- /Tools/Docker/AsaDetonatorWindows/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | 3 | services: 4 | chocotester: 5 | container_name: AsaDetonator 6 | build: 7 | context: . 8 | dockerfile: Dockerfile 9 | volumes: 10 | - type: bind 11 | source: D:/AsaDetonator/output 12 | target: C:/output 13 | - type: bind 14 | source: D:/AsaDetonator/input 15 | target: C:/input 16 | - type: bind 17 | source: D:/AsaDetonator/logs 18 | target: C:/logs -------------------------------------------------------------------------------- /Tools/scripts/GetUniqueFilePathCounts.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM 2 | (SELECT 3 | path, 4 | COUNT(1) AS 'num' 5 | FROM 6 | windows_files 7 | GROUP BY 8 | path) a 9 | WHERE CONVERT(INT, CONVERT(VARCHAR(12), a.num)) > 2 10 | ORDER BY a.num DESC -------------------------------------------------------------------------------- /Tools/scripts/GetUniqueRegkeyCounts.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM 2 | (SELECT 3 | regkey, 4 | COUNT(1) AS 'num' 5 | FROM 6 | REGISTRY 7 | GROUP BY 8 | regkey) a 9 | WHERE CONVERT(INT, CONVERT(VARCHAR(12), a.num)) > 2 10 | ORDER BY a.num DESC -------------------------------------------------------------------------------- /Tools/scripts/LinuxCronGather.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd ~/AsaCli/ 3 | 4 | ./AttackSurfaceAnalyzerCli collect -a 5 | ./AttackSurfaceAnalyzerCli export-collect --outputpath output --explodedoutput 6 | ./AttackSurfaceAnalyzerCli config --trim-to-latest 7 | 8 | cd output 9 | 10 | DIRS=$(ls -l | grep '^d' | rev | cut -d' ' -f1 | rev) 11 | for d in $DIRS 12 | do 13 | cd $d 14 | FILES=*_* 15 | for f in $FILES 16 | do 17 | if [ $(wc -l $f | cut -d' ' -f1) -gt "0" ]; then 18 | c=$(echo $f | cut -d'_' -f1) 19 | u=$(uname) 20 | c="$u_$c" 21 | p=$(cat ~/CREDENTIAL) 22 | u=$(cat ~/USER) 23 | echo "Adding $f's data to '$c' collection" 24 | mongoimport -h noise-mongodb.documents.azure.com:10255 --ssl -c $c -u $u -p $p --jsonArray $f 25 | fi 26 | done 27 | cd .. 28 | rm -rf $d 29 | echo "Deleting parsed directory $d" 30 | done -------------------------------------------------------------------------------- /Tools/scripts/WindowsGatherer.ps1: -------------------------------------------------------------------------------- 1 | $wd = pwd 2 | 3 | if (-not (Test-Path ~\stage) ){ 4 | New-Item -Path ~\stage -ItemType "directory" 5 | } 6 | if (-not (Test-Path ~\stage\output) ){ 7 | New-Item -Path ~\stage\output -ItemType "directory" 8 | } 9 | if (-not (Test-Path ~\stage\ingested) ){ 10 | New-Item -Path ~\stage\ingested -ItemType "directory" 11 | } 12 | cd ~\stage 13 | 14 | ~\AsaCli\res\AttackSurfaceAnalyzerCli.exe collect -a --no-filters --debug 15 | ~\AsaCli\res\AttackSurfaceAnalyzerCli.exe export-collect --outputpath output --explodedoutput 16 | ~\AsaCli\res\AttackSurfaceAnalyzerCli.exe config --trim-to-latest 17 | 18 | $p = Get-Content ~/CREDENTIAL.txt 19 | $u = Get-Content ~/USER.txt 20 | $c = "windows" 21 | 22 | 23 | $files = New-Object Collections.Generic.List[string] 24 | $registry = New-Object Collections.Generic.List[string] 25 | 26 | 27 | Get-ChildItem -Recurse -Directory output | ForEach-Object { 28 | $dir = $_.FullName 29 | Get-ChildItem -File -Filter files_* $dir | ForEach-Object{ 30 | if ( $(Get-Item $_.FullName).Length -lt 50000000 ){ 31 | if ( $(Get-Item $_.FullName).Length -gt 2){ 32 | Write-Host "Parsing $_" 33 | Get-Content $_.FullName | Select-String -SimpleMatch -Pattern "`"Path`"" | ForEach-Object{ 34 | $a = $_.Line.Split('`"')[3] 35 | $files.add($a) 36 | } 37 | } 38 | else{ 39 | Write-Host "Skipping $_. Empty file." 40 | } 41 | } 42 | else{ 43 | Write-Host "Skipping $_. Too large." 44 | } 45 | } 46 | 47 | Get-ChildItem -File -Filter registry_* $dir | ForEach-Object{ 48 | if ( $(Get-Item $_.FullName).Length -lt 50000000 ){ 49 | if ( $(Get-Item $_.FullName).Length -gt 2){ 50 | Write-Host "Parsing $_" 51 | Get-Content $_.FullName | Select-String -SimpleMatch -Pattern "`"Key`"" | ForEach-Object{ 52 | $a = $_.Line.Split('`"')[3] 53 | $registry.add($a) 54 | } 55 | } 56 | else{ 57 | Write-Host "Skipping $_. Empty file." 58 | } 59 | } 60 | else{ 61 | Write-Host "Skipping $_. Too large." 62 | } 63 | } 64 | 65 | $files = $files | sort -unique 66 | Add-Content ~\files.txt $files 67 | 68 | $registry = $registry | sort -unique 69 | Add-Content ~\registry.txt $registry 70 | 71 | if ($files.Count -gt 0){ 72 | C:\Program` Files\Microsoft` SQL` Server\Client` SDK\ODBC\110\Tools\Binn\bcp.exe windows_files in C:\users\noise\files.txt -S asa-noise-2.database.windows.net -d asa-noise -U $u -P $p -q -c -t 73 | } 74 | 75 | if ($registry.Count -gt 0){ 76 | C:\Program` Files\Microsoft` SQL` Server\Client` SDK\ODBC\110\Tools\Binn\bcp.exe registry in C:\users\noise\registry.txt -S asa-noise-2.database.windows.net -d asa-noise -U $u -P $p -q -c -t 77 | } 78 | 79 | $files=New-Object Collections.Generic.List[string] 80 | del C:\users\noise\files.txt 81 | 82 | $registry=New-Object Collections.Generic.List[string] 83 | del C:\users\noise\registry.txt 84 | 85 | Move-Item -Path $dir -Destination ~\stage\ingested\ 86 | } 87 | -------------------------------------------------------------------------------- /docfx/.gitignore: -------------------------------------------------------------------------------- 1 | ############### 2 | # folder # 3 | ############### 4 | /**/DROP/ 5 | /**/TEMP/ 6 | /**/packages/ 7 | /**/bin/ 8 | /**/obj/ 9 | _site 10 | obj -------------------------------------------------------------------------------- /docfx/api/.gitignore: -------------------------------------------------------------------------------- 1 | ############### 2 | # temp file # 3 | ############### 4 | *.yml 5 | .manifest 6 | -------------------------------------------------------------------------------- /docfx/api/index.md: -------------------------------------------------------------------------------- 1 | # Explore 2 | 3 | You can explore the Attack Surface Analyzer API using the navigation bar to the left. -------------------------------------------------------------------------------- /docfx/docfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": [ 3 | { 4 | "src": [ 5 | { 6 | "files": [ 7 | "Lib.csproj" 8 | ], 9 | "exclude": [ "**/bin/**", "**/obj/**" ], 10 | "src":"../Lib" 11 | } 12 | ], 13 | "dest": "api", 14 | "disableGitFeatures": false, 15 | "disableDefaultFilter": false 16 | } 17 | ], 18 | "build": { 19 | "content": [ 20 | { 21 | "files": [ 22 | "api/**.yml", 23 | "api/index.md" 24 | ] 25 | }, 26 | { 27 | "files": [ 28 | "articles/**.md", 29 | "articles/**/toc.yml", 30 | "toc.yml", 31 | "*.md" 32 | ] 33 | } 34 | ], 35 | "resource": [ 36 | { 37 | "files": [ 38 | "images/**" 39 | ] 40 | } 41 | ], 42 | "overwrite": [ 43 | { 44 | "files": [ 45 | "apidoc/**.md" 46 | ], 47 | "exclude": [ 48 | "obj/**", 49 | "_site/**" 50 | ] 51 | } 52 | ], 53 | "dest": "_site", 54 | "globalMetadataFiles": [], 55 | "fileMetadataFiles": [], 56 | "template": [ 57 | "default" 58 | ], 59 | "postProcessors": [], 60 | "markdownEngineName": "markdig", 61 | "noLangKeyword": false, 62 | "keepFileLink": false, 63 | "cleanupCacheHistory": false, 64 | "disableGitFeatures": false 65 | } 66 | } -------------------------------------------------------------------------------- /docfx/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Articles 2 | href: articles/ 3 | - name: Api Documentation 4 | href: api/ 5 | homepage: api/index.md 6 | -------------------------------------------------------------------------------- /icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/AttackSurfaceAnalyzer/6732415862c5f39533fdb0a68293c81c8564b270/icon-128.png -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", 3 | "version": "2.4-alpha", 4 | "publicReleaseRefSpec": [ 5 | "^refs/heads/main$", 6 | "^refs/heads/v\\d+(?:\\.\\d+)?$" 7 | ], 8 | "cloudBuild": { 9 | "buildNumber": { 10 | "enabled": true, 11 | "includeCommitId": { 12 | "when": "always" 13 | } 14 | } 15 | }, 16 | "release": { 17 | "branchName": "release/v{version}" 18 | } 19 | } 20 | --------------------------------------------------------------------------------