SC-200 · Domain 3: Perform threat hunting · 22% of the exam
Task 3.1: Detect threats by using Microsoft Defender XDR
Choosing advanced hunting tables, KQL and advanced hunting queries, threat analytics, hunting graphs and blast radius, and entity relationships in Sentinel graph.
Study it
Advanced hunting tables and KQL
Lesson coming
Threat analytics reports
Lesson coming
Hunting graph, blast radius and Sentinel graph
Lesson coming
Sample questions
Try each one before opening the answer. Every option is explained, with the Microsoft documentation page that proves it.
Question 1 · choose 1
You suspect an attacker on a workstation enumerated Domain Admins and service accounts by sending LDAP queries to domain controllers. Defender for Identity sensors run on all DCs. Which advanced hunting table records those queries?
AIdentityLogonEvents
BIdentityDirectoryEvents
CIdentityQueryEvents
DDeviceNetworkEvents
Show the answer and why
AIdentityLogonEvents
Incorrect
Directory queries aren't logon events, so they aren't recorded there.
BIdentityDirectoryEvents
Incorrect
It doesn't record queries against directory objects.
CIdentityQueryEvents
Correct
It holds queries against Active Directory objects such as users, groups and devices.
DDeviceNetworkEvents
Incorrect
It shows connections from the device, not the LDAP queries' content.
IdentityQueryEvents, populated by Defender for Identity, holds queries performed against Active Directory objects, including LDAP queries, so it's the table for hunting reconnaissance against domain controllers.
A hunter runs DeviceProcessEvents | where ProcessCommandLine has "psexec". It finds psexec.exe launches but misses runs of a renamed tool called RunPsExecHelper.exe. What explains the miss, and what finds both?
Ahas matches whole terms only; use contains to match the substring
Bhas is case sensitive; use =~ instead
CThe term is shorter than three characters; use has_cs
DProcessCommandLine isn't indexed; use search instead
Show the answer and why
Ahas matches whole terms only; use contains to match the substring
Correct
PsExec is inside the term RunPsExecHelper, so has doesn't match it.
Bhas is case sensitive; use =~ instead
Incorrect
has is case-insensitive, and =~ compares whole values.
CThe term is shorter than three characters; use has_cs
Incorrect
psexec is six characters, and has_cs is still term-based.
DProcessCommandLine isn't indexed; use search instead
Incorrect
String columns are indexed; the issue is term matching.
KQL breaks strings into maximal alphanumeric sequences (terms) and has matches whole terms. In RunPsExecHelper.exe, the terms are RunPsExecHelper and exe, so has "psexec" returns false while contains "psexec" returns true. has is faster, so use contains only when you need substrings.
DeviceInfo has many rows per device. You need one row per DeviceId with all columns from that device's most recent report, to check OS versions. Which query does that?
ADeviceInfo | summarize max(Timestamp) by DeviceId, OSVersion
BDeviceInfo | summarize arg_max(Timestamp, *) by DeviceId
CDeviceInfo | top 1 by Timestamp
DDeviceInfo | distinct DeviceId, OSVersion
Show the answer and why
ADeviceInfo | summarize max(Timestamp) by DeviceId, OSVersion
Incorrect
It returns the latest time per device and OS pair, not the latest full row.
BDeviceInfo | summarize arg_max(Timestamp, *) by DeviceId
Correct
arg_max returns the row with the highest Timestamp per device, with all its columns.
CDeviceInfo | top 1 by Timestamp
Incorrect
It returns a single row for the whole table.
DDeviceInfo | distinct DeviceId, OSVersion
Incorrect
It lists combinations without telling which is current.
arg_max(ExprToMaximize, *) finds the row that maximizes the expression in each group and returns the requested columns; with * it returns all of them.
You join EmailAttachmentInfo (left) to DeviceFileEvents on SHA256 to see every recipient whose device saved a malicious attachment. Three users got the file, but the results show only one recipient per hash. What do you change?
APut DeviceFileEvents on the left side of the join
BUse kind=leftsemi so all recipients are returned
CAdd a time window filter before the join
DSpecify kind=inner in the join
Show the answer and why
APut DeviceFileEvents on the left side of the join
Incorrect
Swapping sides changes which table is deduplicated, not the behavior.
BUse kind=leftsemi so all recipients are returned
Incorrect
leftsemi returns left rows that have a match, without the right table's columns.
CAdd a time window filter before the join
Incorrect
Filtering helps performance but doesn't restore deduplicated rows.
DSpecify kind=inner in the join
Correct
The default innerunique flavor keeps one left row per key; inner keeps them all.
The default join flavor, innerunique, deduplicates rows in the left table by the join key before matching, leaving a single random row per key. Specifying kind=inner returns all left rows with matching values.
You need to list every message that zero-hour auto purge moved out of a mailbox after delivery last week, with the action taken. Which advanced hunting table do you query?
AEmailEvents
BUrlClickEvents
CEmailPostDeliveryEvents
DCloudAppEvents
Show the answer and why
AEmailEvents
Incorrect
It records delivery-time events, not actions taken after delivery.
BUrlClickEvents
Incorrect
It doesn't record mailbox actions taken after delivery.
CEmailPostDeliveryEvents
Correct
It holds security events after delivery, such as ZAP actions.
DCloudAppEvents
Incorrect
It holds activities in cloud apps, not email post-delivery actions.
EmailPostDeliveryEvents contains information about security events that occur after delivery, when Microsoft 365 has delivered the message to the recipient mailbox, including zero-hour auto purge actions.
During an incident you need to know whether a compromised laptop has any path, through users, permissions or other devices, to a specific production database server. You want an interactive graph, not a hand-written query. Which hunting graph scenario do you start with?
APaths between two entities
BEntity relationship map
CCritical identities with storage access
DAccess to Azure DevOps repositories
Show the answer and why
APaths between two entities
Correct
It takes a start and a target and shows the paths between them.
BEntity relationship map
Incorrect
It shows the direct connections of one entity, not paths to a target.
CCritical identities with storage access
Incorrect
It finds privileged users with storage access, without a starting device.
DAccess to Azure DevOps repositories
Incorrect
It maps who can read or write an ADO repository.
The hunting graph in advanced hunting offers predefined scenarios. Paths between two entities takes a start and target and shows whether a path leads from one to the other, which is the lateral movement question asked here.
On a Windows device, you found one malicious powershell.exe instance in DeviceProcessEvents and need every child process that this exact instance started in the last 12 hours. Process IDs on the device are reused. Which two matching approaches return only that instance's children? (Choose TWO.)
AMatch the children's InitiatingProcessId to the parent's ProcessId
BMatch the children's InitiatingProcessFileName to powershell.exe
CMatch the children's InitiatingProcessUniqueId to the parent's ProcessUniqueId
DMatch the children's InitiatingProcessCommandLine to the parent's command line
EMatch DeviceId plus the initiating process ID and creation time to the parent's
Show the answer and why
AMatch the children's InitiatingProcessId to the parent's ProcessId
Incorrect
Process IDs are recycled, so this mixes in children of other processes that had the same ID.
BMatch the children's InitiatingProcessFileName to powershell.exe
Incorrect
Every PowerShell instance on the device has that file name.
CMatch the children's InitiatingProcessUniqueId to the parent's ProcessUniqueId
Correct
On Windows, ProcessUniqueId identifies one process instance and links a parent to its children directly.
DMatch the children's InitiatingProcessCommandLine to the parent's command line
Incorrect
A command line isn't unique: other instances can run with the same one.
EMatch DeviceId plus the initiating process ID and creation time to the parent's
Correct
A process ID together with its creation time and the device identifies one process instance.
Windows reuses process IDs, so a PID alone can't identify a process. Combining the process ID with the process creation time and the device ID identifies a single instance, and on Windows the ProcessUniqueId and InitiatingProcessUniqueId columns do the same more directly: match each child's InitiatingProcessUniqueId to the parent's ProcessUniqueId. File names and command lines are shared by every instance of the same program.
You want to find devices where a new value was added under a registry Run key in the past week. Which advanced hunting table do you query?
ADeviceRegistryEvents
BDeviceFileEvents
CDeviceInfo
DIdentityDirectoryEvents
Show the answer and why
ADeviceRegistryEvents
Correct
It records the creation and modification of registry entries.
BDeviceFileEvents
Incorrect
It records file creation and modification.
CDeviceInfo
Incorrect
It holds device information such as the OS version.
DIdentityDirectoryEvents
Incorrect
It doesn't record registry changes on workstations.
DeviceRegistryEvents contains information about the creation and modification of registry entries, which makes it the table for hunting persistence through Run keys.
Which filter limits an advanced hunting query to events from the last seven days?
A| take 7d
B| where Timestamp between (7d)
C| summarize by bin(Timestamp, 7d)
D| where Timestamp > ago(7d)
Show the answer and why
A| take 7d
Incorrect
take returns a number of rows, not a time range.
B| where Timestamp between (7d)
Incorrect
between needs a start and an end value.
C| summarize by bin(Timestamp, 7d)
Incorrect
bin groups values into buckets; it doesn't filter.
D| where Timestamp > ago(7d)
Correct
ago(7d) returns the time seven days before now.
ago() subtracts a timespan from the current UTC time, so where Timestamp > ago(7d) keeps the last seven days. Filtering on time early also improves query performance.
A threat analytics report covers a ransomware group that exploits a known vulnerability. In which section of the report do you see how many of your devices are exposed to it?
AAnalyst report
BEndpoints exposure
CRelated incidents
DAliases
Show the answer and why
AAnalyst report
Incorrect
It's the detailed write-up from Microsoft's researchers.
BEndpoints exposure
Correct
It shows your devices' exposure to the threat.
CRelated incidents
Incorrect
It lists incidents linked to the threat.
DAliases
Incorrect
Aliases list other vendors' names for the threat.
Each threat analytics report has sections for Overview, Analyst report, Related incidents, Impacted assets, Endpoints exposure, Recommended actions and Indicators (preview). Endpoints exposure shows how your devices are exposed to the threat.
You want to find accounts that signed in to more than 20 different devices today, from DeviceLogonEvents. Which aggregation counts the distinct devices per account?
Asummarize count() by AccountName
Bsummarize make_list(DeviceId) by AccountName
Csummarize dcount(DeviceId) by AccountName
Dsummarize arg_max(Timestamp, DeviceId) by AccountName
Show the answer and why
Asummarize count() by AccountName
Incorrect
count() counts sign-in events, not distinct devices.
Bsummarize make_list(DeviceId) by AccountName
Incorrect
make_list returns the device IDs as an array, not a count.
Csummarize dcount(DeviceId) by AccountName
Correct
dcount estimates the number of distinct values per group.
Dsummarize arg_max(Timestamp, DeviceId) by AccountName
Incorrect
It doesn't count devices.
dcount() estimates the number of distinct values in each summary group, so dcount(DeviceId) by AccountName counts devices per account; add a where clause on the result to keep accounts above 20.