redcanaryco / invoke-atomicredteam

Invoke-AtomicRedTeam is a PowerShell module to execute tests as defined in the [atomics folder](https://github.com/redcanaryco/atomic-red-team/tree/master/atomics) of Red Canary's Atomic Red Team project.
MIT License
818 stars 194 forks source link

I would like be able to run multiple ART at once #39

Closed Scoubi closed 2 years ago

Scoubi commented 4 years ago

Right now we can either run 1 Techinique at a time or All the Techniques. There is no middle ground.

Here's a POC ps1 script that I put together that will loop for all provided Techniques and perform the following :

#Requires -RunAsAdministrator
# Quick and dirty script to get prerequisite and run ART tests

# Change the path to fit your installation
Import-Module "C:\AtomicRedTeam\invoke-atomicredteam\Invoke-AtomicRedTeam.psd1" -Force

# Change/Add all the tests you want to perform in the line below
# One day I might make this as arguments, but not tonight ;)
$ARTtests = "T1047 T1220 T1098 T1197" 
$ARTtests = $ARTtests.split(" ");
foreach ($ARTtest in $ARTtests) {
   Invoke-AtomicTest $ARTtest -GetPrereqs
   Invoke-AtomicTest $ARTtest
   pause
   Invoke-AtomicTest $ARTtest -Cleanup
}
mgraeber-rc commented 4 years ago

Thanks for the feedback, @Scoubi! What are your thoughts on whether you feel that PowerShell itself may be sufficient to write a script to automate multiple tests? Otherwise, if you feel it would be more appropriate to incorporate the ability to mix and match tests across multiple techniques in a single call to Invoke-AtomicTest, how might you envision the parameters being designed. Thanks in advance for the thoughtful response!

Scoubi commented 4 years ago

Hi Matt, Thanks for the quick reply.

In the end, it is not "important" how/where the feature is implemented. I would say, let's use the path of least resistance. The script I've put in the comment was spun from a discussion with @clr2of8 in ART's Slack. So it is a very simple wrapper that obviously needs some improvements. I think in the end what would be nice is to be able to specify either on the command line or through a file (or both?) the list of Techniques and Tests we want to perform in a specific order. This way, the tests could be used/breakdown by Tactics. A few Techniques belong to multiple Tactics so one might one to run only the tests for that Tactics at a given time and other tests from the same Technique later.

In this current project, PAUSE option (between execution and cleanup or next execution) in the script was very useful to let the security product owner look at artifacts generated by the test before going to the next test. Having a script (or file) with the test in a specific order ensure that we compare the various flavor of OS and the various Security Vendor in the exact same way.

Let me know if some parts are not clear or if you would like to go more in details

mgraeber-rc commented 4 years ago

Makes sense. Thanks for elaborating. Would a simple wrapper function like this suffice?

function Invoke-AtomicTechniqueSequence {
    param (
        [String[]]
        $AtomicTechnique
    )

    PROCESS {
        foreach ($Technique in $AtomicTechnique) {
            Invoke-AtomicTest -AtomicTechnique $Technique -GetPrereqs
            Invoke-AtomicTest -AtomicTechnique $Technique
            pause
            Invoke-AtomicTest -AtomicTechnique $Technique -Cleanup
        }
    }
}

If that's the style of abstraction you'd be looking for, that's the kind of thing that would make sense to me to have stand on its own versus incorporating it into the repo due. Thoughts?

Scoubi commented 4 years ago

It is OK for my current needs.

On the other hand, I seen a lot of requests about something similar on the ART's Slack. As such, I think it should be added to the repo and I'm not sure 100% of the users would find the "pause" convenient.

The ability to run only specific test for a technique might be useful for some people (myself included but wanted the easiest way to do it as my coding skills are non-existent). So if we could call it like this I think it would cover most scenario : Invoke-AtomicTechniqueSequence T1003 1 2, T1197, T1086.001 2, T1003 3 -pause -cleanup Where -pause & -cleanup are optional flags or
Invoke-AtomicTechniqueSequence mytest.txt -pause -cleanup

Where each line contains a Technique and Tests you want to execute

It would be perfect. But not sure how the script would handle the various naming convention of the Invoke-AtomicTest

mgraeber-rc commented 4 years ago

Thanks for the suggestions! I'm going to have to sit with this one for a bit as I still struggle with how we might incorporate that into Invoke-AtomicTest in a way that would be intuitive, not error-prone, and would serve to enhance functionality beyond what PowerShell already offers. Mind you my bias tends to be towards traditional PowerShell design principles of a function/cmdlet doing one thing and doing that one thing well. When the scope begins to creep in, that's a good time to consider building a new function/cmdlet.

mgraeber-rc commented 4 years ago

Hey @Scoubi. I put a little bit of thought into how to more easily define chaining multiple tests together and I prototyped this up. Would something like this be relatively intuitive to define multiple tests?

image

AtomicTest is a little helper function that just helps with more easily defining arguments to pass to Invoke-AtomicTest. I think this implementation would check both boxes from an ease of use perspective while also maintaining PowerShell best practices. Thoughts?

Scoubi commented 4 years ago

Hi Matt!

Sorry for the long delay, I was on vacations when you reply and it slipped my mind when I came back.

I was think of something that would preserve the same syntax as the original script for tests and subtest.

So for example Invoke-AtomicTest T1117 -TestNumbers 1,2
Invoke-AtomicTest T1117 -TestNames "Regsvr32 remote COM scriptlet execution","Regsvr32 local DLL execution"
Invoke-AtomicTest T1003 -TestGuids 5c2571d0-1572-416d-9676-812e64ca9f44,66fb0bc1-3c3f-47e9-a298-550ecfefacbc

All those syntax should all be working, but we should be able to chain them like so : Invoke-MultiTest T1117 -TestNumbers 1,2 | T1003 -TestGuids 5c2571d0-1572-416d-9676-812e64ca9f44,66fb0bc1-3c3f-47e9-a298-550ecfefacbc

So one solution that I will be doing on my end, is to change the script I posted originally to change the delimiter from " " to "|". I think that this would be the easiest way for me to be granular and respect the original syntax.

If this could be added directly into the Invoke-AtomicTest it would be even better. "|" might not be a suitable character in PowerShell and I would not mind changing it for any other that do make more sense like ";"

Of course, it should be possible to use the command line and not just a hard coded string in the script. But the hard coded string worked perfectly for my use case of ensuring the exact same tests were executed in the same order on multiple hosts (In my case: No-EDR, EDR Vendor1, EDR Vendor2)

What do you think?

clr2of8 commented 2 years ago

Our suggested solution is for users to chain commands together in a simple PowerShell script as shown in this example:

Invoke-AtomicTest T1016 -TestNumber 1

Sleep 3

Invoke-AtomicTest T1485 -TestNumber 1 -GetPrereqs
Invoke-AtomicTest T1485 -TestNumber 1

Sleep 3

$myArgs = @{ "port_file" = "c:\Users\art\Desktop\ports.txt" }
Invoke-AtomicTest T1016 -TestNumber 5 -InputArgs $myArgs
Invoke-AtomicTest T1016 -TestNumber 5 -Cleanup