Detection rules › Elastic

Self Injection via AppDomain Manager Assembly

Time window
1m
Sequence by
process.entity_id
Source
github.com/elastic/protections-artifacts

Identifies an attempt to load a recently created and unsigned DLL file by a .NET application via an AppDomain Manager manifest followed by suspicious VirtualProtect call to modify the memory content of the loaded DLL. This may indicate an attempt to load a malicious module via DLL search order hijacking.

MITRE ATT&CK coverage

Rule body

[rule]
description = """
Identifies an attempt to load a recently created and unsigned DLL file by a .NET application via an AppDomain Manager
manifest followed by suspicious VirtualProtect call to modify the memory content of the loaded DLL. This may indicate an
attempt to load a malicious module via DLL search order hijacking.
"""
id = "50dd274c-651e-46aa-9485-768fa4939b93"
license = "Elastic License v2"
name = "Self Injection via AppDomain Manager Assembly"
os_list = ["windows"]
reference = [
    "https://www.rapid7.com/blog/post/2023/05/05/appdomain-manager-injection-new-techniques-for-red-teams/",
]
version = "1.0.3"

query = '''
sequence by process.entity_id with maxspan=1m
 [library where
  not dll.code_signature.status : "trusted" and not endswith~(dll.name, process.name) and
  user.id : ("S-1-5-21*", "S-1-12-*") and
  (dll.Ext.relative_file_creation_time <= 500 or 
   dll.Ext.relative_file_name_modify_time <= 500 or 
   (dll.Ext.device.product_id : ("Virtual DVD-ROM", "Virtual Disk","USB *") and not dll.path : "C:\\*")) and
  _arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info: "*clr.dll!ParseManifest*") and
  process.thread.Ext.call_stack_summary : "ntdll.dll|kernelbase.dll|clr.dll|mscorlib.ni.dll|clr.dll|mscoreei.dll|mscoree.dll|kernel32.dll|ntdll.dll" and 
   
   /* DLL loaded from the process.executable current directory */
  endswith~(substring(dll.path, 0, length(dll.path) - (length(dll.name) + 1)), substring(process.executable, 0, length(process.executable) - (length(process.name) + 1))) and 
  
  not process.executable : 
           ("?:\\Program Files\\*", 
            "?:\\Program Files (x86)\\*", 
            "?:\\Windows\\Explorer.exe", 
            "?:\\Windows\\SysWOW64\\*", 
            "?:\\Windows\\System32\\*", 
            "?:\\Windows\\splwow64.exe", 
            "?:\\Windows\\Microsoft.NET\\*") and
            
  not dll.path :
        ("?:\\Windows\\System32\\DriverStore\\FileRepository\\*", 
         "?:\\Windows\\SysWOW64\\DriverStore\\FileRepository\\*", 
         "?:\\Windows\\assembly\\NativeImages\\*",
         "?:\\windows\\WinSxS\\*",
         "?:\\windows\\system32\\*",
         "?:\\windows\\syswow64\\*",
         "?:\\Program Files\\*", 
         "?:\\Program Files (x86)\\*", 
         "?:\\Windows\\Microsoft.NET\\*")] as event0
 [api where process.Ext.api.name : "VirtualProtect" and process.Ext.api.parameters.size >= 10000 and 
  stringcontains~(process.Ext.api.metadata.target_address_path, event0.dll.path) and 
  process.Ext.api.parameters.protection : "RWX" and process.Ext.api.parameters.protection_old : "RCX" and 
  process.thread.Ext.call_stack_final_user_module.name : "Unbacked" and 
  process.thread.Ext.call_stack_final_user_module.protection_provenance : "clr.dll"]
'''

min_endpoint_version = "8.10.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 = "T1055"
name = "Process Injection"
reference = "https://attack.mitre.org/techniques/T1055/"

[[threat.technique]]
id = "T1574"
name = "Hijack Execution Flow"
reference = "https://attack.mitre.org/techniques/T1574/"
[[threat.technique.subtechnique]]
id = "T1574.001"
name = "DLL"
reference = "https://attack.mitre.org/techniques/T1574/001/"



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

[internal]
min_endpoint_version = "8.10.0"

Stages and Predicates

Ordered sequence: each step below must occur in order within 1m, correlated by process.entity_id.

Stage 1: library

[library where
  not dll.code_signature.status : "trusted" and not endswith~(dll.name, process.name) and
  user.id : ("S-1-5-21*", "S-1-12-*") and
  (dll.Ext.relative_file_creation_time <= 500 or
   dll.Ext.relative_file_name_modify_time <= 500 or
   (dll.Ext.device.product_id : ("Virtual DVD-ROM", "Virtual Disk","USB *") and not dll.path : "C:\\*")) and
  _arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info: "*clr.dll!ParseManifest*") and
  process.thread.Ext.call_stack_summary : "ntdll.dll|kernelbase.dll|clr.dll|mscorlib.ni.dll|clr.dll|mscoreei.dll|mscoree.dll|kernel32.dll|ntdll.dll" and
  endswith~(substring(dll.path, 0, length(dll.path) - (length(dll.name) + 1)), substring(process.executable, 0, length(process.executable) - (length(process.name) + 1))) and
  not process.executable :
           ("?:\\Program Files\\*",
            "?:\\Program Files (x86)\\*",
            "?:\\Windows\\Explorer.exe",
            "?:\\Windows\\SysWOW64\\*",
            "?:\\Windows\\System32\\*",
            "?:\\Windows\\splwow64.exe",
            "?:\\Windows\\Microsoft.NET\\*") and
  not dll.path :
        ("?:\\Windows\\System32\\DriverStore\\FileRepository\\*",
         "?:\\Windows\\SysWOW64\\DriverStore\\FileRepository\\*",
         "?:\\Windows\\assembly\\NativeImages\\*",
         "?:\\windows\\WinSxS\\*",
         "?:\\windows\\system32\\*",
         "?:\\windows\\syswow64\\*",
         "?:\\Program Files\\*",
         "?:\\Program Files (x86)\\*",
         "?:\\Windows\\Microsoft.NET\\*")] as event0

Stage 2: api

[api where process.Ext.api.name : "VirtualProtect" and process.Ext.api.parameters.size >= 10000 and 
  stringcontains~(process.Ext.api.metadata.target_address_path, event0.dll.path) and 
  process.Ext.api.parameters.protection : "RWX" and process.Ext.api.parameters.protection_old : "RCX" and 
  process.thread.Ext.call_stack_final_user_module.name : "Unbacked" and 
  process.thread.Ext.call_stack_final_user_module.protection_provenance : "clr.dll"]

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
dll.code_signature.statuseqtrustedexcludes:dll.code_signature.status field:"dll.code_signature.status" value:"trusted"
dll.nameends_withprocess.nameexcludes:dll.name field:"dll.name" value:"process.name"
dll.pathstarts_with?:\Windows\System32\DriverStore\FileRepository\, ?:\Windows\SysWOW64\DriverStore\FileRepository\, ?:\Windows\assembly\NativeImages\, ?:\windows\WinSxS\, ?:\windows\system32\, ?:\windows\syswow64\, ?:\Program Files\, ?:\Program Files (x86)\, ?:\Windows\Microsoft.NET\excludes:dll.path
process.executablewildcard?:\Program Files\*, ?:\Program Files (x86)\*, ?:\Windows\Explorer.exe, ?:\Windows\SysWOW64\*, ?:\Windows\System32\*, ?:\Windows\splwow64.exe, ?:\Windows\Microsoft.NET\*excludes:process.executable

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
dll.Ext.device.product_idwildcard
  • USB *
  • Virtual DVD-ROM corpus 5 (elastic 5)
  • Virtual Disk corpus 5 (elastic 5)
field:"dll.Ext.device.product_id" kind:wildcard
dll.Ext.relative_file_creation_timele
  • 500 transforms: number corpus 11 (elastic 11)
field:"dll.Ext.relative_file_creation_time" kind:le value:"500"
dll.Ext.relative_file_name_modify_timele
  • 500 transforms: number corpus 9 (elastic 9)
field:"dll.Ext.relative_file_name_modify_time" kind:le value:"500"
process.Ext.api.metadata.target_address_pathcontains
  • event0.dll.path (field reference)
field:"process.Ext.api.metadata.target_address_path" kind:contains value:"event0.dll.path"
process.Ext.api.namewildcard
  • VirtualProtect corpus 5 (elastic 5)
field:"process.Ext.api.name" kind:wildcard value:"VirtualProtect"
process.Ext.api.parameters.protectionwildcard
  • RWX corpus 4 (elastic 4)
field:"process.Ext.api.parameters.protection" kind:wildcard value:"RWX"
process.Ext.api.parameters.protection_oldwildcard
  • RCX
field:"process.Ext.api.parameters.protection_old" kind:wildcard value:"RCX"
process.Ext.api.parameters.sizege
  • 10000 transforms: number corpus 11 (elastic 11)
field:"process.Ext.api.parameters.size" kind:ge value:"10000"
process.thread.Ext.call_stack_final_user_module.namewildcard
  • Unbacked corpus 6 (elastic 6)
field:"process.thread.Ext.call_stack_final_user_module.name" kind:wildcard value:"Unbacked"
process.thread.Ext.call_stack_final_user_module.protection_provenancewildcard
  • clr.dll corpus 4 (elastic 4)
field:"process.thread.Ext.call_stack_final_user_module.protection_provenance" kind:wildcard value:"clr.dll"
process.thread.Ext.call_stack_summarywildcard
  • ntdll.dll|kernelbase.dll|clr.dll|mscorlib.ni.dll|clr.dll|mscoreei.dll|mscoree.dll|kernel32.dll|ntdll.dll
field:"process.thread.Ext.call_stack_summary" kind:wildcard value:"ntdll.dll|kernelbase.dll|clr.dll|mscorlib.ni.dll|clr.dll|mscoreei.dll|mscoree.dll|kernel32.dll|ntdll.dll"
user.idwildcard
  • S-1-12-* corpus 46 (elastic 46)
  • S-1-5-21* corpus 47 (elastic 47)
field:"user.id" kind:wildcard