Detection rules › Elastic

API Call from a Suspicious Stack

Source
github.com/elastic/protections-artifacts

Identifies the call to some Windows APIs from an unusual call stack. This may be the result of an evasion attempt to hide the origin of the API call from the call stack such as unbacked memory region.

MITRE ATT&CK coverage

TacticTechniques
Stealth

Rule body

[rule]
description = """
Identifies the call to some Windows APIs from an unusual call stack. This may be the result of an evasion attempt to
hide the origin of the API call from the call stack such as unbacked memory region.
"""
id = "1089f634-35bd-4877-a638-01e42cb47ae2"
license = "Elastic License v2"
name = "API Call from a Suspicious Stack"
os_list = ["windows"]
reference = ["https://www.elastic.co/security-labs/doubling-down-etw-callstacks"]
version = "1.0.1"

query = '''
api where process.Ext.api.name in ("VirtualAlloc", "VirtualProtect", "WriteProcessMemory", "ResumeThread") and
  process.thread.Ext.call_stack_summary == "ntdll.dll|kernelbase.dll|kernel32.dll|ntdll.dll" and
  not _arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info like
                                                                                ("c:\\windows\\sys?????\\ntdll.dll!LdrLoadDll*",
                                                                                 "c:\\windows\\sys?????\\kernelbase.dll!LoadLibrary*",
                                                                                 "c:\\windows\\sys?????\\kernelbase.dll+0x*",
                                                                                 "c:\\windows\\sys?????\\ntdll.dll+0x*",
                                                                                 "c:\\windows\\sys?????\\kernelbase.dll!MsixIsSystemPackageByPackageFullName*"))
'''

min_endpoint_version = "8.10.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0

[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1055"
name = "Process Injection"
reference = "https://attack.mitre.org/techniques/T1055/"


[threat.tactic]
id = "TA0005"
name = "Defense Evasion"
reference = "https://attack.mitre.org/tactics/TA0005/"

[internal]
min_endpoint_version = "8.10.0"

Stages and Predicates

Stage 1: api

api where process.Ext.api.name in ("VirtualAlloc", "VirtualProtect", "WriteProcessMemory", "ResumeThread") and
  process.thread.Ext.call_stack_summary == "ntdll.dll|kernelbase.dll|kernel32.dll|ntdll.dll" and
  not _arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info like
                                                                                ("c:\\windows\\sys?????\\ntdll.dll!LdrLoadDll*",
                                                                                 "c:\\windows\\sys?????\\kernelbase.dll!LoadLibrary*",
                                                                                 "c:\\windows\\sys?????\\kernelbase.dll+0x*",
                                                                                 "c:\\windows\\sys?????\\ntdll.dll+0x*",
                                                                                 "c:\\windows\\sys?????\\kernelbase.dll!MsixIsSystemPackageByPackageFullName*"))

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
process.thread.Ext.call_stackarray_any(no value, null check)excludes:process.thread.Ext.call_stack

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
process.Ext.api.namein
  • ResumeThread
  • VirtualAlloc corpus 4 (elastic 4)
  • VirtualProtect corpus 19 (elastic 19)
  • WriteProcessMemory corpus 14 (elastic 14)
field:"process.Ext.api.name" kind:in
process.thread.Ext.call_stack_summaryeq
  • ntdll.dll|kernelbase.dll|kernel32.dll|ntdll.dll corpus 2 (elastic 2)
field:"process.thread.Ext.call_stack_summary" kind:eq value:"ntdll.dll|kernelbase.dll|kernel32.dll|ntdll.dll"