-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
276 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
name: Lint Atomic Red Team | ||
on: [push, pull_request] | ||
jobs: | ||
lint: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v2 | ||
|
||
- name: Lint Atomic Red Team | ||
uses: ./ | ||
with: | ||
cleanup: true | ||
remote: false | ||
adversary-emulation: true | ||
list-of-atomics: "./koko.csv" | ||
logging_module: File | ||
execution_log_path: "" | ||
technique: T1033 | ||
test-numbers: 2 |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[submodule "atomic-red-team"] | ||
path = atomic-red-team | ||
url = https://github.com/redcanaryco/atomic-red-team.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
name: 'Invoke-AtomicRedTeam Action' | ||
description: 'Run local Atomic Red Team tests and adversary emulation' | ||
author: 'smolse' | ||
|
||
inputs: | ||
technique: | ||
description: 'ID of the technique to execute' | ||
required: false | ||
test-names: | ||
description: 'Test names to execute' | ||
required: false | ||
test-numbers: | ||
description: 'Test numbers to execute' | ||
required: false | ||
test-guids: | ||
description: 'Test GUIDs to execute' | ||
required: false | ||
get-prereqs: | ||
description: 'Get prerequisites for tests execution' | ||
required: false | ||
default: 'true' | ||
cleanup: | ||
description: 'Clean up after tests execution' | ||
required: false | ||
default: 'true' | ||
adversary-emulation: | ||
description: 'Execute adversary emulation based on a schedule file' | ||
required: false | ||
default: 'false' | ||
list-of-atomics: | ||
description: 'Path to adversary emulation CSV schedule file' | ||
required: false | ||
private-config: | ||
description: 'Path to the private configuration file' | ||
required: false | ||
|
||
runs: | ||
using: 'composite' | ||
steps: | ||
|
||
- name: Validate action inputs | ||
shell: pwsh | ||
run: | | ||
Write-Output '${{ toJson(inputs) }}' | ||
if ('${{ inputs.adversary-emulation }}' -ne 'true' -and '${{ inputs.technique }}' -eq '') { | ||
Write-Output "::error::Technique ID must be provided for atomic test execution" | ||
exit 1 | ||
} | ||
if ('${{ inputs.adversary-emulation }}' -eq 'true' -and '${{ inputs.list-of-atomics }}' -eq '') { | ||
Write-Output "::error::List of atomics must be provided when adversary emulation is enabled" | ||
exit 1 | ||
} | ||
- name: Install Invoke-AtomicRedTeam | ||
shell: pwsh | ||
run: | | ||
if (-not (Get-Module -ListAvailable -Name Invoke-AtomicRedTeam)) { | ||
Install-Module -Name Invoke-AtomicRedTeam -Scope CurrentUser -Force | ||
Write-Output "::notice::Invoke-AtomicRedTeam has been installed" | ||
} else { | ||
Write-Output "::notice::Invoke-AtomicRedTeam is already installed" | ||
} | ||
- name: Install atomics folder | ||
shell: pwsh | ||
run: | | ||
$atomicsPath = if ($IsWindows) { 'C:\AtomicRedTeam\atomics' } else { "$env:HOME/AtomicRedTeam/atomics" } | ||
if (-not (Test-Path $atomicsPath)) { | ||
./scripts/Install-AtomicsFolder.ps1 | ||
Write-Output "::notice::Atomics folder has been installed" | ||
} else { | ||
Write-Output "::notice::Atomics folder already exists" | ||
} | ||
working-directory: ${{ github.action_path }} | ||
|
||
- name: Execute atomic technique | ||
if: inputs.adversary-emulation != 'true' | ||
shell: pwsh | ||
run: | | ||
$Params = @{} | ||
if ('${{ inputs.test-names }}' -ne '') { $Params.TestNames = '${{ inputs.test-names }}' } | ||
if ('${{ inputs.test-numbers }}' -ne '') { $Params.TestNumbers = '${{ inputs.test-numbers }}' } | ||
if ('${{ inputs.test-guids }}' -ne '') { $Params.TestGuids = '${{ inputs.test-guids }}' } | ||
if ('${{ inputs.get-prereqs }}' -eq 'true') { $Params.GetPrereqs = $true } | ||
if ('${{ inputs.cleanup }}' -eq 'true') { $Params.Cleanup = $true } | ||
Invoke-AtomicTest ${{ inputs.technique }} @Params | ||
- name: Execute adversary emulation | ||
if: inputs.adversary-emulation == 'true' | ||
shell: pwsh | ||
run: | | ||
ls -la ~ | ||
$Params = @{ | ||
ListOfAtomics = '${{ inputs.list-of-atomics }}' | ||
} | ||
if ('${{ inputs.get-prereqs }}' -eq 'true') { $Params.GetPrereqs = $true } | ||
if ('${{ inputs.cleanup }}' -eq 'true') { $Params.Cleanup = $true } | ||
Invoke-AtomicRunner @Params | ||
branding: | ||
icon: 'shield' | ||
color: 'blue' |
Submodule atomic-red-team
added at
12afd8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Order,Technique,TestName,auto_generated_guid,supported_platforms,TimeoutSeconds,InputArgs,AtomicsFolder,enabled,notes | ||
1,T1003.002,Scheduled task Local,42f53695-ad4a-4546-abb6-7d837f644a71,linux,120,,Public,TRUE,Emulation converted from https://github.com/Atomics-on-A-Friday/Emulation-Tools |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
function Install-AtomicsFolder { | ||
|
||
<# | ||
.SYNOPSIS | ||
This is a simple script to download the atttack definitions in the "atomics" folder of the Red Canary Atomic Red Team project. | ||
License: MIT License | ||
Required Dependencies: powershell-yaml | ||
Optional Dependencies: None | ||
.PARAMETER DownloadPath | ||
Specifies the desired path to download atomics zip archive to. | ||
.PARAMETER InstallPath | ||
Specifies the desired path for where to unzip the atomics folder. | ||
.PARAMETER Force | ||
Delete the existing atomics folder before installation if it exists. | ||
.EXAMPLE | ||
Install atomics folder | ||
PS> Install-AtomicsFolder.ps1 | ||
.NOTES | ||
Use the '-Verbose' option to print detailed information. | ||
#> | ||
[CmdletBinding()] | ||
Param( | ||
[Parameter(Mandatory = $False, Position = 0)] | ||
[string]$InstallPath = $( if ($IsLinux -or $IsMacOS) { $Env:HOME + "/AtomicRedTeam" } else { $env:HOMEDRIVE + "\AtomicRedTeam" }), | ||
|
||
[Parameter(Mandatory = $False, Position = 1)] | ||
[string]$DownloadPath = $InstallPath, | ||
|
||
[Parameter(Mandatory = $False, Position = 2)] | ||
[string]$RepoOwner = "redcanaryco", | ||
|
||
[Parameter(Mandatory = $False, Position = 3)] | ||
[string]$Branch = "master", | ||
|
||
[Parameter(Mandatory = $False)] | ||
[switch]$Force = $False, # delete the existing install directory and reinstall | ||
|
||
[Parameter(Mandatory = $False)] | ||
[switch]$NoPayloads = $False | ||
) | ||
Try { | ||
$InstallPathwAtomics = Join-Path $InstallPath "atomics" | ||
if ($Force -or -Not (Test-Path -Path $InstallPathwAtomics )) { | ||
write-verbose "Directory Creation" | ||
if ($Force) { | ||
Try { | ||
if ((Test-Path $InstallPathwAtomics) -and (-not $NoPayloads)) { Remove-Item -Path $InstallPathwAtomics -Recurse -Force -ErrorAction Stop | Out-Null } | ||
} | ||
Catch { | ||
Write-Host -ForegroundColor Red $_.Exception.Message | ||
return | ||
} | ||
} | ||
if (-not (Test-Path $InstallPath)) { New-Item -ItemType directory -Path $InstallPath | Out-Null } | ||
|
||
$url = "https://github.com/$RepoOwner/atomic-red-team/archive/$Branch.zip" | ||
$path = Join-Path $DownloadPath "$Branch.zip" | ||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 | ||
write-verbose "Beginning download of atomics folder from Github" | ||
|
||
# disable progress bar for faster performances | ||
$ProgressPreference_backup = $global:ProgressPreference | ||
$global:ProgressPreference = "SilentlyContinue" | ||
|
||
if ($NoPayloads) { | ||
# download zip to memory and only extract atomic yaml files | ||
# load ZIP methods | ||
Write-Host -ForegroundColor Yellow "Reading the Atomic Red Team repo into a memory stream. This could take up to 3 minutes." | ||
Add-Type -AssemblyName System.IO.Compression.FileSystem | ||
[System.Reflection.Assembly]::LoadWithPartialName('System.IO.Compression') | Out-Null | ||
|
||
# read github zip archive into memory | ||
$ms = New-Object IO.MemoryStream | ||
[Net.ServicePointManager]::SecurityProtocol = ([Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12) | ||
|
||
Add-Type -AssemblyName System.Net.Http | ||
$httpClient = New-Object System.Net.Http.HttpClient | ||
$httpClient.Timeout = New-Object System.TimeSpan(0, 3, 0) | ||
$response = $httpClient.GetAsync($url).Result | ||
$response.Content.CopyToAsync($ms).Wait() | ||
$zip = New-Object System.IO.Compression.ZipArchive($ms) | ||
|
||
$Filter = '*.yaml' | ||
|
||
# ensure the output folder exists | ||
$exists = Test-Path -Path $InstallPathwAtomics | ||
if ($exists -eq $false) { | ||
$null = New-Item -Path $InstallPathwAtomics -ItemType Directory -Force | ||
} | ||
|
||
# find all files in ZIP that match the filter (i.e. file extension) | ||
$zip.Entries | | ||
Where-Object { | ||
($_.FullName -like $Filter) ` | ||
-and (($_.FullName | split-path | split-path -Leaf) -eq [System.IO.Path]::GetFileNameWithoutExtension($_.Name)) ` | ||
-and ($_.FullName | split-path | split-path | split-path -Leaf) -eq "atomics" | ||
} | | ||
ForEach-Object { | ||
# extract the selected items from the ZIP archive | ||
# and copy them to the out folder | ||
$dstDir = Join-Path $InstallPathwAtomics ($_.FullName | split-path | split-path -Leaf) | ||
New-Item -ItemType Directory -Force -Path $dstDir | Out-Null | ||
[System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, (Join-Path $dstDir $_.Name), $true) | ||
} | ||
$zip.Dispose() | ||
} | ||
else { | ||
Invoke-WebRequest $url -OutFile $path | ||
|
||
write-verbose "Extracting ART to $InstallPath" | ||
$zipDest = Join-Path "$DownloadPath" "tmp" | ||
Microsoft.PowerShell.Archive\Expand-Archive -LiteralPath $path -DestinationPath "$zipDest" -Force:$Force | ||
$atomicsFolderUnzipped = Join-Path (Join-Path $zipDest "atomic-red-team-$Branch") "atomics" | ||
Move-Item $atomicsFolderUnzipped $InstallPath | ||
Remove-Item $zipDest -Recurse -Force | ||
Remove-Item $path | ||
} | ||
|
||
# restore progress bar preferences | ||
$global:ProgressPreference = $ProgressPreference_backup | ||
} | ||
else { | ||
Write-Host -ForegroundColor Yellow "An atomics folder already exists at $InstallPathwAtomics. No changes were made." | ||
Write-Host -ForegroundColor Cyan "Try the install again with the '-Force' parameter if you want to delete the existing installion and re-install." | ||
Write-Host -ForegroundColor Red "Warning: All files within the atomics folder ($InstallPathwAtomics) will be deleted when using the '-Force' parameter." | ||
} | ||
} | ||
Catch { | ||
Write-Error "Installation of the AtomicsFolder Failed." | ||
Write-Host $_.Exception.Message`n | ||
} | ||
} |