diff --git a/.github/workflows/lint-action.yml b/.github/workflows/lint-action.yml new file mode 100644 index 0000000..d2419ec --- /dev/null +++ b/.github/workflows/lint-action.yml @@ -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 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..80b2b9c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "atomic-red-team"] + path = atomic-red-team + url = https://github.com/redcanaryco/atomic-red-team.git diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..2ef4d5a --- /dev/null +++ b/action.yml @@ -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: Download atomics + shell: pwsh + run: | + $atomicsPath = if ($IsWindows) { 'C:\AtomicRedTeam\atomics' } else { "$env:HOME/AtomicRedTeam/atomics" } + if (-not (Test-Path $atomicsPath)) { + git submodule update --init --remote --single-branch atomic-red-team + New-Item -ItemType Directory -Path $atomicsPath + Copy-Item -Path './atomic-red-team/atomics' -Destination $atomicsPath -Recurse + Write-Output "::notice::Atomics have been downloaded" + } else { + Write-Output "::notice::Atomics folder already exists" + } + + - 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: | + $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' diff --git a/atomic-red-team b/atomic-red-team new file mode 160000 index 0000000..12afd8e --- /dev/null +++ b/atomic-red-team @@ -0,0 +1 @@ +Subproject commit 12afd8e372da603f93d5f3ba51477d6fcd7965dd diff --git a/koko.csv b/koko.csv new file mode 100644 index 0000000..2070279 --- /dev/null +++ b/koko.csv @@ -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 \ No newline at end of file