Detection rules › Elastic
GetAsyncKeyState API Call from Suspicious Process
Identifies attempts to enumerate the state of keyboard keys by an unusual process. Adversaries may log user keystrokes to intercept credentials or other information from the user as the user types them.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Collection |
Rule body
[rule]
description = """
Identifies attempts to enumerate the state of keyboard keys by an unusual process. Adversaries may log user keystrokes
to intercept credentials or other information from the user as the user types them.
"""
id = "ef0a2322-641b-4127-8b48-2def55fe1f1f"
license = "Elastic License v2"
name = "GetAsyncKeyState API Call from Suspicious Process"
os_list = ["windows"]
reference = [
"https://attack.mitre.org/techniques/T1056/001/",
"https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getasynckeystate",
"https://www.elastic.co/security-labs/protecting-your-devices-from-information-theft-keylogger-protection",
]
version = "1.0.5"
query = '''
sequence by process.entity_id with maxspan=5m
[process where event.action == "start" and
(
(process.Ext.device.product_id : ("Virtual DVD-ROM", "Virtual Disk") and not process.executable : "C:\\*") or
(process.Ext.relative_file_creation_time <= 500 and (process.code_signature.trusted == false or process.code_signature.exists == false)) or
process.name in~ ("rundll32.exe", "regsvr32.exe", "powershell.exe", "wscript.exe", "cscript.exe", "mshta.exe") or
process.pe.original_file_name : ("python*.exe", "AutoIt*.exe") or
(process.Ext.relative_file_creation_time <= 500 and
process.executable :
("?:\\Users\\Public\\*",
"?:\\Users\\*\\Downloads\\*",
"?:\\Windows\\Temp\\*",
"?:\\Windows\\Tasks\\*",
"?:\\ProgramData\\*",
"?:\\Windows\\Microsoft.NET\\*")) or
process.executable : ("?:\\Users\\*\\AppData\\Local\\Temp\\7z*\\",
"?:\\Users\\*\\AppData\\Local\\Temp\\Rar$*\\*",
"?:\\Users\\*\\AppData\\Local\\Temp\\Temp?_*\\*",
"?:\\Users\\*\\AppData\\Local\\Temp\\BNZ.*") or
(process.parent.name : "svchost.exe" and process.parent.args : "Schedule")
) and
not process.executable :
("?:\\ProgramData\\Microsoft\\Windows Defender\\Platform\\*\\MsMpEng.exe",
"?:\\Program Files (x86)\\*.exe",
"?:\\Program Files\\*.exe") and
not (process.name : "rundll32.exe" and process.args : "C:\\Windows\\System32\\LogiLDA.dll,LogiFetch")
]
[api where process.Ext.api.name == "GetAsyncKeyState" and
process.Ext.api.metadata.background_callcount >= 400 and process.Ext.api.metadata.ms_since_last_keyevent >= 100 and
not (process.executable : "?:\\Windows\\System32\\rundll32.exe" and
process.command_line : "\"?:\\Windows\\System32\\rundll32.exe\" C:\\Windows\\System32\\LogiLDA.dll,LogiFetch" and
process.thread.Ext.call_stack_summary == "win32u.dll|winsrvext.dll|ntdll.dll")]
'''
min_endpoint_version = "8.12.0"
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[optional_actions]]
action = "rollback"
field = "process.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1056"
name = "Input Capture"
reference = "https://attack.mitre.org/techniques/T1056/"
[[threat.technique.subtechnique]]
id = "T1056.001"
name = "Keylogging"
reference = "https://attack.mitre.org/techniques/T1056/001/"
[threat.tactic]
id = "TA0009"
name = "Collection"
reference = "https://attack.mitre.org/tactics/TA0009/"
[internal]
min_endpoint_version = "8.12.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 5m, correlated by process.entity_id.
Stage 1: process
[process where event.action == "start" and
(
(process.Ext.device.product_id : ("Virtual DVD-ROM", "Virtual Disk") and not process.executable : "C:\\*") or
(process.Ext.relative_file_creation_time <= 500 and (process.code_signature.trusted == false or process.code_signature.exists == false)) or
process.name in~ ("rundll32.exe", "regsvr32.exe", "powershell.exe", "wscript.exe", "cscript.exe", "mshta.exe") or
process.pe.original_file_name : ("python*.exe", "AutoIt*.exe") or
(process.Ext.relative_file_creation_time <= 500 and
process.executable :
("?:\\Users\\Public\\*",
"?:\\Users\\*\\Downloads\\*",
"?:\\Windows\\Temp\\*",
"?:\\Windows\\Tasks\\*",
"?:\\ProgramData\\*",
"?:\\Windows\\Microsoft.NET\\*")) or
process.executable : ("?:\\Users\\*\\AppData\\Local\\Temp\\7z*\\",
"?:\\Users\\*\\AppData\\Local\\Temp\\Rar$*\\*",
"?:\\Users\\*\\AppData\\Local\\Temp\\Temp?_*\\*",
"?:\\Users\\*\\AppData\\Local\\Temp\\BNZ.*") or
(process.parent.name : "svchost.exe" and process.parent.args : "Schedule")
) and
not process.executable :
("?:\\ProgramData\\Microsoft\\Windows Defender\\Platform\\*\\MsMpEng.exe",
"?:\\Program Files (x86)\\*.exe",
"?:\\Program Files\\*.exe") and
not (process.name : "rundll32.exe" and process.args : "C:\\Windows\\System32\\LogiLDA.dll,LogiFetch")
]
Stage 2: api
[api where process.Ext.api.name == "GetAsyncKeyState" and
process.Ext.api.metadata.background_callcount >= 400 and process.Ext.api.metadata.ms_since_last_keyevent >= 100 and
not (process.executable : "?:\\Windows\\System32\\rundll32.exe" and
process.command_line : "\"?:\\Windows\\System32\\rundll32.exe\" C:\\Windows\\System32\\LogiLDA.dll,LogiFetch" and
process.thread.Ext.call_stack_summary == "win32u.dll|winsrvext.dll|ntdll.dll")]
Exclusions
The rule actively suppresses these predicates.
Indicators
These rows show field, operator, and value matches.