Working with Dynamic Data and JSON in KQL.
The evidence was not missing.
It was hidden inside a JSON object.
One field contained dozens of values.
Agent Foskett knew the investigation depended on extracting the right one.
Lesson overview
Learn how to extract useful evidence from dynamic fields and JSON objects in Microsoft Defender XDR using KQL functions such as parse_json(), todynamic(), tostring(), toint() and mv-expand.
Why dynamic data matters
The dynamic data investigation workflow
Step 1 — Inspect the dynamic field
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
DeviceEvents
| where Timestamp > ago(24h)
| where isnotempty(AdditionalFields)
| project Timestamp,
DeviceName,
ActionType,
AdditionalFields
| take 20
Step 2 — Parse JSON with parse_json()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
DeviceEvents
| where Timestamp > ago(24h)
| where isnotempty(AdditionalFields)
| extend Details = parse_json(AdditionalFields)
| project Timestamp,
DeviceName,
ActionType,
Details
Step 3 — Extract specific properties
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
DeviceEvents
| where Timestamp > ago(24h)
| extend Details = parse_json(AdditionalFields)
| extend PolicyName = tostring(Details.PolicyName)
| extend RiskScore = toint(Details.RiskScore)
| project Timestamp,
DeviceName,
ActionType,
PolicyName,
RiskScore
| order by Timestamp desc
Step 4 — Use bracket notation for difficult property names
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
DeviceEvents
| where Timestamp > ago(24h)
| extend Details = parse_json(AdditionalFields)
| extend DetectionName = tostring(Details["Detection Name"])
| extend ThreatCategory = tostring(Details["Threat.Category"])
| project Timestamp,
DeviceName,
ActionType,
DetectionName,
ThreatCategory
Step 5 — Expand arrays with mv-expand
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
DeviceEvents
| where Timestamp > ago(24h)
| extend Details = parse_json(AdditionalFields)
| extend Indicators = Details.Indicators
| mv-expand Indicators
| extend IndicatorValue = tostring(Indicators.Value)
| extend IndicatorType = tostring(Indicators.Type)
| project Timestamp,
DeviceName,
ActionType,
IndicatorType,
IndicatorValue
Step 6 — Build a cleaner investigation output
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
DeviceEvents
| where Timestamp > ago(7d)
| where isnotempty(AdditionalFields)
| extend Details = parse_json(AdditionalFields)
| extend ExtractedUser = tostring(Details.UserName)
| extend ExtractedIp = tostring(Details.IpAddress)
| extend ExtractedProcess = tostring(Details.ProcessName)
| extend ExtractedResult = tostring(Details.Result)
| project Timestamp,
DeviceName,
ActionType,
ExtractedUser,
ExtractedIp,
ExtractedProcess,
ExtractedResult
| order by Timestamp desc
How to read dynamic evidence
Real-world investigation
Investigation checklist
Related Agent Foskett Academy lessons
Coming next
Final thought
Working with Dynamic Data and JSON in KQL
Agent Foskett Academy Lesson 93 teaches defenders how to work with dynamic data and JSON in KQL for Microsoft Defender XDR threat hunting.
Dynamic data and JSON in Microsoft Defender XDR
This lesson explains parse_json(), todynamic(), dot notation, bracket notation, tostring(), toint(), mv-expand, AdditionalFields and practical ways to extract hidden evidence from Microsoft Defender XDR telemetry.
