This week I have built a simple scenario for a customer PoC to demonstrate some EDR features of Microsoft Defender Advanced Threat Protection. The idea is to show in a simple to deploy and easy to understand scenario
- how threats can be detected with Advanced Hunting
- how custom detections can be turned into alerts
- how a custom detection can be extended by an action
- what is an investigation package and how to examine it
- how to initate a live response session and use PowerShell scripts to investigate and clean up
Step 1: Manipulate the client!
In my scenario someone has decided to use his local administrative privileges to create a local user and make him a member a member of the local group “Administrators”. This has been done by these good old commands:

Since this is often a legitimate task this is not prevented by any measure of Attack Surface Reduction and Defender AV does not intervene.
Actually it should not come so far of course. A user should have no admin rights on the client, the execution of macros or code from Office documents should be blocked by ASR Rules, but this is a nice demo case.
Step 2: Go hunting!
Since the system is protected by MDATP, we can trace this process very granular in the DeviceProcessEvents table in the advanced hunting area.
However, since this is a well-known annoyance (whether caused by attackers or users) there is already a good query in the persistence section of the community queries.

I’m not sure if this query has a different purpose than I have or is just buggy. In any case I had to make a small adjustment to make the query work for me. At the last condition CreatedOnLocalMachine must be true to find local accounts. My query was then:
DeviceProcessEvents
| where FileName in~ (“net.exe”, “net1.exe”) and Timestamp > ago(3d)
| parse kind=regex flags=iU ProcessCommandLine with * "user " CreatedUser " " * "/ad"
| where isnotempty(CreatedUser)
| where not (FileName =~ "net1.exe" and InitiatingProcessFileName =~ "net.exe" and replace("net", "net1", InitiatingProcessCommandLine) =~ ProcessCommandLine)
| extend CreatedOnLocalMachine=(ProcessCommandLine !contains "/do")
| where ProcessCommandLine !contains "/add" or (CreatedOnLocalMachine == 1 and ProcessCommandLine !contains "/domain")
| summarize MachineCount=dcount(DeviceName) by CreatedUser, CreatedOnLocalMachine, InitiatingProcessFileName, FileName, ProcessCommandLine, InitiatingProcessCommandLine
and this was my result:

In my opinion, Advanced Hunting is one of the strongest features of MDATP and will be even better when integrated with the ATP products in Microsoft Threat Protection. Furthermore Kusto Query Language is easy to learn and is also used e.g. in Log Analytics / Monitor and Sentinel.
Step 3: Generate an alert rule from your query!
Fortunately, it is now very easy to generate an alert from this query using the „Create detection rule“ button. For this to work, a query must at least display the following columns:
- Timestamp
- DeviceId
- ReportId
So we just append it to the last line of our query and have the following:
DeviceProcessEvents
| where FileName in~ ("net.exe", "net1.exe") and Timestamp > ago(3d)
| parse kind=regex flags=iU ProcessCommandLine with * "user " CreatedUser " " * "/ad"
| where isnotempty(CreatedUser)
| where not (FileName =~ "net1.exe" and InitiatingProcessFileName =~ "net.exe" and replace("net", "net1", InitiatingProcessCommandLine) =~ ProcessCommandLine)
| extend CreatedOnLocalMachine=(ProcessCommandLine !contains "/do")
| where ProcessCommandLine !contains "/add" or (CreatedOnLocalMachine == 1 and ProcessCommandLine !contains "/domain")
| summarize MachineCount=dcount(DeviceName) by CreatedUser, CreatedOnLocalMachine, InitiatingProcessFileName, FileName, ProcessCommandLine, InitiatingProcessCommandLine, Timestamp, DeviceId, ReportId
My new alert rule will
- immediately start running and then run every hour
- can be started manually (for tests/demos) in the Settings -> Custom Detections area.
- generate an alert with severity high (very useful for manipulating the device risk for other demonstrations)
- generate an incident (note the automatic generated Incident title)
- generate an investigation package

Custom detection rules make it possible to transform a one-time investigation into a continuous process and thus to learn and optimize it. However, since they can only be checked every hour at the most, they are not a means of fighting threats in „real time“.
Step 4: Examine the automatic collected investigation
Finding the download link for the investigation package generated by the detection rule is a bit tricky: You have to choose the Action center from the device page
Once downloaded the Investigation Package ZIP file can be examined. For our scenario, the folder „Users and Groups“ and the text files it contains are of particular interest.


The automatic generation of an Investigation Package is a feature of the response part of the EDR, which is non-invasive and gives us more information to fix the problem manually in the next step. In a production environment I would also use the response actions Run Antivirus scan and Initiate investigation to add Next Generation Protection and Automatic Investigation & Remediation features.
Step 5: Connect to the client!
Now it’s time to use the Live Response Session capabilities of MDATP to take a closer look and to clean up. For a Live Response Session the client connects periodically to the MDATP service and pulls jobs. So the session works through any NAT router or proxy (except SSL interception) but is a bit slow.
At first, the Live Response Session looks like a Remote PowerShell but you soon realize that this is not the case. There is a rather limited specialized set of commands available. Fortunately, it is possible to easily transport PowerShell scripts to the client and execute them.
For my demo scenario I have therefore created two very simple scripts:
- one that reads the group of local admins
- one that removes a given user from the group
To execute a Powershell script on a target system the feature must be enabled, the executing admin must have the appropriate rights and the script must either be signed or the execution of unsigned scripts must be allowed.
After adding the „Read“ script to the library and executing it with the RUN command, it is confirmed again that an unwanted user is local Admin. For executing the „Remove“ script we have to pass the username as a parameter.
Live-Response-Session
Step 6: Solving the incident
As a last step it is a good idea to solve the incident, because this will lower the device risk and in general it is a good idea to have an empty incident queue.
Some Sources:
- Investigation Packages:
- Live Response Session:
- Kusto Query Language