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
815 stars 193 forks source link

Add tab completion support for atomic techniques #67

Closed Karneades closed 2 years ago

Karneades commented 3 years ago

Improve usability by adding dynamic parameter support for atomic techniques. This allows tab completion support for the available techniques. Further improvement could be to use the display name of the technique instead of the ID and translate that later to the technique ID in the code.

The important part is the following - getting all the filenames from the path (either default or given by the user) and remove the extension.

-ValidateSet $(((gci $PathToAtomicsFolder\T*\* -Filter *.yaml).name) -replace "\.yaml","")

I don't use the framework much, so I'm thankful if someone could test if anything breaks due to the change. Parameter settings like pipeline support or the position are still ensured.

Use <tab> to jump through the techniques or use <ctrl-space> to list them.

# use a prefix and then tab complete to get all the available techniques and browse through them
PS> Invoke-AtomicTest -PathToAtomicsFolder .\atomic-red-team\atomics\ -AtomicTechnique T10<ctrl-space>
T1003      T1006      T1021.001  T1030      T1037.002  T1049      T1055      T1059.001  T1070      T1071.004  T1087.002
T1003.001  T1007      T1021.002  T1033      T1037.004  T1053.001  T1055.001  T1059.002  T1070.001  T1072      T1090.001
T1003.002  T1010      T1021.003  T1036      T1037.005  T1053.002  T1055.004  T1059.003  T1070.002  T1074.001  T1095
T1003.003  T1012      T1021.006  T1036.003  T1040      T1053.003  T1055.012  T1059.004  T1070.003  T1078.001  T1098
T1003.004  T1014      T1027      T1036.004  T1046      T1053.004  T1056.001  T1059.005  T1070.004  T1078.003  T1098.001
T1003.006  T1016      T1027.001  T1036.005  T1047      T1053.005  T1056.002  T1059.006  T1070.005  T1082      T1098.004
T1003.007  T1018      T1027.002  T1036.006  T1048      T1053.006  T1056.004  T1069.001  T1070.006  T1083
T1003.008  T1020      T1027.004  T1037.001  T1048.003  T1053.007  T1057      T1069.002  T1071.001  T1087.001

PS> Invoke-AtomicTest -PathToAtomicsFolder .\atomic-red-team\atomics\ -AtomicTechnique T1003<ctrl-space>
T1003      T1003.001  T1003.002  T1003.003  T1003.004  T1003.006  T1003.007  T1003.008  T1006      T1007

# use a prefix and then tab complete to browse through the available techniques
PS> Invoke-AtomicTest -PathToAtomicsFolder .\atomic-red-team\atomics\ -AtomicTechnique T100<tab>
PS> Invoke-AtomicTest -PathToAtomicsFolder .\atomic-red-team\atomics\ -AtomicTechnique T1003<tab>
PS> Invoke-AtomicTest -PathToAtomicsFolder .\atomic-red-team\atomics\ -AtomicTechnique T1003.001<tab>
...

If you directly give the technique without explicitly use the parameter name, tab completion is missing but the value is still checked against the validate set

# test with id at position 0 without parameter name
PS> Invoke-AtomicTest T1218.010 -PathToAtomicsFolder .\atomic-red-team\atomics\ -ShowDetailsBrief
PathToAtomicsFolder = ...

T1218.010-1 Regsvr32 local COM scriptlet execution
T1218.010-2 Regsvr32 remote COM scriptlet execution
T1218.010-3 Regsvr32 local DLL execution
T1218.010-4 Regsvr32 Registering Non DLL
T1218.010-5 Regsvr32 Silent DLL Install Call DllRegisterServer

# test with wrong technique id
PS> Invoke-AtomicTest T1218.019 -PathToAtomicsFolder .\atomic-red-team\atomics\ -ShowDetailsBrief
Invoke-AtomicTest : ...The argument "T1218.019" does not belong to the ValidateSet-Attribut "T1003;T1003.001;T1003.002;T1003.003;T1003.004;T1003.006;T1003.007;T1003.008;T
1006;T1007;T1010;T1012;T1014;T1016;T1018;T1020;T1021.001;T1021.002;T1021.003;T1021.006;T1027;T1027.001;T1027.002;T1027.004;T1030;T1033;T1036;T1036.003;T1036.004;T1036.005;..."
Karneades commented 3 years ago

If the PR is merged in the future, then the wiki can be updated to reflect the tab completion support.

clr2of8 commented 3 years ago

This seems amazing. I'll check it out but just wanted to let you know that I will be out on vacation for a couple weeks and won't be able to test until after that. I do have a question about if you can support an atomic technique of "All" which is something we currently allow. For example, Invoke-AtomicTest All -CheckPrereqs

Karneades commented 3 years ago

Oh, good point with the All value... right, this would fail currently because the file does (obviously) not exist... I will work on that now to get the "All" to the validate set.


Instead of just using the file listing, I add the All first and extend that list.

PS> $ValidateSetAtomics = @("All")
PS> $ValidateSetAtomics += $(((gci $PathToAtomicsFolder\T*\* -Filter *.yaml).name) -replace "\.yaml","")
PS> $ValidateSetAtomics
All
T1003
T1003.001
T1003.002
T1003.003
mgraeber-rc commented 3 years ago

Thanks for offering this, @Karneades! So that we can better understand the use case, can you let us know how you use this to help save you time? Thanks! For example, I'm thinking, do you use the tab completion to identify which ATT&CK Technique IDs you want to test? Do you use it tab-complete a parent ATT&CK Technique ID so that you can see what sub-techniques are available? In other words, do you use it more to save keystrokes on an technique ID you already know you want to execute or do you use it more to discover what techniques IDs are available?

Karneades commented 3 years ago

Yes, typing only some numbers and then tab complete or listing the available techniques. If it really helps is also for me unclear with the IDs currently. You already have to know the ID when using the command and then you can copy paste it. But if you type the number manually it helps quickly jump through the IDs. I saw a video from Red Canary yesterday, where I saw that someone typed the ID by hand and then thought adding that tap completion.

The speed gain with tab complete is obvisouly not very high here... so maybe it's unneeded code for what it provides :D That tab completion could be extended to allow using the display name (human readable) in the command which is then translated to the ID.

mgraeber-rc commented 3 years ago

Thanks for the explanation! I could see this being helpful for some but a concern I've always had with dynamic parameters is that they break PowerShell's ability to self-document with Get-Help. What looks like a happy middle ground where you'd be able to keep the original parameter while also supporting tab completion is with the Register-ArgumentCompleter cmdlet but that's only available in PowerShell Core. My personal workflow for learning any new cmdlet/function is to call Get-Help which is why I've always struggled with dynamic parameters since they break that. Thoughts?

Karneades commented 3 years ago

Yes, that missing self-documentation for get-help is an issue. It's a tradeoff between the functionality and the documentation. If the help outweighs the tab complete functionality, then I'm totally fine to close the PR.

The missing self-documentation could be compensated by adding further information to the Wiki and the files itself. Documentation for the dynamic parameter could be added to the DESCRIPTION or EXAMPLE section in the PS1 file and you generally already have a good documentation in the wiki and elsewhere about Invoke-AtomicRedTeam. Because the parameter is mandatory it will popup if someone is missing that.

In my other modules I use PlatyPS for generating the PS help files where I was able to include the dynamic parameter information in the description which is then displayed in get-help. This is disproportionately for the current case, I guess.

mgraeber-rc commented 3 years ago

Thanks for that additional context, @Karneades! Sorry for the late reply. I'd love to get @clr2of8's input on this. Thanks!

clr2of8 commented 2 years ago

I'm going to close this out for now, in favor of leaving the Get-Help functional, but we do appreciate all the time and effort invested and hope that you will continue to contribute in the future.