Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

COM Event System Loading New DLL

Back
Id02f6c2e5-219d-4426-a0bf-ad67abc63d53
RulenameCOM Event System Loading New DLL
DescriptionThis 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.
SeverityMedium
TacticsPrivilegeEscalation
TechniquesT1543
Required data connectorsSecurityEvents
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Detections/SecurityEvent/COMEventSystemLoadingNewDLL.yaml
Version1.0.4
Arm template02f6c2e5-219d-4426-a0bf-ad67abc63d53.json
Deploy To Azure
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])
severity: Medium
relevantTechniques:
- T1543
queryFrequency: 1d
kind: Scheduled
version: 1.0.4
metadata:
  support:
    tier: Community
  categories:
    domains:
    - Security - Others
  author:
    name: Shain
  source:
    kind: Community
triggerOperator: gt
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.'
queryPeriod: 1d
id: 02f6c2e5-219d-4426-a0bf-ad67abc63d53
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
tactics:
- PrivilegeEscalation
name: COM Event System Loading New DLL
triggerThreshold: 0
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/SecurityEvent/COMEventSystemLoadingNewDLL.yaml
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])  
requiredDataConnectors:
- dataTypes:
  - SecurityEvents
  connectorId: SecurityEvents
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "apiVersion": "2023-02-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",
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "PrivilegeEscalation"
        ],
        "techniques": [
          "T1543"
        ],
        "templateVersion": "1.0.4",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}