Detection rules › Kusto

Modification of Accessibility Features

Severity
medium
Time window
1h
Group by
CommandLine, Computer, CurrentDirectory, Description, EventID, Hashes, Image, OriginalFileName, ParentCommandLine, ParentImage, ParentProcessGuid, ParentUser, ProcessGuid, ProcessId, User
Author
Vasileios Paschalidis
Source
github.com/Azure/Azure-Sentinel

Adversaries may establish persistence and/or elevate privileges by executing malicious content triggered by accessibility features. Windows contains accessibility features that may be launched with a key combination before a user has logged in (ex: when the user is on the Windows logon screen). An adversary can modify the way these programs are launched to get a command prompt or backdoor without logging in to the system. Two common accessibility programs are C:\Windows\System32\sethc.exe, launched when the shift key is pressed five times and C:\Windows\System32\utilman.exe, launched when the Windows + U key combination is pressed. The sethc.exe program is often referred to as "sticky keys", and has been used by adversaries for unauthenticated access through a remote desktop login screen. [1] Ref: https://attack.mitre.org/techniques/T1546/008/

MITRE ATT&CK coverage

Event coverage

ProviderEventTitle
SysmonEvent ID 1Process creation

Rule body kusto

id: d714ef62-1a56-4779-804f-91c4158e528d
name: Modification of Accessibility Features
description: |
  'Adversaries may establish persistence and/or elevate privileges by executing malicious content triggered by accessibility features. Windows contains accessibility features that may be launched with a key combination before a user has logged in (ex: when the user is on the Windows logon screen). An adversary can modify the way these programs are launched to get a command prompt or backdoor without logging in to the system.
  Two common accessibility programs are C:\Windows\System32\sethc.exe, launched when the shift key is pressed five times and C:\Windows\System32\utilman.exe, launched when the Windows + U key combination is pressed. The sethc.exe program is often referred to as "sticky keys", and has been used by adversaries for unauthenticated access through a remote desktop login screen. [1]
  Ref: https://attack.mitre.org/techniques/T1546/008/'
severity: Medium
requiredDataConnectors:
  - connectorId: SecurityEvents
    dataTypes:
      - SecurityEvent
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Persistence
relevantTechniques:
  - T1546.008
query: |
  let ImagesList = dynamic (["sethc.exe","utilman.exe","osk.exe","Magnify.exe","Narrator.exe","DisplaySwitch.exe","AtBroker.exe"]); 
  let OriginalFileNameList = dynamic (["sethc.exe","utilman.exe","osk.exe","Magnify.exe","Narrator.exe","DisplaySwitch.exe","AtBroker.exe","SR.exe","utilman2.exe","ScreenMagnifier.exe"]); 
  Event
  | where EventLog == "Microsoft-Windows-Sysmon/Operational" and EventID==1
  | parse EventData with * 'ProcessId">' ProcessId "<" * 'Image">' Image "<" * 'OriginalFileName">' OriginalFileName "<" *
  | where Image has_any (ImagesList) and not (OriginalFileName has_any (OriginalFileNameList))
  | parse EventData with * 'ProcessGuid">' ProcessGuid "<" * 'Description">' Description "<" * 'CommandLine">' CommandLine "<" * 'CurrentDirectory">' CurrentDirectory "<" * 'User">' User "<" * 'LogonGuid">' LogonGuid "<" * 'Hashes">' Hashes "<" * 'ParentProcessGuid">' ParentProcessGuid "<" * 'ParentImage">' ParentImage "<" * 'ParentCommandLine">' ParentCommandLine "<" * 'ParentUser">' ParentUser "<" *
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by EventID, Computer, User, ParentImage, ParentProcessGuid, ParentCommandLine, ParentUser, Image, ProcessId, ProcessGuid, CommandLine, Description, OriginalFileName, CurrentDirectory, Hashes
  | extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
  | extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
  | extend AccountName = tostring(split(User, "\\")[1]), AccountNTDomain = tostring(split(User, "\\")[0])
  | extend ImageFileName = tostring(split(Image, "\\")[-1])
  | extend ImageDirectory = replace_string(Image, ImageFileName, "")
  | project-away DomainIndex
entityMappings:
  - entityType: Process
    fieldMappings:
      - identifier: CommandLine
        columnName: CommandLine
      - identifier: ProcessId
        columnName: ProcessId
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: Computer
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: HostNameDomain
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: User
      - identifier: Name
        columnName: AccountName
      - identifier: NTDomain
        columnName: AccountNTDomain
  - entityType: File
    fieldMappings:
      - identifier: Name
        columnName: ImageFileName
      - identifier: Directory
        columnName: ImageDirectory
version: 1.0.4
kind: Scheduled
metadata:
    source:
        kind: Community
    author:
        name: Vasileios Paschalidis
    support:
        tier: Community
    categories:
        domains: [ "Security - Others" ]

Stages and Predicates

Parameters

let ImagesList = dynamic (["sethc.exe","utilman.exe","osk.exe","Magnify.exe","Narrator.exe","DisplaySwitch.exe","AtBroker.exe"]);

Let binding: OriginalFileNameList

let OriginalFileNameList = dynamic (["sethc.exe","utilman.exe","osk.exe","Magnify.exe","Narrator.exe","DisplaySwitch.exe","AtBroker.exe","SR.exe","utilman2.exe","ScreenMagnifier.exe"]);

Stage 1: source

Event

Stage 2: where

| where EventLog == "Microsoft-Windows-Sysmon/Operational" and EventID==1

Stage 3: parse

| parse EventData with * 'ProcessId">' ProcessId "<" * 'Image">' Image "<" * 'OriginalFileName">' OriginalFileName "<" *

Stage 4: where

| where Image has_any (ImagesList) and not (OriginalFileName has_any (OriginalFileNameList))

References OriginalFileNameList (defined above).

Stage 5: parse

| parse EventData with * 'ProcessGuid">' ProcessGuid "<" * 'Description">' Description "<" * 'CommandLine">' CommandLine "<" * 'CurrentDirectory">' CurrentDirectory "<" * 'User">' User "<" * 'LogonGuid">' LogonGuid "<" * 'Hashes">' Hashes "<" * 'ParentProcessGuid">' ParentProcessGuid "<" * 'ParentImage">' ParentImage "<" * 'ParentCommandLine">' ParentCommandLine "<" * 'ParentUser">' ParentUser "<" *

Stage 6: summarize

| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by EventID, Computer, User, ParentImage, ParentProcessGuid, ParentCommandLine, ParentUser, Image, ProcessId, ProcessGuid, CommandLine, Description, OriginalFileName, CurrentDirectory, Hashes

Stage 7: extend (5 consecutive steps)

| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| extend AccountName = tostring(split(User, "\\")[1]), AccountNTDomain = tostring(split(User, "\\")[0])
| extend ImageFileName = tostring(split(Image, "\\")[-1])
| extend ImageDirectory = replace_string(Image, ImageFileName, "")

Stage 8: project-away

| project-away DomainIndex

Exclusions

Top-level NOT(...) conjuncts: predicates this rule actively suppresses.

FieldKindExcluded values
OriginalFileNamematchsethc.exe, utilman.exe, osk.exe, Magnify.exe, Narrator.exe, DisplaySwitch.exe, AtBroker.exe, SR.exe, utilman2.exe, ScreenMagnifier.exe

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.

FieldKindValues
EventIDeq
  • 1 transforms: cased corpus 237 (splunk 224, kusto 13)
EventLogeq
  • Microsoft-Windows-Sysmon/Operational transforms: cased corpus 10 (kusto 10)
Imagematch
  • AtBroker.exe
  • DisplaySwitch.exe
  • Magnify.exe
  • Narrator.exe
  • osk.exe
  • sethc.exe
  • utilman.exe

Output fields

Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.

FieldSource
CommandLinesummarize
Computersummarize
CurrentDirectorysummarize
Descriptionsummarize
EndTimesummarize
EventIDsummarize
Hashessummarize
Imagesummarize
OriginalFileNamesummarize
ParentCommandLinesummarize
ParentImagesummarize
ParentProcessGuidsummarize
ParentUsersummarize
ProcessGuidsummarize
ProcessIdsummarize
StartTimesummarize
Usersummarize
HostNameextend
HostNameDomainextend
AccountNTDomainextend
AccountNameextend
ImageFileNameextend
ImageDirectoryextend