COM Event System Loading New DLL
Id | 02f6c2e5-219d-4426-a0bf-ad67abc63d53 |
Rulename | COM Event System Loading New DLL |
Description | This query uses Sysmon Image Load (Event ID 7) and Process Create (Event ID 1) data to look for COM Event System being used to load a newly seen DLL. |
Severity | Medium |
Tactics | PrivilegeEscalation |
Techniques | T1543 |
Required data connectors | SecurityEvents |
Kind | Scheduled |
Query frequency | 1d |
Query period | 1d |
Trigger threshold | 0 |
Trigger operator | gt |
Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Detections/SecurityEvent/COMEventSystemLoadingNewDLL.yaml |
Version | 1.0.4 |
Arm template | 02f6c2e5-219d-4426-a0bf-ad67abc63d53.json |
let lookback_start = 7d;
let lookback_end = 1d;
let timedelta = 5s;
// Get a list of previously seen DLLs being loaded
let known_dlls = (Event
| where TimeGenerated between(ago(lookback_start)..ago(lookback_end))
| where EventID == 7
| extend EvData = parse_xml(EventData)
| extend EventDetail = EvData.DataItem.EventData.Data
| extend LoadedItems = parse_json(tostring(parse_json(tostring(EvData.DataItem)).EventData)).["Data"]
| mv-expand LoadedItems
| where tostring(LoadedItems.["@Name"]) =~ "ImageLoaded"
| extend DLL = tostring(LoadedItems.["#text"])
| summarize by DLL);
// Get Image Load events related to svchost.exe
Event
| where Source =~ "Microsoft-Windows-Sysmon"
// Image Load Event in Sysmon
| where EventID == 7
| extend EvData = parse_xml(EventData)
| extend EventDetail = EvData.DataItem.EventData.Data
| extend Images = parse_json(tostring(parse_json(tostring(EvData.DataItem)).EventData)).["Data"]
| mv-expand Images
// Parse out executing process
| where tostring(Images.["@Name"]) =~ "Image"
| extend Image = tostring(Images.["#text"])
| where Image endswith "\\svchost.exe"
// Parse out loaded DLLs
| extend LoadedItems = parse_json(tostring(parse_json(tostring(EvData.DataItem)).EventData)).["Data"]
| mv-expand LoadedItems
| where tostring(LoadedItems.["@Name"]) =~ "ImageLoaded"
| extend DLL = tostring(LoadedItems.["#text"])
| extend Image = tostring(Image)
| extend ImageLoadTime = TimeGenerated
// Join with processes with a command line related to COM Event System
| join kind = inner(Event
| where Source =~ "Microsoft-Windows-Sysmon"
// Sysmon process execution events
| where EventID == 1
| extend RenderedDescription = tostring(split(RenderedDescription, ":")[0])
| extend EventData = parse_xml(EventData).DataItem.EventData.Data
| mv-expand bagexpansion=array EventData
| evaluate bag_unpack(EventData)
| extend Key = tostring(column_ifexists('@Name', "")), Value = column_ifexists('#text', "")
| evaluate pivot(Key, any(Value), TimeGenerated, Source, EventLog, Computer, EventLevel, EventLevelName, EventID, UserName, RenderedDescription, MG, ManagementGroupName, Type, _ResourceId)
| extend ParentImage = tostring(column_ifexists("ParentImage", "NotAvailable"))
// Command line related to COM Event System
| where ParentImage endswith "\\svchost.exe"
//| where ParentCommandLine has_all (" -k LocalService"," -p"," -s EventSystem")
| extend ProcessExecutionTime = TimeGenerated) on $left.Image == $right.ParentImage
// Check timespan between DLL load and process creation
| extend delta = ProcessExecutionTime - ImageLoadTime
| where ImageLoadTime <= ProcessExecutionTime and delta <= timedelta
// Filter to only newly seen DLLs
| where DLL !in (known_dlls)
| extend ParentCommandLine = tostring(column_ifexists("ParentCommandLine", "NotAvailable"))
| project-reorder ImageLoadTime, ProcessExecutionTime , Image, ParentCommandLine, DLL
| extend Hashes = tostring(column_ifexists("Hashes", "NotAvailable, NotAvailable"))
| extend Hashes = split(Hashes, ",")
| mv-apply Hashes on (summarize FileHashes = make_bag(pack(tostring(split(Hashes, "=")[0]), tostring(split(Hashes, "=")[1]))))
| extend SHA1 = tostring(FileHashes.SHA1)
| extend HashAlgo = "SHA1"
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| extend Name = tostring(split(UserName, "\\")[1]), NTDomain = tostring(split(UserName, "\\")[0])
relevantTechniques:
- T1543
name: COM Event System Loading New DLL
requiredDataConnectors:
- dataTypes:
- SecurityEvents
connectorId: SecurityEvents
entityMappings:
- fieldMappings:
- identifier: FullName
columnName: UserName
- identifier: Name
columnName: Name
- identifier: NTDomain
columnName: NTDomain
entityType: Account
- fieldMappings:
- identifier: FullName
columnName: Computer
- identifier: HostName
columnName: HostName
- identifier: DnsDomain
columnName: HostNameDomain
entityType: Host
- fieldMappings:
- identifier: Value
columnName: SHA1
- identifier: Algorithm
columnName: HashAlgo
entityType: FileHash
triggerThreshold: 0
id: 02f6c2e5-219d-4426-a0bf-ad67abc63d53
tactics:
- PrivilegeEscalation
version: 1.0.4
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/SecurityEvent/COMEventSystemLoadingNewDLL.yaml
queryPeriod: 1d
kind: Scheduled
metadata:
categories:
domains:
- Security - Others
author:
name: Shain
support:
tier: Community
source:
kind: Community
queryFrequency: 1d
severity: Medium
description: |
'This query uses Sysmon Image Load (Event ID 7) and Process Create (Event ID 1) data to look for COM Event System being used to load a newly seen DLL.'
query: |
let lookback_start = 7d;
let lookback_end = 1d;
let timedelta = 5s;
// Get a list of previously seen DLLs being loaded
let known_dlls = (Event
| where TimeGenerated between(ago(lookback_start)..ago(lookback_end))
| where EventID == 7
| extend EvData = parse_xml(EventData)
| extend EventDetail = EvData.DataItem.EventData.Data
| extend LoadedItems = parse_json(tostring(parse_json(tostring(EvData.DataItem)).EventData)).["Data"]
| mv-expand LoadedItems
| where tostring(LoadedItems.["@Name"]) =~ "ImageLoaded"
| extend DLL = tostring(LoadedItems.["#text"])
| summarize by DLL);
// Get Image Load events related to svchost.exe
Event
| where Source =~ "Microsoft-Windows-Sysmon"
// Image Load Event in Sysmon
| where EventID == 7
| extend EvData = parse_xml(EventData)
| extend EventDetail = EvData.DataItem.EventData.Data
| extend Images = parse_json(tostring(parse_json(tostring(EvData.DataItem)).EventData)).["Data"]
| mv-expand Images
// Parse out executing process
| where tostring(Images.["@Name"]) =~ "Image"
| extend Image = tostring(Images.["#text"])
| where Image endswith "\\svchost.exe"
// Parse out loaded DLLs
| extend LoadedItems = parse_json(tostring(parse_json(tostring(EvData.DataItem)).EventData)).["Data"]
| mv-expand LoadedItems
| where tostring(LoadedItems.["@Name"]) =~ "ImageLoaded"
| extend DLL = tostring(LoadedItems.["#text"])
| extend Image = tostring(Image)
| extend ImageLoadTime = TimeGenerated
// Join with processes with a command line related to COM Event System
| join kind = inner(Event
| where Source =~ "Microsoft-Windows-Sysmon"
// Sysmon process execution events
| where EventID == 1
| extend RenderedDescription = tostring(split(RenderedDescription, ":")[0])
| extend EventData = parse_xml(EventData).DataItem.EventData.Data
| mv-expand bagexpansion=array EventData
| evaluate bag_unpack(EventData)
| extend Key = tostring(column_ifexists('@Name', "")), Value = column_ifexists('#text', "")
| evaluate pivot(Key, any(Value), TimeGenerated, Source, EventLog, Computer, EventLevel, EventLevelName, EventID, UserName, RenderedDescription, MG, ManagementGroupName, Type, _ResourceId)
| extend ParentImage = tostring(column_ifexists("ParentImage", "NotAvailable"))
// Command line related to COM Event System
| where ParentImage endswith "\\svchost.exe"
//| where ParentCommandLine has_all (" -k LocalService"," -p"," -s EventSystem")
| extend ProcessExecutionTime = TimeGenerated) on $left.Image == $right.ParentImage
// Check timespan between DLL load and process creation
| extend delta = ProcessExecutionTime - ImageLoadTime
| where ImageLoadTime <= ProcessExecutionTime and delta <= timedelta
// Filter to only newly seen DLLs
| where DLL !in (known_dlls)
| extend ParentCommandLine = tostring(column_ifexists("ParentCommandLine", "NotAvailable"))
| project-reorder ImageLoadTime, ProcessExecutionTime , Image, ParentCommandLine, DLL
| extend Hashes = tostring(column_ifexists("Hashes", "NotAvailable, NotAvailable"))
| extend Hashes = split(Hashes, ",")
| mv-apply Hashes on (summarize FileHashes = make_bag(pack(tostring(split(Hashes, "=")[0]), tostring(split(Hashes, "=")[1]))))
| extend SHA1 = tostring(FileHashes.SHA1)
| extend HashAlgo = "SHA1"
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| extend Name = tostring(split(UserName, "\\")[1]), NTDomain = tostring(split(UserName, "\\")[0])
triggerOperator: gt
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspace": {
"type": "String"
}
},
"resources": [
{
"apiVersion": "2024-01-01-preview",
"id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/02f6c2e5-219d-4426-a0bf-ad67abc63d53')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/02f6c2e5-219d-4426-a0bf-ad67abc63d53')]",
"properties": {
"alertRuleTemplateName": "02f6c2e5-219d-4426-a0bf-ad67abc63d53",
"customDetails": null,
"description": "'This query uses Sysmon Image Load (Event ID 7) and Process Create (Event ID 1) data to look for COM Event System being used to load a newly seen DLL.'\n",
"displayName": "COM Event System Loading New DLL",
"enabled": true,
"entityMappings": [
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "UserName",
"identifier": "FullName"
},
{
"columnName": "Name",
"identifier": "Name"
},
{
"columnName": "NTDomain",
"identifier": "NTDomain"
}
]
},
{
"entityType": "Host",
"fieldMappings": [
{
"columnName": "Computer",
"identifier": "FullName"
},
{
"columnName": "HostName",
"identifier": "HostName"
},
{
"columnName": "HostNameDomain",
"identifier": "DnsDomain"
}
]
},
{
"entityType": "FileHash",
"fieldMappings": [
{
"columnName": "SHA1",
"identifier": "Value"
},
{
"columnName": "HashAlgo",
"identifier": "Algorithm"
}
]
}
],
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Detections/SecurityEvent/COMEventSystemLoadingNewDLL.yaml",
"query": "let lookback_start = 7d;\nlet lookback_end = 1d;\nlet timedelta = 5s;\n// Get a list of previously seen DLLs being loaded\nlet known_dlls = (Event\n| where TimeGenerated between(ago(lookback_start)..ago(lookback_end))\n| where EventID == 7\n| extend EvData = parse_xml(EventData)\n| extend EventDetail = EvData.DataItem.EventData.Data\n| extend LoadedItems = parse_json(tostring(parse_json(tostring(EvData.DataItem)).EventData)).[\"Data\"]\n| mv-expand LoadedItems\n| where tostring(LoadedItems.[\"@Name\"]) =~ \"ImageLoaded\"\n| extend DLL = tostring(LoadedItems.[\"#text\"])\n| summarize by DLL);\n// Get Image Load events related to svchost.exe\nEvent\n| where Source =~ \"Microsoft-Windows-Sysmon\"\n// Image Load Event in Sysmon\n| where EventID == 7\n| extend EvData = parse_xml(EventData)\n| extend EventDetail = EvData.DataItem.EventData.Data\n| extend Images = parse_json(tostring(parse_json(tostring(EvData.DataItem)).EventData)).[\"Data\"]\n| mv-expand Images\n// Parse out executing process\n| where tostring(Images.[\"@Name\"]) =~ \"Image\"\n| extend Image = tostring(Images.[\"#text\"])\n| where Image endswith \"\\\\svchost.exe\"\n// Parse out loaded DLLs\n| extend LoadedItems = parse_json(tostring(parse_json(tostring(EvData.DataItem)).EventData)).[\"Data\"]\n| mv-expand LoadedItems\n| where tostring(LoadedItems.[\"@Name\"]) =~ \"ImageLoaded\"\n| extend DLL = tostring(LoadedItems.[\"#text\"])\n| extend Image = tostring(Image)\n| extend ImageLoadTime = TimeGenerated\n// Join with processes with a command line related to COM Event System\n| join kind = inner(Event\n| where Source =~ \"Microsoft-Windows-Sysmon\"\n// Sysmon process execution events\n| where EventID == 1\n| extend RenderedDescription = tostring(split(RenderedDescription, \":\")[0])\n| extend EventData = parse_xml(EventData).DataItem.EventData.Data\n| mv-expand bagexpansion=array EventData\n| evaluate bag_unpack(EventData)\n| extend Key = tostring(column_ifexists('@Name', \"\")), Value = column_ifexists('#text', \"\")\n| evaluate pivot(Key, any(Value), TimeGenerated, Source, EventLog, Computer, EventLevel, EventLevelName, EventID, UserName, RenderedDescription, MG, ManagementGroupName, Type, _ResourceId)\n| extend ParentImage = tostring(column_ifexists(\"ParentImage\", \"NotAvailable\"))\n// Command line related to COM Event System\n| where ParentImage endswith \"\\\\svchost.exe\"\n//| where ParentCommandLine has_all (\" -k LocalService\",\" -p\",\" -s EventSystem\")\n| extend ProcessExecutionTime = TimeGenerated) on $left.Image == $right.ParentImage\n// Check timespan between DLL load and process creation\n| extend delta = ProcessExecutionTime - ImageLoadTime\n| where ImageLoadTime <= ProcessExecutionTime and delta <= timedelta\n// Filter to only newly seen DLLs\n| where DLL !in (known_dlls)\n| extend ParentCommandLine = tostring(column_ifexists(\"ParentCommandLine\", \"NotAvailable\"))\n| project-reorder ImageLoadTime, ProcessExecutionTime , Image, ParentCommandLine, DLL\n| extend Hashes = tostring(column_ifexists(\"Hashes\", \"NotAvailable, NotAvailable\"))\n| extend Hashes = split(Hashes, \",\")\n| mv-apply Hashes on (summarize FileHashes = make_bag(pack(tostring(split(Hashes, \"=\")[0]), tostring(split(Hashes, \"=\")[1]))))\n| extend SHA1 = tostring(FileHashes.SHA1)\n| extend HashAlgo = \"SHA1\"\n| extend HostName = tostring(split(Computer, \".\")[0]), DomainIndex = toint(indexof(Computer, '.'))\n| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)\n| extend Name = tostring(split(UserName, \"\\\\\")[1]), NTDomain = tostring(split(UserName, \"\\\\\")[0])\n",
"queryFrequency": "P1D",
"queryPeriod": "P1D",
"severity": "Medium",
"subTechniques": [],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"PrivilegeEscalation"
],
"techniques": [
"T1543"
],
"templateVersion": "1.0.4",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}