Files
sigma-rules/hunting/windows/docs/detect_rare_dll_sideload_by_occurrence.md
T
Terrance DeJesus 70411664cf [Bug] Normalize Hunting Index Link Generation (#3872)
* normalizing hunting link generation

* replacing header

* adjusting quotes in f-strings

* added source file to metadata

* removed os dependency

* address bug in source file links

* reverting TOML loading

* change all List type hinting to list

* change all List type hinting to list

* fixed accented characters in queries

* reverted accent character removal; moved macos query and MD to macos folder
2024-07-10 11:01:59 -04:00

4.6 KiB

Rare DLL Side-Loading by Occurrence


Metadata

  • Author: Elastic
  • Description: This hunt identifies instances where a signed Windows process attempts to load an unsigned DLL from the same process folder. Matches are limited to a unique host with low library load occurrence. Adversaries may execute their own malicious payloads by side-loading malicious DLLs.
  • UUID: 34a7aadb-fb0f-45ea-9260-830f39c3343b
  • Integration: endpoint, windows
  • Language: [ES|QL]
  • Source File: Rare DLL Side-Loading by Occurrence

Query

from logs-endpoint.events.library-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.action == "load" and process.code_signature.status == "trusted" and dll.code_signature.status != "trusted" and dll.Ext.relative_file_creation_time <= 86400
| eval dll_folder = substring(dll.path, 1, length(dll.path) - (length(dll.name) + 1))
| eval process_folder = substring(process.executable, 1, length(process.executable) - (length(process.name) + 1))
| where process_folder is not null and dll_folder is not null and process_folder == dll_folder and process.name != dll.name
| eval dll_folder = replace(dll_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""), process_folder = replace(process_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval dll_folder = replace(dll_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\"), process_folder = replace(process_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\")
| stats host_count = count_distinct(host.id), total_count = count(*) by dll_folder, dll.name, process.name, dll.hash.sha256
/* total_count can be adjusted to higher or lower values depending on env */
| where host_count == 1 and total_count <= 10 | keep total_count, host_count, dll_folder, dll.name, process.name, dll.hash.sha256
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action == "Image loaded" and file.code_signature.status != "Valid" and
  not file.path rlike """[c-fC-F]:\\(Windows|windows|WINDOWS)\\(System32|SysWOW64|system32|syswow64)\\[a-zA-Z0-9_]+.dll"""
| eval dll_folder = substring(file.path, 1, length(file.path) - (length(file.name) + 1))
| eval process_folder = substring(process.executable, 1, length(process.executable) - (length(process.name) + 1))
| where process_folder is not null and dll_folder is not null and process_folder == dll_folder and file.name != process.name
/* paths normalization by removing random patterns */
| eval dll_folder = replace(dll_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""), process_folder = replace(process_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""), dll_folder = replace(dll_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\"), process_folder = replace(process_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\")
| stats host_count = count_distinct(host.id), total_count = count(*) by dll_folder, file.name, process.name, file.hash.sha256
/* total_count can be adjusted to higher or lower values depending on env */
| where host_count == 1 and total_count <= 10
| keep total_count, host_count, dll_folder, file.name, process.name, file.hash.sha256

Notes

  • This hunt has two optional queries, one for Elastic Defend data and another for Sysmon data.
  • Based on the returned results you can further investigate suspicious DLLs by sha256 and library path.
  • Paths like C:\\Users\\Public and C:\\ProgramData\\ are often observed in malware employing DLL side-loading.
  • Elastic Defned DLL Events include dll.Ext.relative_file_creation_time which help us limit the hunt to recently dropped DLLs.

MITRE ATT&CK Techniques

License

  • Elastic License v2