feat: MeshSafe 文件摆渡安全卫士 v1.0 初始提交
核心功能: - 6 层检测管线: L0 结构分析 → L1 ClamAV → L2 文档深度检测 → L3 关键词匹配 → L4 YARA → L5 PE/二进制 - FastAPI + PostgreSQL + Redis + Docker Compose 架构 - 客户端 HMAC-SHA256 签名鉴权 + 限流 + 幂等性 - 控制台 UI (登录/Dashboard/诊断中心/策略管理/任务列表/测试中心/产品介绍页) - 三层诊断定时器 (error_scan 30s / db_aggregate 30s / container_check 5min) 并发与稳定性修复: - 诊断定时器 Redis 时间槽位锁 (多 worker 同一槽位只有一个执行) - JSONL 存储 fcntl 跨进程排他锁 + 容错解码 + 原子重写 - 移除 SQLite fallback, 统一 PostgreSQL - API_CLIENTS 脱敏为环境变量, .env 已 .gitignore
This commit is contained in:
307
rules/linux.yar
Normal file
307
rules/linux.yar
Normal file
@@ -0,0 +1,307 @@
|
||||
// =============================================================================
|
||||
// MeshSafe L2B YARA 规则集 —— Linux / 跨平台后门专项(C7)
|
||||
// =============================================================================
|
||||
//
|
||||
// 设计原则:
|
||||
// - 光闸摆渡场景,所有规则 2-3 特征组合命中,避免单一关键词误伤合法 Shell/Python 代码
|
||||
// - 覆盖范围:反弹 Shell、持久化(crontab/authorized_keys/systemd/LD_PRELOAD)、
|
||||
// Rootkit 特征、挖矿通用特征
|
||||
// - 命中后作为 finding 交给 PolicyEngine 权重累加
|
||||
//
|
||||
// 维护:
|
||||
// - 新后门工具/家族出现时优先补充 "工具名 + 持久化手段" 组合
|
||||
// =============================================================================
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C7-1 反弹 Shell(多种语言实现)
|
||||
// =============================================================================
|
||||
|
||||
rule C7_Linux_ReverseShell_Bash {
|
||||
meta:
|
||||
risk_level = "critical"
|
||||
category = "C7"
|
||||
false_positive_rate = "low"
|
||||
reference = "MITRE ATT&CK T1059.004 Bash"
|
||||
description = "Bash 反弹 Shell 组合:/dev/tcp + bash -i 或 sh -c"
|
||||
strings:
|
||||
$devtcp = /\/dev\/tcp\/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{2,5}/ ascii
|
||||
$bash_i = "bash -i" ascii
|
||||
$sh_c = /sh\s+-c\s+['"]bash -i/ ascii
|
||||
$exec3 = "exec 3<>/dev/tcp/" ascii
|
||||
$exec4 = "exec 4>&0 0>&1 1>&4" ascii
|
||||
condition:
|
||||
// /dev/tcp/IP:PORT + bash -i 这两个必须同时出现
|
||||
$devtcp and ($bash_i or $sh_c or $exec3)
|
||||
or
|
||||
// exec fd 重定向链
|
||||
$exec3 and $exec4
|
||||
}
|
||||
|
||||
rule C7_Linux_ReverseShell_NC {
|
||||
meta:
|
||||
risk_level = "critical"
|
||||
category = "C7"
|
||||
false_positive_rate = "medium"
|
||||
reference = "MITRE ATT&CK T1059.004 Netcat"
|
||||
description = "nc/ncat 反弹 Shell:-e/-c 参数指定 bash 或 sh"
|
||||
strings:
|
||||
$nc1 = /nc\s+[\w.-]+\s+\d{2,5}\s+-e\s+(\/bin\/(ba)?sh|bash|sh)/ ascii
|
||||
$nc2 = /ncat\s+[\w.-]+\s+\d{2,5}\s+-e\s+(\/bin\/(ba)?sh|bash|sh)/ ascii
|
||||
$nc3 = /nc\s+[\w.-]+\s+\d{2,5}\s+-c\s+(\/bin\/(ba)?sh|bash|sh)/ ascii
|
||||
$nc4 = /netcat\s+[\w.-]+\s+\d{2,5}\s+-e/ ascii
|
||||
$mkfifo = /mkfifo\s+\/tmp\/\w+;\s*(nc|ncat)\s+/ ascii
|
||||
condition:
|
||||
any of ($*)
|
||||
}
|
||||
|
||||
rule C7_Linux_ReverseShell_Python {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C7"
|
||||
false_positive_rate = "medium"
|
||||
reference = "MITRE ATT&CK T1059.006 Python"
|
||||
description = "Python 反弹 Shell:socket + exec/bin/sh + pty"
|
||||
strings:
|
||||
$socket1 = "import socket" ascii
|
||||
$socket2 = "socket.socket" ascii
|
||||
$pty = "import pty" ascii
|
||||
$sub = "import subprocess" ascii
|
||||
$sh = /\/bin\/(ba)?sh/ ascii
|
||||
$osdup2 = "os.dup2" ascii
|
||||
$execv = "os.execv" ascii
|
||||
condition:
|
||||
// socket + pty + /bin/bash = 完整 Python pty 反弹
|
||||
($socket1 or $socket2) and $pty and $sh
|
||||
or
|
||||
// socket + subprocess + /bin/sh + dup2 = 经典模式
|
||||
($socket1 or $socket2) and $sub and $sh and $osdup2
|
||||
or
|
||||
// socket + os.execv + /bin/bash
|
||||
($socket1 or $socket2) and $execv and $sh
|
||||
}
|
||||
|
||||
rule C7_Linux_ReverseShell_Perl {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C7"
|
||||
false_positive_rate = "medium"
|
||||
reference = "MITRE ATT&CK T1059.005 Perl"
|
||||
description = "Perl 反弹 Shell:IO::Socket + exec + /bin/sh"
|
||||
strings:
|
||||
$iosocket = "IO::Socket::INET" ascii nocase
|
||||
$socketvar = /\$s\s*=\s*IO::Socket/ ascii
|
||||
$exec = /exec\s+['"]\/bin\/(ba)?sh['"]/ ascii
|
||||
$open = /open\s*\(.*<&\$\{?s\}?/ ascii
|
||||
$eval = /eval\s+reverse\s+['"]/ ascii
|
||||
condition:
|
||||
($iosocket or $socketvar) and ($exec or $open or $eval)
|
||||
}
|
||||
|
||||
rule C7_Linux_ReverseShell_Socat {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C7"
|
||||
false_positive_rate = "low"
|
||||
reference = "MITRE ATT&CK T1059.004 Socat"
|
||||
description = "socat 反弹 Shell:TCP-LISTEN + EXEC:/bin/bash"
|
||||
strings:
|
||||
$socat1 = /socat\s+(TCP-LISTEN:\d{2,5},?\s*(reuseaddr|fork)?|TCP4:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{2,5})/ ascii
|
||||
$socat2 = /EXEC:\/bin\/(ba)?sh/ ascii
|
||||
$socat3 = /EXEC:'\/bin\/(ba)?sh'/ ascii
|
||||
condition:
|
||||
any of ($socat1*) and any of ($socat2, $socat3)
|
||||
}
|
||||
|
||||
rule C7_Linux_ReverseShell_Misc {
|
||||
meta:
|
||||
risk_level = "medium"
|
||||
category = "C7"
|
||||
false_positive_rate = "medium"
|
||||
reference = "多种语言反弹 Shell 通用特征"
|
||||
description = "通用反弹 Shell 标记:/dev/tcp 或 /dev/udp 或 reverse shell 工具名"
|
||||
strings:
|
||||
$devudp = /\/dev\/udp\/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{2,5}/ ascii
|
||||
$bashc = /bash\s+-c\s+['"].*\/dev\/(tcp|udp)/ ascii
|
||||
$dash_e = /\/bin\/bash\s+-e\s+['"]/ ascii
|
||||
$hydra = /Hydra|crackmap|weevely|meterpreter|msfconsole|msfvenom/ ascii nocase
|
||||
$reverseshell = /reverse[_\s]?shell|shell[_\s]?shock/ ascii nocase
|
||||
condition:
|
||||
any of ($devudp, $bashc, $dash_e) or any of ($hydra, $reverseshell)
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C7-2 持久化 —— crontab / authorized_keys / systemd
|
||||
// =============================================================================
|
||||
|
||||
rule C7_Linux_Persistence_Crontab {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C7"
|
||||
false_positive_rate = "medium"
|
||||
reference = "MITRE ATT&CK T1053.003 Cron"
|
||||
description = "crontab 持久化:下载执行 + .bashrc 注入 + /tmp/.hidden 目录"
|
||||
strings:
|
||||
$crontab1 = /\*\s+\*\s+\*\s+\*\s+\*\s+(curl|wget)\s+['"]?https?:/ ascii
|
||||
$crontab2 = /\*\s+\*\s+\*\s+\*\s+\*\s+(bash|sh)\s+\S+\s+['"]\/dev\/tcp/ ascii
|
||||
$crontab3 = /crontab\s+-[lre]?\s+\/tmp\/\w+/ ascii
|
||||
$bashrc = /\.bashrc|\.bash_profile|\.profile/ ascii
|
||||
$wget = /wget\s+https?:/ ascii
|
||||
$curl = /curl\s+.*\|\s*(bash|sh)/ ascii
|
||||
$hidden = /\/tmp\/\.?\w+\s+&&/ ascii
|
||||
condition:
|
||||
any of ($crontab1, $crontab2, $crontab3)
|
||||
or
|
||||
$bashrc and ($wget or $curl) and $hidden
|
||||
}
|
||||
|
||||
rule C7_Linux_Persistence_AuthorizedKeys {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C7"
|
||||
false_positive_rate = "low"
|
||||
reference = "MITRE ATT&CK T1098 SSH Authorized Keys"
|
||||
description = "authorized_keys 写入:下载公钥 + 追加到 .ssh/authorized_keys + chmod 600"
|
||||
strings:
|
||||
$authkeys = /\.ssh\/authorized_keys/ ascii
|
||||
$wgetkey = /wget\s+-O\s+.*authorized_keys/ ascii
|
||||
$curlkey = /curl\s+.*authorized_keys/ ascii
|
||||
$echokey = /echo\s+['"]ssh-(rsa|ecdsa|ed25519)/ ascii
|
||||
$chmod = /chmod\s+\d{3,4}\s+\$\{?SSH_DIR\}?authorized_keys/ ascii
|
||||
condition:
|
||||
any of ($wgetkey, $curlkey, $echokey) or ($authkeys and any of ($wgetkey, $curlkey, $chmod))
|
||||
}
|
||||
|
||||
rule C7_Linux_Persistence_SystemD {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C7"
|
||||
false_positive_rate = "medium"
|
||||
reference = "MITRE ATT&CK T1543.002 Systemd Service"
|
||||
description = "恶意 systemd unit 文件:ExecStart 指向 /tmp/.hidden + multi-user.target + 反弹命令"
|
||||
strings:
|
||||
$unit = /\[Unit\]/ ascii
|
||||
$service = /\[Service\]/ ascii
|
||||
$install = /\[Install\]/ ascii
|
||||
$execstart = /ExecStart=/ ascii
|
||||
$multiuser = /multi-user\.target/ ascii
|
||||
$hiddenpath = /\/tmp\/\.?\w+|\/var\/tmp\/\.?\w+/ ascii
|
||||
$bashsh = /\/bin\/(ba)?sh\s+-c/ ascii
|
||||
condition:
|
||||
// 完整 unit 片段 + 可疑路径
|
||||
$unit and $service and $execstart and ($hiddenpath or $bashsh)
|
||||
or
|
||||
// Install multi-user.target + ExecStart 反弹
|
||||
$install and $multiuser and any of ($execstart, $bashsh)
|
||||
}
|
||||
|
||||
rule C7_Linux_Persistence_LD_PRELOAD {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C7"
|
||||
false_positive_rate = "medium"
|
||||
reference = "MITRE ATT&CK T1574.006 LD_PRELOAD"
|
||||
description = "LD_PRELOAD 劫持:环境变量注入 + .so 文件 + dlopen"
|
||||
strings:
|
||||
$ldpreload = /LD_PRELOAD=/ ascii
|
||||
$sofile = /\.so(\.\d+)?:?/ ascii
|
||||
$dlopen = "dlopen" ascii
|
||||
$dlsym = "dlsym" ascii
|
||||
$exportenv = /export\s+LD_PRELOAD/ ascii
|
||||
condition:
|
||||
($ldpreload or $exportenv) and ($sofile or $dlopen or $dlsym)
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C7-3 Rootkit + 挖矿通用特征
|
||||
// =============================================================================
|
||||
|
||||
rule C7_Linux_Rootkit_KernelModule {
|
||||
meta:
|
||||
risk_level = "critical"
|
||||
category = "C7"
|
||||
false_positive_rate = "medium"
|
||||
reference = "MITRE ATT&CK T1547.006 Kernel Modules and Extensions"
|
||||
description = "内核模块加载:insmod/modprobe + .ko + /proc/kallsyms 隐藏"
|
||||
strings:
|
||||
$insmod = /insmod\s+.*\.ko/ ascii
|
||||
$modprobe = /modprobe\s+.*\.ko/ ascii
|
||||
$ko = /\.ko(\.xz|\.gz)?\b/ ascii
|
||||
$hiddenproc = /hide_process_from_dcache|hide_module/ ascii
|
||||
$proc = /\/proc\/kallsyms|\/proc\/modules/ ascii
|
||||
$netstat = /\/proc\/net\/tcp|\/proc\/net\/udp/ ascii
|
||||
condition:
|
||||
any of ($insmod, $modprobe) and any of ($ko, $hiddenproc)
|
||||
or
|
||||
any of ($hiddenproc) and any of ($proc, $netstat)
|
||||
}
|
||||
|
||||
rule C7_Linux_Miner_Generic {
|
||||
meta:
|
||||
risk_level = "medium"
|
||||
category = "C7"
|
||||
false_positive_rate = "medium"
|
||||
reference = "MITRE ATT&CK T1496 Resource Hijacking"
|
||||
description = "挖矿通用特征:stratum+tcp 协议 + 非标准端口(3333/5555/8080)"
|
||||
strings:
|
||||
$stratum = "stratum+tcp://" ascii
|
||||
$stratums = "stratum+ssl://" ascii
|
||||
$pool = /pool\.(xmr|mine|nanopool|coin|mining)/ ascii nocase
|
||||
$port3333 = /:\s*3333\b/ ascii
|
||||
$port5555 = /:\s*5555\b/ ascii
|
||||
$highcpu = /nice\s+-n\s+[+-]?\d+|cpulimit\s+-l/ ascii
|
||||
condition:
|
||||
any of ($stratum, $stratums, $pool) and any of ($port3333, $port5555)
|
||||
or
|
||||
any of ($stratum, $stratums) and $highcpu
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C7-4 跨平台后门:Ruby + Lua + Node.js
|
||||
// =============================================================================
|
||||
|
||||
rule C7_Misc_Ruby_Lua_ReverseShell {
|
||||
meta:
|
||||
risk_level = "medium"
|
||||
category = "C7"
|
||||
false_positive_rate = "medium"
|
||||
reference = "多语言反弹 Shell"
|
||||
description = "Ruby/Lua 反弹 Shell:TCPSocket + exec/system"
|
||||
strings:
|
||||
$ruby = "TCPSocket" ascii
|
||||
$lua = "loadstring" ascii
|
||||
$lua2 = "luasocket" ascii
|
||||
$exec = /(exec|system|IO\.popen)\s+.*\/bin\/(ba)?sh/ ascii
|
||||
condition:
|
||||
any of ($ruby, $lua, $lua2) and ($exec or any of ($ruby, $lua, $lua2))
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C7-5 网络投毒 / MITM 工具(内网横向移动)
|
||||
// =============================================================================
|
||||
|
||||
rule C7_Network_Tools_Malicious {
|
||||
meta:
|
||||
risk_level = "medium"
|
||||
category = "C7"
|
||||
false_positive_rate = "medium"
|
||||
reference = "内网攻击工具"
|
||||
description = "内网攻击工具:ettercap/responder/nmap 扫描 + SMB/DNS 投毒"
|
||||
strings:
|
||||
$ettercap = "ettercap" ascii nocase
|
||||
$responder = /responder(\.py)?/ ascii nocase
|
||||
$nmap = "nmap" ascii nocase
|
||||
$smb = /--smb/ ascii
|
||||
$ms17 = "ms17-010" ascii nocase
|
||||
$smbghost = "SMBGhost" ascii nocase
|
||||
$dnsspoof = /dns[-_]spoof|dns[-_]mitm/ ascii nocase
|
||||
$arppoison = /arp[-_]poison|arp[-_]spoof/ ascii nocase
|
||||
condition:
|
||||
any of ($ettercap, $responder, $dnsspoof, $arppoison)
|
||||
or
|
||||
$nmap and ($smb or $ms17 or $smbghost)
|
||||
}
|
||||
403
rules/pe.yar
Normal file
403
rules/pe.yar
Normal file
@@ -0,0 +1,403 @@
|
||||
// =============================================================================
|
||||
// MeshSafe L2B YARA 规则集 —— Windows PE 恶意程序专项(C1 + C8)
|
||||
// =============================================================================
|
||||
//
|
||||
// 设计原则:
|
||||
// - 所有规则使用 2-3 特征组合命中(API 组合 + C2 URL + Mutex 持久化等)
|
||||
// - binary.py 的 PE 结构分析负责:节熵 + 签名 + 可疑导入(单 API)
|
||||
// - YARA 负责:多 API 组合 + 字符串组合 + 壳 + 勒索专项
|
||||
// - 命中后作为 finding 交给 PolicyEngine 权重累加,不直接零容忍
|
||||
//
|
||||
// 范围:
|
||||
// - C1: Windows PE 恶意程序(注入器 / 下载器 / RAT / Loader)
|
||||
// - C8: 勒索 / 挖矿专项
|
||||
// - C9: 壳 / 签名 / 结构异常(binary.py 已覆盖大部分,YARA 补充壳特征)
|
||||
//
|
||||
// 维护:
|
||||
// - 新恶意家族出现时,优先补充"API 组合 + Mutex 名 + C2 URL"三件套
|
||||
// - 壳特征(UPX/Themida/VMP)可识别后自动送沙箱深检
|
||||
// =============================================================================
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C1-1 进程注入三件套(VirtualAllocEx + WriteProcessMemory + CreateRemoteThread)
|
||||
// binary.py 扫了 SuspiciousImports(单个 API),但 3 个同时出现 = 必然是注入器
|
||||
// =============================================================================
|
||||
|
||||
rule C1_PE_ProcessInjection {
|
||||
meta:
|
||||
risk_level = "critical"
|
||||
category = "C1"
|
||||
false_positive_rate = "low"
|
||||
reference = "MITRE ATT&CK T1055 Process Injection"
|
||||
description = "PE 文件同时导入 进程注入三件套 API = 远控/注入器特征"
|
||||
strings:
|
||||
$s1 = "VirtualAllocEx" ascii
|
||||
$s2 = "WriteProcessMemory" ascii
|
||||
$s3 = "CreateRemoteThread" ascii
|
||||
// 备选:Nt 系列(NtUnmapViewOfSection + VirtualAllocEx + CreateRemoteThread)
|
||||
$n1 = "NtUnmapViewOfSection" ascii
|
||||
$n2 = "NtMapViewOfSection" ascii
|
||||
$n3 = "ZwUnmapViewOfSection" ascii
|
||||
// 也可能是 QueueUserAPC 注 APC 注入
|
||||
$apc = "QueueUserAPC" ascii
|
||||
// 或 SetWindowsHookEx DLL 注入
|
||||
$hook = "SetWindowsHookEx" ascii
|
||||
condition:
|
||||
// 经典三件套(必须同时命中)
|
||||
$s1 and $s2 and $s3
|
||||
or
|
||||
// Nt 系列内存注入(至少 2 个 Nt + 1 个注入)
|
||||
(any of ($n1, $n2, $n3) and any of ($s1, $s3, $apc))
|
||||
or
|
||||
// APC 注入 + VirtualAllocEx
|
||||
$apc and $s1
|
||||
or
|
||||
// Hook DLL 注入
|
||||
$hook and $s1
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C1-2 下载器组合(网络 API + 本地持久化 / 执行)
|
||||
// 单一 URLDownloadToFile 不致命,但 "下载 + 执行 + 持久化" 三件套 = Loader
|
||||
// =============================================================================
|
||||
|
||||
rule C1_PE_Downloader_Loader {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C1"
|
||||
false_positive_rate = "low"
|
||||
reference = "MITRE ATT&CK T1105 Ingress Tool Transfer"
|
||||
description = "下载器组合:HTTP/FTP 下载 + 写入到可疑路径 + 执行"
|
||||
strings:
|
||||
// 网络下载 API(任选其一)
|
||||
$net1 = "URLDownloadToFile" ascii
|
||||
$net2 = "InternetOpenUrl" ascii
|
||||
$net3 = "WinHttpOpen" ascii
|
||||
$net4 = "WinHttpOpenRequest" ascii
|
||||
$net5 = "FtpOpenFile" ascii
|
||||
$net6 = "DownloadFile" ascii
|
||||
$net7 = "WinHttpSendRequest" ascii
|
||||
|
||||
// 写入/保存到本地
|
||||
$save1 = "WriteFile" ascii
|
||||
$save2 = "SaveToFile" ascii
|
||||
$save3 = "URLDownloadToCacheFile" ascii
|
||||
|
||||
// 执行下载的载荷
|
||||
$exec1 = "WinExec" ascii
|
||||
$exec2 = "CreateProcess" ascii
|
||||
$exec3 = "ShellExecute" ascii
|
||||
$exec4 = "CreateRemoteThread" ascii
|
||||
|
||||
// 持久化(注册表/启动项)
|
||||
$persist1 = "RegSetValueEx" ascii
|
||||
$persist2 = "SetServiceObjectSecurity" ascii
|
||||
$persist3 = "CreateService" ascii
|
||||
$persist4 = "schtasks.exe" ascii
|
||||
$persist5 = "RUN" ascii // HKCU\Software\Microsoft\Windows\CurrentVersion\Run
|
||||
condition:
|
||||
// 下载 + 保存 + 执行(三件套)
|
||||
any of ($net*) and any of ($save*) and any of ($exec*)
|
||||
or
|
||||
// 下载 + 持久化(即使没执行也是准备投毒)
|
||||
any of ($net*) and any of ($persist*)
|
||||
or
|
||||
// 执行 + 持久化(下载可能在运行时动态完成)
|
||||
any of ($exec1, $exec2, $exec3) and any of ($persist*)
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C1-3 RAT / 远控特征(C2 通信 + 命令执行 + 持久化)
|
||||
// =============================================================================
|
||||
|
||||
rule C1_PE_RAT_CommandControl {
|
||||
meta:
|
||||
risk_level = "critical"
|
||||
category = "C1"
|
||||
false_positive_rate = "medium"
|
||||
reference = "MITRE ATT&CK T1071 Application Layer Protocol"
|
||||
description = "RAT C2 通信特征:WinHTTP/WSASend + 命令执行 API + 可疑 URL/域名"
|
||||
strings:
|
||||
// C2 网络通道
|
||||
$c2_send = /WSASend|send\s*\(|sendto|WinHttpSendRequest|InternetWriteFile/ ascii
|
||||
$c2_recv = /WSARecv|recv\s*\(|recvfrom|WinHttpReadData|InternetReadFile/ ascii
|
||||
$c2_connect = /WSAConnect|connect\s*\(|WinHttpConnect|InternetConnect/ ascii
|
||||
|
||||
// 命令执行
|
||||
$cmd = /CreateProcess|ShellExecute|WinExec|system\s*\(|popen/ ascii
|
||||
|
||||
// 可疑 C2 URL(可执行文件里出现 http://...exe 或常见 C2 域名)
|
||||
$c2url1 = /http:\/\/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{2,5}/ ascii
|
||||
$c2url2 = /https?:\/\/[^\"\s'\)]+\.(ru|top|xyz|tk|ml|ga|gq|cf|pw|click|stream|xyz|buzz|loan)\/[^\"\s'\)]*\.exe/ ascii
|
||||
$c2url3 = /(c2|panel|gate|bot|ops|serv|beacon|stage|stager)\.(ru|top|xyz|cc|io|com|net)/ ascii
|
||||
condition:
|
||||
// C2 通信 + 命令执行(至少两个网络 + 一个命令)
|
||||
any of ($c2_send, $c2_recv, $c2_connect) and any of ($cmd*) and any of ($c2url*)
|
||||
or
|
||||
// C2 URL 模式 + 网络 API
|
||||
any of ($c2url*) and any of ($c2_connect, $c2_send)
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C1-4 Mutex 互斥体名(勒索 / RAT / Loader 的持久化标记)
|
||||
// 单一 Mutex 名有一定价值,但必须配合其他特征才触发
|
||||
// =============================================================================
|
||||
|
||||
rule C1_PE_Mutex_Persistence {
|
||||
meta:
|
||||
risk_level = "medium"
|
||||
category = "C1"
|
||||
false_positive_rate = "medium"
|
||||
reference = "MITRE ATT&CK T1057 Process Discovery (mutex as persistence marker)"
|
||||
description = "可疑 Mutex 名称 + CreateMutex API = 持久化标记"
|
||||
strings:
|
||||
$createmutex = "CreateMutexA" ascii
|
||||
$createmutexw = "CreateMutexW" ascii
|
||||
// 常见勒索/RAT Mutex 名(大小写不敏感,含 Unicode 变体用 wide)
|
||||
// LockBit
|
||||
$lockbit1 = /Global\\[Ll]ock[Bb]it/ ascii
|
||||
$lockbit2 = /Local\\[Ll]ock[Bb]it/ ascii
|
||||
// BlackCat / ALPHV
|
||||
$blackcat = /Global\\[Bb]lack[Cc]at|[Aa][Ll][Pp][Hh][Vv]/ ascii
|
||||
// Ryuk
|
||||
$ryuk = /RyukTask[\d]|Global\\Ryuk/ ascii
|
||||
// Conti
|
||||
$conti = /Global\\[Cc]onti|Local\\[Cc]onti/ ascii
|
||||
// Pseudo/Dharma
|
||||
$dharma = /Global\\[Dd]harma|Local\\[Dd]harma/ ascii
|
||||
// 通用可疑模式:Mutex 名包含 "Mutex" + UUID 变体
|
||||
$generic1 = /Global\\Mutex[0-9a-f]{8}/ ascii
|
||||
// Kryptik/Qakbot
|
||||
$qakbot = /[Qq]akbot|[Kk]ryptik/ ascii
|
||||
// Cobalt Strike named pipe
|
||||
$cs1 = /\\\\\.\\pipe\\msagent_[0-9a-f]+/ ascii
|
||||
$cs2 = /\\\\\.\\pipe\\[Bb]eacon_[0-9a-f]+/ ascii
|
||||
condition:
|
||||
// CreateMutex + 已知家族 Mutex 名
|
||||
(any of ($createmutex*)) and any of ($lockbit1, $lockbit2, $blackcat, $ryuk, $conti, $dharma, $qakbot)
|
||||
or
|
||||
// Cobalt Strike 命名管道特征(不需要 CreateMutex)
|
||||
any of ($cs*)
|
||||
or
|
||||
// CreateMutex + 通用可疑 UUID Mutex
|
||||
(any of ($createmutex*)) and $generic1
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C1-5 DLL 劫持 / LoadLibrary 动态加载
|
||||
// =============================================================================
|
||||
|
||||
rule C1_PE_DLLHijacking {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C1"
|
||||
false_positive_rate = "medium"
|
||||
reference = "MITRE ATT&CK T1574 Hijack Execution Flow"
|
||||
description = "PE 动态加载多个系统 DLL + 非系统路径 = DLL 劫持迹象"
|
||||
strings:
|
||||
$loadlib = "LoadLibraryA" ascii
|
||||
$loadlibw = "LoadLibraryW" ascii
|
||||
$getproc = "GetProcAddress" ascii
|
||||
// 可疑加载路径(非 System32)
|
||||
$path1 = /\\Users\\[^\\]+\\AppData\\Local\\Temp/ ascii
|
||||
$path2 = /\\AppData\\Local\\Temp/ ascii
|
||||
$path3 = /\\ProgramData\\/ ascii
|
||||
$path4 = /\\Public\\Documents\\/ ascii
|
||||
condition:
|
||||
// LoadLibrary + 可疑路径 + GetProcAddress = 完整劫持链
|
||||
(any of ($loadlib*)) and any of ($path*) and $getproc
|
||||
or
|
||||
// LoadLibrary + 多个可疑路径
|
||||
(any of ($loadlib*)) and 2 of ($path*)
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C1-6 LOLBin(Living Off The Land Binary)调用特征
|
||||
// 已知合法 Windows 二进制被恶意利用来执行命令
|
||||
// =============================================================================
|
||||
|
||||
rule C1_PE_LOLBin_Usage {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C1"
|
||||
false_positive_rate = "low"
|
||||
reference = "https://lolbas-project.github.io/"
|
||||
description = "PE 文件中出现 LOLBin 调用:certutil / mshta / rundll32 / regsvr32 / bitsadmin / wmic / msiexec"
|
||||
strings:
|
||||
$certutil = /certutil(\.exe)?\s+(-urlcache|-decode|-encode|-hashfile)/ ascii
|
||||
$mshta = /mshta(\.exe)?\s+(https?:|javascript:|vbscript:)/ ascii
|
||||
$rundll32 = /rundll32(\.exe)?\s+[A-Za-z0-9_.]+,/ ascii
|
||||
$regsvr32 = /regsvr32(\.exe)?\s+\/s\s+\/u/ ascii
|
||||
$bitsadmin = /bitsadmin(\.exe)?\s+(\/transfer|\/create)/ ascii
|
||||
$wmic = /wmic(\.exe)?\s+(process\s+call\s+create|product\s+call)/ ascii
|
||||
$msiexec = /msiexec(\.exe)?\s+\/[ia]\s+https?:/ ascii
|
||||
$installutil = /installutil(\.exe)?\s+\/u\s+\/logfile=/ ascii
|
||||
$syncapp = /syncapp(\.exe)?\s+\/compattrack/ ascii
|
||||
$psexec = /psexec(\.exe)?\s+(-accepteula|-i\s+\d+|-w\s+https?:)/ ascii
|
||||
// 命令执行 API(用于组合条件)
|
||||
$exec1 = "CreateProcess" ascii
|
||||
$exec2 = "ShellExecute" ascii
|
||||
$exec3 = "WinExec" ascii
|
||||
condition:
|
||||
// 至少 1 个 LOLBin 调用 + 命令执行 API
|
||||
any of ($certutil*, $mshta*, $rundll32*, $regsvr32*, $bitsadmin*, $wmic*, $msiexec*, $installutil*, $syncapp*, $psexec*)
|
||||
and any of ($exec*)
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C8-1 勒索加密 API 组合(CryptEncrypt + BCrypt* + 文件遍历 + 删除卷影)
|
||||
// =============================================================================
|
||||
|
||||
rule C8_Ransomware_Encryption {
|
||||
meta:
|
||||
risk_level = "critical"
|
||||
category = "C8"
|
||||
false_positive_rate = "low"
|
||||
reference = "MITRE ATT&CK T1486 Data Encrypted for Impact"
|
||||
description = "勒索加密链:CryptEncrypt/BCryptEncrypt + 大量文件遍历 + 卷影删除 = 勒索"
|
||||
strings:
|
||||
// 加密 API(至少出现两个)
|
||||
$enc1 = "CryptEncrypt" ascii
|
||||
$enc2 = "CryptDeriveKey" ascii
|
||||
$enc3 = "BCryptEncrypt" ascii
|
||||
$enc4 = "BCryptDeriveKeyPair" ascii
|
||||
$enc5 = "CryptGenKey" ascii
|
||||
|
||||
// 文件遍历(全盘加密需要)
|
||||
$enum1 = "FindFirstFileA" ascii
|
||||
$enum2 = "FindFirstFileW" ascii
|
||||
$enum3 = "FindNextFileA" ascii
|
||||
$enum4 = "FindNextFileW" ascii
|
||||
|
||||
// 卷影删除(勒索前置)
|
||||
$vss1 = "vssadmin" ascii
|
||||
$vss2 = "delete shadows" ascii
|
||||
$vss3 = "DeleteShadowCopies" ascii
|
||||
$vss4 = "wmic" ascii
|
||||
|
||||
// 勒索信文件名变体(出现在二进制里)
|
||||
$ransomnote1 = /(HOW_TO_RECOVER|RESTORE_FILES|DECRYPT_INSTRUCTIONS|README|HELP_DECRYPT|_readme|_restore)[\w.-]*\.(txt|html|png|jpg|bmp|url)/ nocase
|
||||
$ransomnote2 = /\.(locky|zepto|cryptolocker|tor|crpt|encrypted|virus|wallet|pay2)/ nocase
|
||||
$ransomnote3 = /bitcoin|bitcash|monero|ltc|BTC\b/ ascii
|
||||
condition:
|
||||
// 加密 API + 文件遍历 = 加密工具(必须至少 2 个加密 API)
|
||||
(2 of ($enc*)) and any of ($enum*)
|
||||
or
|
||||
// 加密 API + 卷影删除 = 完整勒索
|
||||
(any of ($enc*)) and any of ($vss*)
|
||||
or
|
||||
// 加密 API + 勒索信 + 加密文件扩展名 = 明确勒索
|
||||
(any of ($enc*)) and (any of ($ransomnote1, $ransomnote2)) and $ransomnote3
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C8-2 挖矿(xmrig / stratum+tcp / 矿池域名)
|
||||
// =============================================================================
|
||||
|
||||
rule C8_Mining_Monero {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C8"
|
||||
false_positive_rate = "low"
|
||||
reference = "MITRE ATT&CK T1496 Resource Hijacking"
|
||||
description = "挖矿程序特征:xmrig 命令行参数 / stratum+tcp / 矿池域名"
|
||||
strings:
|
||||
// xmrig 命令行特征
|
||||
$xmrig1 = "xmrig" ascii nocase
|
||||
$xmrig2 = /--donate-level\s+\d+/ ascii
|
||||
$xmrig3 = /-o\s+stratum\+tcp/ ascii
|
||||
$xmrig4 = /--cpu-priority\s+\d/ ascii
|
||||
$xmrig5 = /--max-threads-hint/ ascii
|
||||
|
||||
// 矿池域名(Monero)
|
||||
$pool1 = "pool.xmrig.com" ascii nocase
|
||||
$pool2 = "pool.minexmr.com" ascii nocase
|
||||
$pool3 = "pool.supportxmr.com" ascii nocase
|
||||
$pool4 = "mine.moneropool.com" ascii nocase
|
||||
$pool5 = "stratum+tcp://" ascii
|
||||
|
||||
// CPU 高占用循环特征
|
||||
$loop = /(while|for)\s*\(\s*\d+\s*[<>=]/ ascii
|
||||
$thread = "CreateThread" ascii
|
||||
condition:
|
||||
// 至少 2 个 xmrig 特征
|
||||
(any of ($xmrig1, $xmrig2, $xmrig3, $xmrig4, $xmrig5)) and 2 of ($*)
|
||||
or
|
||||
// stratum+tcp 矿池协议 + 多个线程创建
|
||||
$pool5 and ($thread or 2 of ($xmrig*))
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C9 壳特征(UPX / Themida / VMProtect / Enigma)
|
||||
// 壳识别后建议升级到 L3 沙箱深检,不单独阻断
|
||||
// =============================================================================
|
||||
|
||||
rule C9_Packer_UPX {
|
||||
meta:
|
||||
risk_level = "medium"
|
||||
category = "C9"
|
||||
false_positive_rate = "low"
|
||||
reference = "UPX Packer"
|
||||
description = "UPX 加壳 PE:节名 UPX0 / UPX1 + UPX 签名"
|
||||
strings:
|
||||
$upx0 = "UPX0" ascii
|
||||
$upx1 = "UPX1" ascii
|
||||
$upx2 = "UPX!" ascii
|
||||
$upx3 = /UPX\s+\d+\.\d+/ ascii // "UPX 3.96" 这类版本字符串
|
||||
$upx4 = /UPX\b/ ascii
|
||||
condition:
|
||||
// 节名(两个)+ 签名
|
||||
($upx0 and $upx1) or ($upx2 and any of ($upx3, $upx4))
|
||||
}
|
||||
|
||||
rule C9_Packer_Themida_VMP {
|
||||
meta:
|
||||
risk_level = "medium"
|
||||
category = "C9"
|
||||
false_positive_rate = "low"
|
||||
reference = "Themida / VMProtect"
|
||||
description = "商业壳特征:Themida / VMProtect 产品标识字符串"
|
||||
strings:
|
||||
$themida1 = "Themida" ascii wide
|
||||
$themida2 = "WinLicense" ascii wide
|
||||
$themida3 = "Oreans" ascii wide
|
||||
$vmp1 = "VMProtect" ascii wide
|
||||
$vmp3 = "VMProtect SDK" ascii wide
|
||||
condition:
|
||||
any of ($themida*) or any of ($vmp*)
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C1-7 PE 高熵 + 大量网络 API(疑似加壳下载器)
|
||||
// binary.py 的 HighEntropySection 已单独扫描,但 YARA 看"熵 + 网络"组合
|
||||
// =============================================================================
|
||||
|
||||
rule C1_PE_EntropyHighNetwork {
|
||||
meta:
|
||||
risk_level = "medium"
|
||||
category = "C1"
|
||||
false_positive_rate = "medium"
|
||||
reference = "binary.py HighEntropySection 联动"
|
||||
description = "PE 同时出现:多个网络 API + 加壳特征(熵高) + 无签名"
|
||||
strings:
|
||||
$net1 = "InternetOpenUrl" ascii
|
||||
$net2 = "WinHttpOpen" ascii
|
||||
$net3 = "URLDownloadToFile" ascii
|
||||
$net4 = "WSAConnect" ascii
|
||||
// 壳特征
|
||||
$upx = "UPX0" ascii
|
||||
$themida = "Themida" ascii
|
||||
condition:
|
||||
// 网络 API + 壳特征 = 加壳下载器
|
||||
any of ($net*) and ($upx or $themida)
|
||||
}
|
||||
210
rules/ransom.yar
Normal file
210
rules/ransom.yar
Normal file
@@ -0,0 +1,210 @@
|
||||
// =============================================================================
|
||||
// MeshSafe L2B YARA 规则集 —— 勒索 / 挖矿专项(C8,剩余家族)
|
||||
// =============================================================================
|
||||
//
|
||||
// 设计原则:
|
||||
// - C8_Ransomware_Encryption 在 pe.yar 里已经覆盖了"加密 API + 卷影删除 + 勒索信"通用链
|
||||
// - 本文件补充:具体家族特征(LockBit/BlackCat/Conti/Ryuk/Pseudo)+
|
||||
// 文件扩展名黑名单变体 + 勒索信文件名模式
|
||||
// - 必须满足"加密 API 组合 + 家族特征"才触发,单靠扩展名不触发
|
||||
//
|
||||
// 元数据规范:同 webshell.yar / pe.yar(risk_level, category, false_positive_rate)
|
||||
// =============================================================================
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C8-1 LockBit 家族
|
||||
// =============================================================================
|
||||
|
||||
rule C8_Ransomware_LockBit {
|
||||
meta:
|
||||
risk_level = "critical"
|
||||
category = "C8"
|
||||
false_positive_rate = "low"
|
||||
reference = "LockBit / BitLocker 勒索家族"
|
||||
description = "LockBit 家族特征:Mutex 名 + .lockbit3/.lockbit 扩展名 + CryptEncrypt"
|
||||
strings:
|
||||
$mutex1 = /Global\\[Ll]ock[Bb]it/ ascii
|
||||
$mutex2 = /Local\\[Ll]ock[Bb]it/ ascii
|
||||
$mutex3 = /LockBit[\d_]/ ascii nocase
|
||||
$ext1 = /\.lockbit3?\b/ ascii nocase
|
||||
$ext2 = /\.lckbt\b/ ascii nocase
|
||||
$enc = /CryptEncrypt|BCryptEncrypt|CryptGenKey/ ascii
|
||||
$ransomnote = /README[\d_-]*\.(html|txt|bmp|png|jpg|url)/ nocase
|
||||
condition:
|
||||
// Mutex + 加密 API(家族识别核心)
|
||||
any of ($mutex*) and any of ($enc*)
|
||||
or
|
||||
// Mutex + 勒索扩展名
|
||||
any of ($mutex*) and any of ($ext*)
|
||||
or
|
||||
// 加密 API + 家族扩展名 + 勒索信
|
||||
any of ($enc*) and any of ($ext*) and $ransomnote
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C8-2 BlackCat / ALPHV 家族
|
||||
// =============================================================================
|
||||
|
||||
rule C8_Ransomware_BlackCat {
|
||||
meta:
|
||||
risk_level = "critical"
|
||||
category = "C8"
|
||||
false_positive_rate = "low"
|
||||
reference = "BlackCat (ALPHV) 勒索家族"
|
||||
description = "BlackCat/ALPHV:Mutex + .blackcat/.bc1 扩展名 + Rust 字符串特征"
|
||||
strings:
|
||||
$mutex1 = /Global\\[Bb]lack[Cc]at/ ascii
|
||||
$mutex2 = /[Aa][Ll][Pp][Hh][Vv]/ ascii
|
||||
$ext1 = /\.blackcat\b/ ascii nocase
|
||||
$ext2 = /\.bc1?\b/ ascii nocase
|
||||
$rust1 = "rustc" ascii
|
||||
$rust2 = "/rustc/" ascii
|
||||
$enc = /CryptEncrypt|BCryptEncrypt/ ascii
|
||||
$note = /BlackCat.*README|how_to_decrypt|restore_files/ ascii nocase
|
||||
condition:
|
||||
any of ($mutex1, $mutex2) and any of ($enc*, $ext*)
|
||||
or
|
||||
any of ($ext*) and any of ($rust*) and $note
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C8-3 Conti 家族
|
||||
// =============================================================================
|
||||
|
||||
rule C8_Ransomware_Conti {
|
||||
meta:
|
||||
risk_level = "critical"
|
||||
category = "C8"
|
||||
false_positive_rate = "low"
|
||||
reference = "Conti 勒索家族"
|
||||
description = "Conti:Mutex + .conti 扩展名 + 加密 API"
|
||||
strings:
|
||||
$mutex1 = /Global\\[Cc]onti/ ascii
|
||||
$mutex2 = /Local\\[Cc]onti/ ascii
|
||||
$ext1 = /\.conti\b/ ascii nocase
|
||||
$enc = /CryptEncrypt|BCryptEncrypt|CryptDeriveKey/ ascii
|
||||
condition:
|
||||
any of ($mutex*) and any of ($enc*, $ext*)
|
||||
or
|
||||
any of ($ext*) and any of ($enc*)
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C8-4 Ryuk / Pseudo / Dharma 家族
|
||||
// =============================================================================
|
||||
|
||||
rule C8_Ransomware_Ryuk_Pseudo {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C8"
|
||||
false_positive_rate = "medium"
|
||||
reference = "Ryuk / Pseudo / Dharma 勒索家族"
|
||||
description = "Ryuk/Pseudo: RyukTask Mutex + 加密 API + .ryk/.pseudo 扩展名"
|
||||
strings:
|
||||
$mutex_ryuk = /RyukTask[\d]/ ascii
|
||||
$mutex_pseudo = /Global\\[Pp]seudo/ ascii
|
||||
$mutex_dharma = /Global\\[Dd]harma/ ascii
|
||||
$ext_ryk = /\.ryk\b/ ascii nocase
|
||||
$ext_pseudo = /\.pseudo\b/ ascii nocase
|
||||
$ext_dharma = /\.dharma\b/ ascii nocase
|
||||
$enc = /CryptEncrypt|CryptDeriveKey/ ascii
|
||||
condition:
|
||||
(any of ($mutex_ryuk, $mutex_pseudo, $mutex_dharma))
|
||||
and (any of ($enc*, $ext_ryk, $ext_pseudo, $ext_dharma))
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C8-5 勒索信文件名模式(独立规则,辅助 family 识别)
|
||||
// =============================================================================
|
||||
|
||||
rule C8_Ransomware_Note_Filename {
|
||||
meta:
|
||||
risk_level = "medium"
|
||||
category = "C8"
|
||||
false_positive_rate = "medium"
|
||||
reference = "勒索信文件名通用模式"
|
||||
description = "勒索信典型文件名变体(匹配后触发需要配合加密 API 才升级高危)"
|
||||
strings:
|
||||
$n1 = /HOW_TO_RECOVER[\w.-]*\.(txt|html|png|bmp|jpg|url|vbs|js)/ nocase
|
||||
$n2 = /RESTORE_FILES[\w.-]*\.(txt|html|png|bmp|jpg|url|vbs|js)/ nocase
|
||||
$n3 = /DECRYPT_INSTRUCTIONS[\w.-]*\.(txt|html|png|bmp|jpg|url)/ nocase
|
||||
$n4 = /README[_\s-]*[\d]*[_\s-]*[\w]*\.(txt|html|png|bmp|jpg|url)/ nocase
|
||||
$n5 = /HELP_DECRYPT[\w.-]*\.(txt|html|png|bmp|jpg|url)/ nocase
|
||||
$n6 = /_readme[\w.-]*\.(txt|html|png|bmp|jpg|url)/ nocase
|
||||
$n7 = /_restore[\w.-]*\.(txt|html|png|bmp|jpg|url)/ nocase
|
||||
$bitcoin = /bitcoin address|BTC\b|monero address|XMR\b|send money|ransom|payment/ nocase
|
||||
$wallet = /1[A-Za-z0-9]{25,34}|bc1[A-Za-z0-9]{11,71}|4[0-9A-Za-z]{32}/ nocase
|
||||
$encapi = /CryptEncrypt|BCryptEncrypt|CryptDeriveKey/ ascii
|
||||
condition:
|
||||
// 勒索信文件名 + 加密 API = 明确勒索
|
||||
any of ($n*) and $encapi
|
||||
or
|
||||
// 勒索信文件名 + 比特币/XMR 地址 = 大概率勒索
|
||||
any of ($n*) and any of ($bitcoin, $wallet)
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C8-6 加密文件扩展名黑名单(不单独触发,配合加密 API)
|
||||
// =============================================================================
|
||||
|
||||
rule C8_Ransomware_Extension_Blacklist {
|
||||
meta:
|
||||
risk_level = "low"
|
||||
category = "C8"
|
||||
false_positive_rate = "medium"
|
||||
reference = "勒索加密文件扩展名模式"
|
||||
description = "常见勒索加密扩展名(.locky/.zepto/.cryptolocker/.encrypted/.virus/.tor/.crpt 等)+ 加密 API"
|
||||
strings:
|
||||
$ext1 = /\.locky\b/ nocase
|
||||
$ext2 = /\.zepto\b/ nocase
|
||||
$ext3 = /\.cryptolocker\b/ nocase
|
||||
$ext4 = /\.cryptor\b/ nocase
|
||||
$ext5 = /\.crypt\b/ nocase
|
||||
$ext6 = /\.encrypted\b/ nocase
|
||||
$ext7 = /\.virus\b/ nocase
|
||||
$ext8 = /\.tor\b/ nocase
|
||||
$ext9 = /\.crpt\b/ nocase
|
||||
$ext10 = /\.wallet\b/ nocase
|
||||
$ext11 = /\.pay2[\w.-]*\.?\w*\b/ nocase
|
||||
$enc = /CryptEncrypt|BCryptEncrypt|CryptDeriveKey/ ascii
|
||||
$note = /HOW_TO_RECOVER|RESTORE_FILES|DECRYPT_INSTRUCTIONS|README/ nocase
|
||||
condition:
|
||||
// 扩展名 + 加密 API + 勒索信 = 完整勒索链
|
||||
any of ($ext*) and $enc and $note
|
||||
or
|
||||
// 扩展名 + 加密 API(至少 2 种扩展名变体)
|
||||
(2 of ($ext*)) and $enc
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// C8-7 卷影删除专项(辅助勒索前置)
|
||||
// =============================================================================
|
||||
|
||||
rule C8_Ransomware_VolumeShadow {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C8"
|
||||
false_positive_rate = "medium"
|
||||
reference = "MITRE ATT&CK T1490 Inhibit System Recovery"
|
||||
description = "删除卷影副本:vssadmin / wmic shadowcopy + 加密 API"
|
||||
strings:
|
||||
$vss1 = "vssadmin delete shadows" ascii
|
||||
$vss2 = /vssadmin\s+delete\s+shadows\s+\/all\b/ ascii
|
||||
$wmic1 = /wmic\s+shadowcopy\s+delete/ ascii
|
||||
$wmic2 = /wmic\s+shadowcopy\s+where\s+\d+/ ascii
|
||||
$vss3 = /ShadowCopy|VolumeShadowCopy|vss\b/i ascii // "i" flag = nocase in YARA
|
||||
$enc = /CryptEncrypt|BCryptEncrypt|CryptDeriveKey/ ascii
|
||||
condition:
|
||||
// 卷影删除 + 加密 API = 完整勒索前置
|
||||
(any of ($vss1, $vss2, $wmic*, $vss3)) and any of ($enc*)
|
||||
or
|
||||
// 连续多次 vssadmin delete = 正在清卷影
|
||||
any of ($vss1, $vss2) and any of ($wmic*)
|
||||
}
|
||||
345
rules/webshell.yar
Normal file
345
rules/webshell.yar
Normal file
@@ -0,0 +1,345 @@
|
||||
// =============================================================================
|
||||
// MeshSafe L2B YARA 规则集 — Webshell 专项(C3)
|
||||
// =============================================================================
|
||||
//
|
||||
// 设计原则:
|
||||
// - 所有规则使用 2-3 个特征组合命中,避免单一关键词导致误杀
|
||||
// - 光闸场景误报代价极高(阻断合法文件传输),宁可漏报不轻易阻断
|
||||
// - 命中后作为 finding 交给 PolicyEngine 权重累加,不直接零容忍
|
||||
//
|
||||
// 元数据规范:
|
||||
// risk_level = critical | high | medium | low
|
||||
// category = "C3"
|
||||
// false_positive_rate = low | medium | high
|
||||
//
|
||||
// 维护:
|
||||
// - 新 Webshell 工具/变体出现时,优先新增"工具特征"组合规则
|
||||
// - 纯 PHP/JSP 反序列化 payload 单特征也可能有价值,但组合原则仍适用
|
||||
// =============================================================================
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// PHP Webshell —— 一行马 / 变形马
|
||||
// =============================================================================
|
||||
|
||||
// PHP 一行 eval($_POST) 组合(常见的菜刀/蚁剑/冰蝎基础形态)
|
||||
// 单一 eval + $_GET/$_POST 误伤太大,必须"动态执行入口 + 用户输入 + 输出回显"三点组合
|
||||
rule C3_PHP_Webshell_Oneliner {
|
||||
meta:
|
||||
risk_level = "critical"
|
||||
category = "C3"
|
||||
false_positive_rate = "low"
|
||||
reference = "OWASP Web Shell Cheat Sheet"
|
||||
description = "PHP 一行 Webshell:eval + 超全局变量 + 输出回显 组合命中"
|
||||
strings:
|
||||
$entrypoint = /eval\s*\(\s*\$\s*_(GET|POST|REQUEST|COOKIE)\s*\[.+\]\s*\)/ ascii
|
||||
// 备选入口:assert / create_function / preg_replace / system
|
||||
$entryp2 = /assert\s*\(\s*\$\s*_(GET|POST|REQUEST)/ ascii
|
||||
$entryp3 = /create_function\s*\(\s*['"]['"]\s*,\s*\$\s*_(GET|POST|REQUEST)/ ascii
|
||||
// 回显手段:print / echo / var_dump / die
|
||||
$echo = /print|echo|var_dump|die/ ascii
|
||||
condition:
|
||||
($entrypoint or $entryp2 or $entryp3) and $echo
|
||||
}
|
||||
|
||||
// PHP Webshell —— 多层解码(base64 + gzinflate + str_rot13)
|
||||
rule C3_PHP_Webshell_Obfuscated {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C3"
|
||||
false_positive_rate = "medium"
|
||||
reference = "典型 Webshell 变形手段"
|
||||
description = "PHP 解码链组合(base64_decode + gzinflate / str_rot13 + eval)"
|
||||
strings:
|
||||
$b64 = "base64_decode" ascii wide
|
||||
$eval = "eval(" ascii wide
|
||||
$gzinflate = "gzinflate" ascii wide
|
||||
$rot13 = "str_rot13" ascii wide
|
||||
$assert = "assert(" ascii wide
|
||||
$createfn = "create_function" ascii wide
|
||||
condition:
|
||||
// base64_decode + (eval|assert|create_function) = 解码后动态执行
|
||||
$b64 and ($eval or $assert or $createfn)
|
||||
or
|
||||
// 解码链:base64 + gzinflate / str_rot13 + 执行
|
||||
$b64 and ($gzinflate or $rot13) and ($eval or $assert)
|
||||
}
|
||||
|
||||
// PHP Webshell —— 变量变形($$a = $_POST['cmd'];$$a($_POST['arg']))
|
||||
rule C3_PHP_Webshell_VariableDeformation {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C3"
|
||||
false_positive_rate = "medium"
|
||||
reference = "PHP 变量变形 Webshell 特征"
|
||||
description = "PHP 可变变量组合:$$ 或 ${$ 配合超全局变量"
|
||||
strings:
|
||||
$doubledollar = /\$\$\w+\s*=\s*\$\s*_(GET|POST|REQUEST)/ ascii
|
||||
$curlyvar = /\$\{\$\w+\}\s*\(/ ascii
|
||||
$superglobal = /\$_/ ascii
|
||||
$invoke = /\$\$\w+\s*\(/ ascii
|
||||
condition:
|
||||
($doubledollar or ($curlyvar and $invoke)) and $superglobal
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// JSP / Java Webshell —— 反射执行 + 反序列化
|
||||
// =============================================================================
|
||||
|
||||
// JSP Runtime.exec + ProcessBuilder 反射执行链
|
||||
rule C3_JSP_Webshell_RuntimeExec {
|
||||
meta:
|
||||
risk_level = "critical"
|
||||
category = "C3"
|
||||
false_positive_rate = "low"
|
||||
reference = "https://blog.csdn.net/JavaWebshell"
|
||||
description = "JSP 通过 Runtime.exec / ProcessBuilder 执行命令,配合反射 / 密码变量(cmd/pass/pwd)"
|
||||
strings:
|
||||
$runtime = "Runtime.getRuntime()" ascii
|
||||
$exec = ".exec(" ascii
|
||||
$processbuilder = "ProcessBuilder" ascii
|
||||
$cmdparam = /(cmd|pass|pwd|exec|shell)\s*=/ ascii
|
||||
$reflection = /Class\.forName|getMethod|getDeclaredMethod|Method\.invoke/ ascii
|
||||
$requestparam = /request\.getParameter\s*\(\s*['"](cmd|pass|pwd|exec|shell)['"]/ ascii
|
||||
$printwriter = /PrintWriter|getWriter|out\.println/ ascii
|
||||
condition:
|
||||
// Runtime.exec + 命令参数名 + 回显 = 完整 Webshell
|
||||
$runtime and $exec and ($requestparam or $printwriter)
|
||||
or
|
||||
// ProcessBuilder + 命令参数名
|
||||
$processbuilder and ($cmdparam or $requestparam)
|
||||
or
|
||||
// 反射链 + getRuntime().exec
|
||||
$runtime and $exec and any of ($reflection*)
|
||||
}
|
||||
|
||||
// JSP 反序列化 CommonsCollections / ysoerial
|
||||
rule C3_JSP_Webshell_Deserialization {
|
||||
meta:
|
||||
risk_level = "critical"
|
||||
category = "C3"
|
||||
false_positive_rate = "low"
|
||||
reference = "https://github.com/frohoff/ysoserial"
|
||||
description = "Java 反序列化利用链:CommonsCollections / Gadgets / InvokerTransformer"
|
||||
strings:
|
||||
$icc = "InvokerTransformer" ascii wide
|
||||
$lzy = "LazyMap" ascii wide
|
||||
$trn = "TransformerFactory" ascii wide
|
||||
$ccimpl = "TemplatesImpl" ascii wide
|
||||
$gadget = "CommonsCollections" ascii wide
|
||||
$readobj = /readObject\s*\(/ ascii wide
|
||||
$objectinputstream = "ObjectInputStream" ascii wide
|
||||
$execchain = /getRuntime\(\)\.exec|ProcessBuilder/ ascii wide
|
||||
condition:
|
||||
// 反序列化链:readObject + InvokerTransformer / LazyMap / TemplatesImpl + Runtime.exec
|
||||
$readobj and ($icc or $lzy or $trn or $ccimpl or $gadget) and any of ($execchain*)
|
||||
or
|
||||
// 直接 ObjectInputStream + 已知 Gadget
|
||||
$objectinputstream and ($icc or $ccimpl or $gadget)
|
||||
}
|
||||
|
||||
// JSP Servlet Filter / Listener 注入型内存马
|
||||
rule C3_JSP_Webshell_MemoryShell {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C3"
|
||||
false_positive_rate = "medium"
|
||||
reference = "Tomcat / JBoss 内存马分析"
|
||||
description = "JSP 动态注册 Filter / Listener / Valve 实现内存 Webshell"
|
||||
strings:
|
||||
$filterdef = "FilterDef" ascii
|
||||
$applicationfilter = "ApplicationFilterConfig" ascii
|
||||
$addfilter = /addFilterDef|addFilterMap|addListener/ ascii
|
||||
$servletcontext = /ServletContext|getServletContext/ ascii
|
||||
$filter = "implements Filter" ascii
|
||||
$listener = /implements\s+(HttpSession|Servlet|Request)Listener/ ascii
|
||||
$standardctx = "StandardContext" ascii
|
||||
// 命令执行特征
|
||||
$runtime = "Runtime.getRuntime()" ascii
|
||||
$execchain = /getRuntime\(\)\.exec|ProcessBuilder/ ascii wide
|
||||
condition:
|
||||
// 动态 Filter 注册链:StandardContext + addFilterDef + FilterDef + ApplicationFilterConfig
|
||||
$standardctx and $addfilter and $filterdef and $applicationfilter
|
||||
or
|
||||
// Listener 注册链:ServletContext + Listener interface + addListener
|
||||
$servletcontext and $listener and any of ($addfilter)
|
||||
or
|
||||
// Filter 接口 + 命令执行(反射/内联)
|
||||
$filter and ($runtime or $execchain)
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// 冰蝎 / 哥斯拉 / 蚁剑 —— 工具专属特征
|
||||
// =============================================================================
|
||||
|
||||
// 冰蝎(Behinder)—— AES 加密通道 + 固定类名特征
|
||||
rule C3_Webshell_Behinder {
|
||||
meta:
|
||||
risk_level = "critical"
|
||||
category = "C3"
|
||||
false_positive_rate = "low"
|
||||
reference = "https://github.com/rebeyond/Behinder"
|
||||
description = "冰蝎 Webshell 特征:AES/CBC/PKCS5Padding 或反射解密"
|
||||
strings:
|
||||
$aes = /AES\s*\/?\s*CBC\s*\/?\s*PKCS5Padding|AES\/CBC\/PKCS5Padding/ ascii wide
|
||||
$cipherget = "Cipher.getInstance" ascii wide
|
||||
$doFinal = /\.doFinal\s*\(/ ascii wide
|
||||
$secret = /secretKey|SecretKeySpec|PasswordKey/ ascii wide
|
||||
$toolname = /Behinder|behinder|冰蝎/ ascii wide nocase
|
||||
// JSP 命令执行特征
|
||||
$execchain1 = /getRuntime\(\)\.exec/ ascii wide
|
||||
$execchain2 = "ProcessBuilder" ascii wide
|
||||
// PHP 执行特征
|
||||
$phpdecrypt = "openssl_decrypt" ascii
|
||||
$phpb64 = "base64_decode" ascii
|
||||
$phpeval = "eval(" ascii
|
||||
$phpassert = "assert(" ascii
|
||||
condition:
|
||||
// 冰蝎 JSP:AES 加密解密 + secretKey + Runtime.exec
|
||||
$cipherget and $aes and $doFinal and $secret and any of ($execchain*)
|
||||
or
|
||||
// 冰蝎 PHP:openssl_encrypt + base64 + eval/assert
|
||||
$phpdecrypt and $phpb64 and ($phpeval or $phpassert)
|
||||
or
|
||||
// 直接工具名(极低概率误报)
|
||||
$toolname
|
||||
}
|
||||
|
||||
// 哥斯拉(Godzilla)—— 加密通信 + 动态字节码加载
|
||||
rule C3_Webshell_Godzilla {
|
||||
meta:
|
||||
risk_level = "critical"
|
||||
category = "C3"
|
||||
false_positive_rate = "low"
|
||||
reference = "https://github.com/whale1017/godzilla"
|
||||
description = "哥斯拉 Webshell 特征:ASM 字节码生成 + ClassLoader 动态加载"
|
||||
strings:
|
||||
$asm = "org.objectweb.asm" ascii wide
|
||||
$classloader = /defineClass|ClassLoader|loadClass/ ascii wide
|
||||
$bytes = /toByteArray|writeByteArray/ ascii wide
|
||||
$reflect = /setAccessible|getDeclaredMethod/ ascii wide
|
||||
$deserialize = "deserialize" ascii wide
|
||||
$toolname = /Godzilla|godzilla|哥斯拉/ ascii wide nocase
|
||||
condition:
|
||||
// ASM 字节码 + ClassLoader.defineClass = 动态加载
|
||||
$asm and ($classloader or $bytes) and any of ($reflect*)
|
||||
or
|
||||
// 反序列化 + ClassLoader
|
||||
$deserialize and $classloader
|
||||
or
|
||||
$toolname
|
||||
}
|
||||
|
||||
// 蚁剑(AntSword)—— 基础 eval + 加密通信 + 自定义 Header
|
||||
rule C3_Webshell_AntSword {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C3"
|
||||
false_positive_rate = "medium"
|
||||
reference = "https://github.com/AntSwordProject/AntSword-Labs"
|
||||
description = "蚁剑 Webshell 特征:assert + 特定请求参数加密 + 自定义 HTTP 头"
|
||||
strings:
|
||||
$phpassert = /assert\s*\(\s*\$\s*_(GET|POST|REQUEST)/ ascii
|
||||
$phpcipher = /openssl_(encrypt|decrypt)|mcrypt_(encrypt|decrypt)/ ascii
|
||||
$header = /X-Request-Id|AntSword|antsword/ ascii
|
||||
$jspcipher = /AES|DES|RSA|Cipher/ ascii wide
|
||||
condition:
|
||||
// PHP:assert + openssl/mcrypt + 蚁剑特征 header
|
||||
$phpassert and $phpcipher and $header
|
||||
or
|
||||
// JSP:加密算法 + 特征 header(可能是蚁剑 JSP 变体)
|
||||
any of ($jspcipher) and $header
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// ASP / ASP.NET Webshell
|
||||
// =============================================================================
|
||||
|
||||
// ASP.NET Eval / Execute + Server.CreateObject("Wscript.Shell")
|
||||
rule C3_Webshell_ASPNET {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C3"
|
||||
false_positive_rate = "low"
|
||||
reference = "ASP.NET Webshell 常见手法"
|
||||
description = "ASP.NET Webshell:Eval/Execute + Server.CreateObject/Wscript.Shell + Process.Start"
|
||||
strings:
|
||||
$eval = /\bEval\s*\(\s*Request\s*\(/ ascii wide
|
||||
$execute = /\bExecute\s*\(\s*Request\s*\(/ ascii wide
|
||||
$wscript = /Server\.CreateObject\s*\(\s*["']Wscript\.Shell["']\s*\)/ ascii wide
|
||||
$processstart = /Process\.Start|Diagnostics\.Process/ ascii wide
|
||||
$reflect = /Activator\.CreateInstance|Assembly\.Load|BinaryFormatter/ ascii wide
|
||||
condition:
|
||||
// Eval + 动态执行
|
||||
($eval or $execute) and ($wscript or $processstart or any of ($reflect*))
|
||||
or
|
||||
// Wscript.Shell + Process.Start
|
||||
$wscript and $processstart
|
||||
or
|
||||
// BinaryFormatter 反序列化 + 命令执行
|
||||
any of ($reflect*) and $processstart
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// ASP Classic (VBScript)
|
||||
// =============================================================================
|
||||
|
||||
rule C3_Webshell_ASP_Classic {
|
||||
meta:
|
||||
risk_level = "high"
|
||||
category = "C3"
|
||||
false_positive_rate = "medium"
|
||||
reference = "ASP Classic Webshell"
|
||||
description = "ASP Classic (VBScript) Webshell:Execute + Wscript.Shell + Request"
|
||||
strings:
|
||||
$execute = /\bExecute\s*\(\s*Request\s*\(/ ascii
|
||||
$wscript = "WScript.Shell" ascii
|
||||
$shellrun = /\.Run\s*\(\s*["']cmd/ ascii
|
||||
$servercreate = "Server.CreateObject" ascii
|
||||
$request = "Request(" ascii
|
||||
condition:
|
||||
// Execute + Request 取参
|
||||
$execute and $request
|
||||
or
|
||||
// Server.CreateObject(WScript.Shell) + cmd Run
|
||||
$servercreate and $wscript and $shellrun
|
||||
}
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// 通用:所有 Webshell 类(PHP/JSP/ASP)的 ProcessBuilder + 输出回显
|
||||
// =============================================================================
|
||||
|
||||
rule C3_Webshell_CommandExecutionEcho {
|
||||
meta:
|
||||
risk_level = "critical"
|
||||
category = "C3"
|
||||
false_positive_rate = "low"
|
||||
reference = "综合 Webshell 命令执行链"
|
||||
description = "任何语言的 Webshell:命令执行 + 输出回显(三特征同时命中)"
|
||||
strings:
|
||||
$exec_php = /(system|exec|passthru|shell_exec|popen|proc_open)\s*\(\s*\$\s*_(GET|POST|REQUEST)/ ascii
|
||||
$exec_java = /Runtime\.getRuntime\(\)\.exec|ProcessBuilder/ ascii
|
||||
$exec_asp = /\.Run\s*\(\s*["']cmd|Process\.Start/ ascii
|
||||
// 回显通道
|
||||
$echo_php = /echo|print|passthru/ ascii
|
||||
$echo_java = /getWriter|getOutputStream|PrintWriter|out\.println|response\.getWriter/ ascii
|
||||
$echo_asp = /Response\.Write|output\.Write/ ascii
|
||||
// 参数来源(外部可控)
|
||||
$param_java = /request\.getParameter|HttpServletRequest|getParameter/ ascii wide
|
||||
$param_php = /\$_(GET|POST|REQUEST)\s*\[/ ascii
|
||||
$param_asp = /Request\("|\bRequest\(/ ascii
|
||||
condition:
|
||||
// PHP 路径
|
||||
$exec_php and $echo_php and $param_php
|
||||
or
|
||||
// Java/JSP 路径
|
||||
$exec_java and any of ($echo_java*) and any of ($param_java*)
|
||||
or
|
||||
// ASP 路径
|
||||
$exec_asp and $echo_asp and ($param_php or $param_asp)
|
||||
}
|
||||
Reference in New Issue
Block a user