Well, attackers have shifted their techniques and now use more PowerShell than before, and this allows them to do a lot of more and dangerous thing in our environments. In my opinion, this is because two main reasons, first PowerShell is on with every Windows machine by default and is difficult to block it without breaking some processes. Second, PowerShell Logging isn’t still enable in many environments.
In this blog, let’s review what domain policies are necessary to detect PowerShell abuse, how to do domain enumeration with PowerShell and how to review the generated events to detect enumeration.
Visibility over PowerShell
TLDR: enable Turn on Module Logging and Turn on PowerShell Transcription, as Mandiant recommends here: https://www.mandiant.com/resources/blog/greater-visibility
Maybe in the future we can get into the details of what are the consideration of using PowerShell Logging and Transcription, but for the purposes of this blog, lets just enable it. (Computer Configuration>Policies>Windows Components>Windows PowerShell)
Domain Enumeration and detection
On this first part, we are going to do use PowerView to automate the enumeration. This is a powerful tool and is easy to use, but it’s noisy because the way it loads on the PowerShell session. To start, let’s put the situation where the AV didn’t detect the script on disk, we can attempt to load it on the PowerShell, but we will find that it gets detected and stopped.
An advance threat actor will most likely make sure that he/she ha disable AV before executing this, but this shows you that there can be times we can just look for string like “malicious software”. Also, we can use the defender logs or the logs from your AV, these are one of the most important to detect malicious action on early stages or event on advance stages.
Event thought we can just disable the AV on this PowerShell session, we can just use some command to disable AMSI and allow us to run our script. We are overwriting the AMSI DLL on memory and with this are able to use the script.
One of the most common ways to detect this type of malicious behavior is realizing that the attacker will attempt to obfuscate their payloads. On this case, base64 was used, and it’s on this that we can detect and alert on. The string “FromBase64String” give us an idea of this obfuscation.
Well now that we loaded the module on our PowerShell session we could start to enumerate, but as we are looking into detecting we can start looking for interesting events. One of which is that the events known from where the script was loaded, you will have to know what is the normal path for script execution. If we know that our users execute PowerShell from C:/scripts, we can just detect on any other path that the script is running from. On this case the script was executed from the Downloads folder, which depending on your environment this can be suspicious.
Now other event we can see is that we have logs for the script blocks, this information is really useful. Many threat actors will change some function names, but many others will just use the same script from the internet, we can detect on this script block those names and use those to alert.
Let’s imagine that for some reason we weren’t able to catch the event of the script being loaded, we can attempt to detect its execution. If the functions names are the same as the script on the internet, our previous detection by function name will still work. In case those names changed, we have other events that can give use some clues.
One event that caught my attention and can help us to identify enumeration is the one that contained System.DirectoryServices. This module is a PowerShell module used on the back end of the script, this would be more difficult to change.
Other string we can also look for is the string DomainSearcher, same as the one before, we can look for it to alert and detect. This is also a difficult one to change and pretty sure this one and the DirectoryServices one are used in many other scripts that automate enumeration.
Conclusion
There are many functions inside PowerView, and we can continue to attempt to detect those as well. On next blogs, we will go and see what type of information the other functions give us and how we can use those to detect. Also, a final and interesting log that teases that we can detect on a higher and more reliable level.