Linux应急响应 - 30 YARA规则

YARA 规则编写与应用

YARA 被称为”恶意软件研究人员的瑞士军刀”。通过编写模式匹配规则,可以在文件系统中快速扫描出恶意文件。本章从语法入门到实战规则,帮你建立完整的 YARA 应用能力。

相关章节:06-文件系统取证 | 14.5-挖矿病毒应急

一、YARA 是什么

1.1 基本概念

YARA 是由 VirusTotal 的 Victor Alvarez 开发的恶意软件识别和分类工具

核心思想:通过定义文本模式、十六进制模式和条件组合来描述恶意软件特征

类比理解:正则表达式用于匹配字符串,YARA 规则用于匹配文件

可以同时匹配文件中的多个特征并设定组合条件

1.2 在应急响应中的应用

主要用途

扫描文件系统,找到已知恶意软件

检测 Webshell、挖矿程序、勒索软件、Rootkit

对取证恢复的文件进行批量分类

内存扫描(配合 Volatility)

优势

规则可读性强,易于编写和维护

扫描速度快,适合大规模扫描

社区有大量现成规则可用

可以自定义针对特定攻击的规则

使用场景

事件期间:扫描 /var/www、/tmp、/dev/shm 等目录

事后排查:对磁盘镜像进行全面扫描

持续监控:集成到定期扫描任务中

二、YARA 规则语法

2.1 基本结构

每个 YARA 规则包含三个部分:meta(元信息)、strings(字符串定义)、condition(匹配条件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
rule ExampleRule
{
meta:
description = "示例规则"
author = "Your Name"
date = "2026-04-02"
severity = "high"

strings:
$text1 = "malicious string"
$text2 = "another pattern"
$hex1 = { 6D 61 6C 77 61 72 65 }
$regex1 = /evil[0-9]+\.php/

condition:
any of them
}

meta 部分:描述性信息,不影响匹配逻辑

常用字段:description、author、date、reference、severity、hash

strings 部分:定义要搜索的模式

condition 部分:定义匹配逻辑

2.2 字符串类型

文本字符串(Text Strings)

1
2
3
4
5
6
7
8
9
strings:
$s1 = "malware" # 精确匹配
$s2 = "MaLwArE" nocase # 不区分大小写
$s3 = "hello\x00world" wide # 宽字符(UTF-16)
$s4 = "test" wide ascii # 同时匹配 ASCII 和 UTF-16
$s5 = "pattern" fullword # 全词匹配(前后不能有字母数字)
$s6 = "base64" base64 # 匹配 Base64 编码后的字符串
$s7 = "xor_string" xor # 匹配 XOR 编码后的字符串(尝试所有单字节 key)
$s8 = "xor_string" xor(0x01-0xFF) # 指定 XOR key 范围

十六进制字符串(Hex Strings)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
strings:
# 精确十六进制序列
$h1 = { 4D 5A 90 00 } # MZ 头(PE 文件)

# 通配符(? 匹配任意半字节)
$h2 = { 4D 5A ?? ?? 00 } # MZ 后两字节任意

# 跳跃([min-max] 匹配指定范围长度)
$h3 = { 4D 5A [2-10] 50 45 } # MZ 和 PE 之间有 2-10 字节

# 选择(| 表示或)
$h4 = { (4D 5A | 7F 45 4C 46) } # MZ 头或 ELF 头

# 无限跳跃
$h5 = { 4D 5A [-] 50 45 00 00 } # MZ 和 PE 之间任意字节

正则表达式(Regular Expressions)

1
2
3
4
5
strings:
$r1 = /https?:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}/ # URL
$r2 = /([0-9]{1,3}\.){3}[0-9]{1,3}/ # IP 地址
$r3 = /eval\s*\(\s*(base64_decode|gzinflate|gzuncompress)/ # PHP 混淆
$r4 = /[A-Za-z0-9+\/]{50,}={0,2}/ # Base64 编码

2.3 条件表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
condition:
# 基本逻辑
$s1 and $s2 # 同时包含 s1 和 s2
$s1 or $s2 # 包含 s1 或 s2
not $s1 # 不包含 s1

# 量词
any of them # 任意一个字符串匹配
all of them # 所有字符串都匹配
2 of them # 至少 2 个字符串匹配
3 of ($s*) # 以 s 开头的字符串中至少 3 个匹配
any of ($webshell_*) # 以 webshell_ 开头的任意一个匹配

# 文件大小
filesize < 500KB # 文件小于 500KB
filesize > 1MB and filesize < 50MB

# 字符串出现次数
#s1 > 5 # s1 出现超过 5 次

# 字符串位置
$s1 at 0 # s1 在文件开头
$s1 in (0..100) # s1 在文件前 100 字节内

# 特殊条件
uint16(0) == 0x5A4D # 文件前 2 字节为 MZ(PE 文件)
uint32(0) == 0x464C457F # ELF 文件魔数

# 入口点(PE 文件)
$s1 at entrypoint # 字符串在 PE 入口点

# 组合条件
filesize < 100KB and (2 of ($s*) or $hex1)

2.4 完整语法示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import "pe"
import "elf"
import "math"

rule SuspiciousELF
{
meta:
description = "检测可疑的 ELF 二进制文件"
author = "IR Team"
date = "2026-04-02"

strings:
$s1 = "/bin/sh" fullword
$s2 = "/bin/bash" fullword
$s3 = "socket" fullword
$s4 = "connect" fullword
$s5 = "/etc/shadow" fullword
$s6 = "/etc/passwd" fullword
$enc1 = "base64" nocase
$enc2 = { 78 6F 72 } // "xor"

condition:
uint32(0) == 0x464C457F // ELF 魔数
and filesize < 5MB
and (
(3 of ($s*))
or
(any of ($enc*) and 2 of ($s*))
)
}

三、实战规则编写

以下每条规则都经过实际测试,可直接使用。建议保存为独立的 .yar 文件,按需组合。

3.1 Webshell 检测规则(PHP)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
rule PHP_Webshell_Generic
{
meta:
description = "检测常见 PHP Webshell 特征"
author = "IR Team"
date = "2026-04-02"
severity = "critical"
filetype = "php"

strings:
// 危险函数调用
$func1 = "eval(" nocase
$func2 = "assert(" nocase
$func3 = "system(" nocase
$func4 = "exec(" nocase
$func5 = "shell_exec(" nocase
$func6 = "passthru(" nocase
$func7 = "popen(" nocase
$func8 = "proc_open(" nocase
$func9 = "pcntl_exec(" nocase

// 编码/混淆特征
$enc1 = "base64_decode(" nocase
$enc2 = "gzinflate(" nocase
$enc3 = "gzuncompress(" nocase
$enc4 = "str_rot13(" nocase
$enc5 = "rawurldecode(" nocase

// 动态函数调用(常见的混淆手法)
$dyn1 = /\$[a-zA-Z_]+\s*\(/
$dyn2 = "create_function(" nocase
$dyn3 = "call_user_func(" nocase
$dyn4 = "preg_replace" nocase
$dyn5 = /\$_(GET|POST|REQUEST|COOKIE)\s*\[/

// 已知 Webshell 特征
$known1 = "c99shell" nocase
$known2 = "r57shell" nocase
$known3 = "b374k" nocase
$known4 = "China Chopper" nocase
$known5 = "AntSword" nocase
$known6 = "Behinder" nocase
$known7 = "Godzilla" nocase
$known8 = "ice scorpion" nocase

condition:
// 文件必须包含 PHP 标记
(uint32(0) == 0x68703F3C or // <?ph
uint16(0) == 0x3F3C) // <?
and filesize < 500KB
and (
// 任何已知 Webshell 名称
any of ($known*)
or
// 危险函数 + 编码函数组合
(any of ($func*) and any of ($enc*))
or
// 从请求参数获取内容并执行
(any of ($func*) and any of ($dyn5))
or
// 多个危险函数同时出现
(3 of ($func*))
)
}

3.2 Webshell 检测规则(JSP)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
rule JSP_Webshell_Generic
{
meta:
description = "检测常见 JSP Webshell 特征"
author = "IR Team"
date = "2026-04-02"
severity = "critical"
filetype = "jsp"

strings:
// Runtime 命令执行
$exec1 = "Runtime.getRuntime().exec(" nocase
$exec2 = "ProcessBuilder" nocase
$exec3 = "getRuntime()" nocase

// 反射调用
$ref1 = "Class.forName(" nocase
$ref2 = "getMethod(" nocase
$ref3 = "invoke(" nocase
$ref4 = "defineClass(" nocase

// 请求参数获取
$req1 = "request.getParameter(" nocase
$req2 = "request.getInputStream()" nocase

// 文件操作
$file1 = "FileOutputStream" nocase
$file2 = "FileWriter" nocase

// Base64 解码
$b64_1 = "Base64.getDecoder" nocase
$b64_2 = "base64Decode" nocase
$b64_3 = "sun.misc.BASE64Decoder" nocase

// 已知 JSP Webshell 特征
$known1 = "JspSpy" nocase
$known2 = "cmdjsp" nocase
$known3 = "chopper" nocase

condition:
filesize < 500KB
and (
any of ($known*)
or
(any of ($exec*) and any of ($req*))
or
(any of ($ref*) and any of ($b64_*) and any of ($req*))
)
}

3.3 挖矿程序检测规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
rule CryptoMiner_Generic
{
meta:
description = "检测加密货币挖矿程序"
author = "IR Team"
date = "2026-04-02"
severity = "high"
reference = "通用挖矿特征"

strings:
// 矿池域名和协议
$pool1 = "stratum+tcp://" nocase
$pool2 = "stratum+ssl://" nocase
$pool3 = "stratum2+tcp://" nocase
$pool4 = "pool.minexmr.com" nocase
$pool5 = "xmrpool.eu" nocase
$pool6 = "pool.supportxmr.com" nocase
$pool7 = "mine.c3pool.com" nocase
$pool8 = "gulf.moneroocean.stream" nocase
$pool9 = ".nicehash.com" nocase
$pool10 = "f2pool.com" nocase
$pool11 = "nanopool.org" nocase

// 挖矿相关字符串
$mining1 = "cryptonight" nocase
$mining2 = "randomx" nocase
$mining3 = "hashrate" nocase
$mining4 = "mining" nocase
$mining5 = "miner" nocase
$mining6 = "XMRig" nocase
$mining7 = "cpuminer" nocase
$mining8 = "ccminer" nocase

// 钱包地址模式(门罗币地址以 4 或 8 开头,95 个字符)
$wallet1 = /[48][0-9AB][1-9A-HJ-NP-Za-km-z]{93}/

// 挖矿配置关键词
$config1 = "\"algo\"" nocase
$config2 = "\"pool\"" nocase
$config3 = "\"wallet\"" nocase
$config4 = "\"coin\"" nocase
$config5 = "\"threads\"" nocase
$config6 = "donate-level" nocase

condition:
(
// ELF 文件包含矿池或挖矿特征
(uint32(0) == 0x464C457F and (any of ($pool*) or 2 of ($mining*)))
or
// 配置文件包含矿池和钱包
(any of ($pool*) and any of ($wallet*))
or
// 配置文件特征
(3 of ($config*) and any of ($pool*))
or
// 脚本文件中的挖矿特征
(any of ($pool*) and any of ($mining*))
)
}

3.4 反弹 Shell 脚本检测规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
rule ReverseShell_Script
{
meta:
description = "检测反弹 Shell 脚本"
author = "IR Team"
date = "2026-04-02"
severity = "critical"

strings:
// Bash 反弹 Shell
$bash1 = "bash -i >& /dev/tcp/" nocase
$bash2 = "bash -c 'bash -i >& /dev/tcp/" nocase
$bash3 = "/dev/tcp/"
$bash4 = "0>&1"

// Netcat 反弹
$nc1 = "nc -e /bin/sh" nocase
$nc2 = "nc -e /bin/bash" nocase
$nc3 = "ncat -e /bin/sh" nocase
$nc4 = "nc.traditional -e" nocase
$nc5 = /mkfifo\s+\S+;\s*cat\s+\S+\s*\|\s*\/bin\/(sh|bash)/

// Python 反弹
$py1 = "socket.socket(socket.AF_INET" nocase
$py2 = "subprocess.call([\"/bin/sh\"" nocase
$py3 = "pty.spawn(\"/bin/sh\")" nocase
$py4 = "pty.spawn(\"/bin/bash\")" nocase
$py5 = "os.dup2(s.fileno()" nocase

// Perl 反弹
$perl1 = "perl -e 'use Socket;" nocase
$perl2 = "perl -MIO -e" nocase

// PHP 反弹
$php1 = "fsockopen(" nocase
$php2 = "php -r '$sock=fsockopen(" nocase
$php3 = "exec(\"/bin/sh -i" nocase

// Ruby 反弹
$ruby1 = "TCPSocket.new" nocase
$ruby2 = "ruby -rsocket" nocase

// 通用特征
$gen1 = "/bin/sh -i"
$gen2 = "0<&196;exec 196<>/dev/tcp/"
$gen3 = "exec 5<>/dev/tcp/"

condition:
filesize < 1MB
and (
($bash1 or $bash2)
or ($bash3 and $bash4)
or any of ($nc*)
or (2 of ($py*))
or any of ($perl*)
or ($php1 and $php3)
or any of ($ruby*)
or any of ($gen*)
)
}

3.5 Rootkit 特征检测规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
rule Linux_Rootkit_Generic
{
meta:
description = "检测 Linux Rootkit 常见特征"
author = "IR Team"
date = "2026-04-02"
severity = "critical"

strings:
// 内核模块 Rootkit 特征
$km1 = "init_module" fullword
$km2 = "cleanup_module" fullword
$km3 = "module_hide" nocase
$km4 = "rootkit" nocase
$km5 = "hide_proc" nocase
$km6 = "hide_file" nocase
$km7 = "hide_port" nocase
$km8 = "sys_call_table" nocase

// 系统调用劫持
$hook1 = "sys_read" fullword
$hook2 = "sys_write" fullword
$hook3 = "sys_getdents" fullword
$hook4 = "sys_getdents64" fullword
$hook5 = "sys_kill" fullword
$hook6 = "sys_open" fullword
$hook7 = "vfs_read" fullword
$hook8 = "tcp4_seq_show" fullword

// LD_PRELOAD Rootkit 特征
$ld1 = "LD_PRELOAD" fullword
$ld2 = "readdir" fullword
$ld3 = "dlsym" fullword
$ld4 = "RTLD_NEXT" fullword
$ld5 = "/proc/net/tcp"
$ld6 = "/etc/ld.so.preload"

// 已知 Rootkit 名称
$known1 = "Diamorphine" nocase
$known2 = "Reptile" nocase
$known3 = "Beurk" nocase
$known4 = "Jynx" nocase
$known5 = "Azazel" nocase
$known6 = "bdvl" nocase
$known7 = "Adore-ng" nocase
$known8 = "knark" nocase

condition:
(
// 已知 Rootkit 名称
any of ($known*)
or
// ELF 内核模块包含隐藏功能
(uint32(0) == 0x464C457F and 2 of ($km*) and any of ($hook*))
or
// LD_PRELOAD 类型 Rootkit(共享库劫持系统调用)
(uint32(0) == 0x464C457F and 3 of ($ld*))
or
// 多个系统调用劫持特征
(uint32(0) == 0x464C457F and 4 of ($hook*))
)
}

3.6 勒索信检测规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
rule Ransomware_Note
{
meta:
description = "检测勒索信文件"
author = "IR Team"
date = "2026-04-02"
severity = "critical"

strings:
// 常见勒索信关键词
$ransom1 = "your files have been encrypted" nocase
$ransom2 = "your data has been encrypted" nocase
$ransom3 = "all your files" nocase
$ransom4 = "decrypt your files" nocase
$ransom5 = "recover your files" nocase
$ransom6 = "files are encrypted" nocase

// 支付相关
$pay1 = "bitcoin" nocase
$pay2 = "btc" fullword nocase
$pay3 = "monero" nocase
$pay4 = "xmr" fullword nocase
$pay5 = "ransom" nocase
$pay6 = "payment" nocase
$pay7 = "wallet" nocase
$pay8 = "tor browser" nocase
$pay9 = ".onion" nocase

// 比特币地址模式
$btc_addr = /[13][a-km-zA-HJ-NP-Z1-9]{25,34}/
// 门罗币地址模式
$xmr_addr = /[48][0-9AB][1-9A-HJ-NP-Za-km-z]{93}/

// 威胁用语
$threat1 = "do not try to" nocase
$threat2 = "do not attempt" nocase
$threat3 = "will be permanently" nocase
$threat4 = "will be destroyed" nocase
$threat5 = "unique decryption key" nocase

condition:
filesize < 100KB
and (
// 加密提示 + 支付要求
(any of ($ransom*) and 2 of ($pay*))
or
// 加密提示 + 加密货币地址
(any of ($ransom*) and ($btc_addr or $xmr_addr))
or
// 支付要求 + 威胁 + 暗网地址
(2 of ($pay*) and any of ($threat*) and $pay9)
)
}

四、YARA 使用方法

4.1 安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Ubuntu / Debian
sudo apt install yara -y

# CentOS / RHEL
sudo yum install epel-release -y
sudo yum install yara -y

# 从源码编译(获取最新版本)
sudo apt install automake libtool make gcc pkg-config libssl-dev libjansson-dev libmagic-dev -y
git clone https://github.com/VirusTotal/yara.git
cd yara
./bootstrap.sh
./configure --with-crypto --enable-magic --enable-cuckoo
make && sudo make install
sudo ldconfig

# 验证
yara --version

# 安装 Python 绑定(可选,用于脚本集成)
pip3 install yara-python

4.2 基本扫描命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 扫描单个文件
yara rule.yar /path/to/suspicious_file

# 递归扫描目录(-r 递归)
yara -r rules.yar /var/www/html/

# 显示匹配的字符串(-s 显示匹配细节)
yara -s rules.yar /path/to/file

# 显示匹配规则的 meta 信息(-m)
yara -m rules.yar /path/to/file

# 显示匹配的规则名和标签(-g 显示标签)
yara -g rules.yar /path/to/file

# 多线程扫描(-p 指定线程数)
yara -r -p 4 rules.yar /var/www/

# 扫描超时(-a 秒数,避免卡在大文件上)
yara -r -a 30 rules.yar /var/www/

# 快速匹配模式(-f 找到第一个匹配就停止)
yara -r -f rules.yar /var/www/

# 输出未匹配的文件(-n 取反)
yara -r -n rules.yar /var/www/

4.3 多规则文件合并扫描

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 方法一:将多个规则写在同一个文件中
cat webshell.yar miner.yar rootkit.yar > all_rules.yar
yara -r all_rules.yar /var/www/

# 方法二:使用 include 指令
cat > master.yar << 'EOF'
include "webshell.yar"
include "miner.yar"
include "rootkit.yar"
include "reverse_shell.yar"
include "ransomware.yar"
EOF
yara -r master.yar /var/www/

# 方法三:遍历规则目录
for rule in /opt/yara-rules/*.yar; do
yara -r "$rule" /var/www/html/ 2>/dev/null
done

4.4 与 find 结合使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 只扫描特定类型的文件
find /var/www -name "*.php" -exec yara webshell.yar {} \;

# 扫描最近 7 天内修改过的文件
find /var/www -mtime -7 -type f -exec yara -s all_rules.yar {} \;

# 扫描特定大小范围的文件
find / -type f -size +1k -size -500k -exec yara miner.yar {} \; 2>/dev/null

# 扫描可疑目录中的所有文件
find /tmp /var/tmp /dev/shm /run -type f -exec yara -s all_rules.yar {} \; 2>/dev/null

# 批量扫描并保存结果
find /var/www -name "*.php" -print0 | xargs -0 -P 4 -I {} yara -s webshell.yar {} > /tmp/yara_results.txt 2>&1

4.5 实用扫描脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/bin/bash
# yara-scan.sh - 自动化 YARA 扫描脚本

RULES_DIR="/opt/yara-rules"
SCAN_DIRS="/var/www /tmp /var/tmp /dev/shm /opt /home"
OUTPUT="/tmp/yara_scan_$(date +%Y%m%d_%H%M%S).txt"

echo "========================================" | tee "$OUTPUT"
echo "YARA 扫描报告" | tee -a "$OUTPUT"
echo "扫描时间: $(date)" | tee -a "$OUTPUT"
echo "规则目录: $RULES_DIR" | tee -a "$OUTPUT"
echo "扫描目录: $SCAN_DIRS" | tee -a "$OUTPUT"
echo "========================================" | tee -a "$OUTPUT"

# 合并所有规则
MERGED_RULES="/tmp/merged_rules.yar"
cat "$RULES_DIR"/*.yar > "$MERGED_RULES" 2>/dev/null

TOTAL_MATCHES=0

for dir in $SCAN_DIRS; do
if [ -d "$dir" ]; then
echo "" | tee -a "$OUTPUT"
echo "[*] 扫描目录: $dir" | tee -a "$OUTPUT"
results=$(yara -r -s -m "$MERGED_RULES" "$dir" 2>/dev/null)
if [ -n "$results" ]; then
echo "$results" | tee -a "$OUTPUT"
count=$(echo "$results" | wc -l)
TOTAL_MATCHES=$((TOTAL_MATCHES + count))
echo "[!] 发现 $count 个匹配" | tee -a "$OUTPUT"
else
echo " 未发现匹配" | tee -a "$OUTPUT"
fi
fi
done

echo "" | tee -a "$OUTPUT"
echo "========================================" | tee -a "$OUTPUT"
echo "扫描完成,总共发现 $TOTAL_MATCHES 个匹配" | tee -a "$OUTPUT"
echo "详细报告: $OUTPUT" | tee -a "$OUTPUT"

# 清理
rm -f "$MERGED_RULES"

五、社区规则源

5.1 YARA-Rules 项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# GitHub 上最大的 YARA 规则社区集合
git clone https://github.com/Yara-Rules/rules.git /opt/yara-community-rules

# 目录结构:
# rules/
# ├── malware/ # 恶意软件规则
# ├── webshells/ # Webshell 规则
# ├── packers/ # 加壳检测规则
# ├── crypto/ # 加密相关规则
# ├── cve_rules/ # CVE 利用检测
# └── ...

# 使用社区规则扫描
yara -r /opt/yara-community-rules/webshells/index.yar /var/www/html/

5.2 signature-base 项目(Neo23x0)

1
2
3
4
5
6
7
8
9
10
11
12
# Florian Roth 维护的高质量规则集
git clone https://github.com/Neo23x0/signature-base.git /opt/signature-base

# 包含:
# - 恶意软件签名
# - Webshell 签名
# - 漏洞利用工具签名
# - APT 组织工具签名
# - Hack 工具签名

# 使用
yara -r /opt/signature-base/yara/*.yar /var/www/html/

5.3 Loki Scanner(集成 YARA)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Loki 是一个集成了 YARA 的 IOC 扫描器
# 内置了大量规则,开箱即用

git clone https://github.com/Neo23x0/Loki.git /opt/loki
cd /opt/loki
pip3 install -r requirements.txt

# 更新规则
python3 loki.py --update

# 扫描目录
python3 loki.py -p /var/www/html/

# 扫描整个系统
sudo python3 loki.py -p / --noindicator --dontwait

# 只扫描特定类型
python3 loki.py -p /var/www/ --filetypes php,jsp,asp

# Loki 的优势:
# - 内置 signature-base 规则库
# - 自动更新规则
# - 集成了 hash IOC 检查
# - 文件名 IOC 检查
# - C2 域名 IOC 检查
# - 彩色输出,结果一目了然

5.4 Thor(商业版)

Thor 是 Loki 的商业增强版,由 Nextron Systems 开发

额外功能:更多规则、内存扫描、性能优化、企业支持

适合需要商业支持和 SLA 的企业环境

5.5 其他规则源

来源 URL 说明
InQuest https://github.com/InQuest/yara-rules 文件分析和恶意文档规则
ReversingLabs https://github.com/reversinglabs/reversinglabs-yara-rules 大量恶意软件家族规则
Elastic https://github.com/elastic/protections-artifacts Elastic Security 规则
GCTI https://github.com/chronicle/GCTI Google Cloud Threat Intelligence
Malpedia https://malpedia.caad.fkie.fraunhofer.de/ 恶意软件百科(含 YARA 规则)

六、实战:用 YARA 扫描实验环境

6.1 场景设定

某服务器疑似被入侵,需要用 YARA 扫描文件系统找出恶意文件

目标目录:/var/www/html(Web 目录)、/tmp、/var/tmp

6.2 操作步骤

Step 1:准备规则文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 创建规则目录
mkdir -p /opt/ir-yara-rules

# 将本章中的规则保存为独立文件
# webshell_php.yar - PHP Webshell 规则
# webshell_jsp.yar - JSP Webshell 规则
# cryptominer.yar - 挖矿程序规则
# reverse_shell.yar - 反弹 Shell 规则
# rootkit.yar - Rootkit 规则
# ransomware.yar - 勒索信规则

# 创建主规则文件
cat > /opt/ir-yara-rules/master.yar << 'EOF'
include "webshell_php.yar"
include "webshell_jsp.yar"
include "cryptominer.yar"
include "reverse_shell.yar"
include "rootkit.yar"
include "ransomware.yar"
EOF

# 同时下载社区规则
git clone https://github.com/Neo23x0/signature-base.git /opt/signature-base 2>/dev/null

Step 2:执行扫描

1
2
3
4
5
6
7
8
9
10
11
# 扫描 Web 目录(重点)
echo "=== 扫描 Web 目录 ==="
yara -r -s -m /opt/ir-yara-rules/master.yar /var/www/html/ 2>/dev/null | tee /tmp/yara_web.txt

# 扫描临时目录
echo "=== 扫描临时目录 ==="
yara -r -s -m /opt/ir-yara-rules/master.yar /tmp/ /var/tmp/ /dev/shm/ 2>/dev/null | tee /tmp/yara_tmp.txt

# 使用 Loki 做全面扫描
cd /opt/loki
sudo python3 loki.py -p /var/www/html/ --csv --logfile /tmp/loki_results.csv

Step 3:分析结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 查看扫描结果
echo "=== YARA 匹配汇总 ==="
cat /tmp/yara_web.txt /tmp/yara_tmp.txt | sort

# 对发现的可疑文件进行进一步分析
# 假设发现 /var/www/html/uploads/image.php 匹配了 Webshell 规则

# 查看文件内容
cat /var/www/html/uploads/image.php

# 计算文件 hash
sha256sum /var/www/html/uploads/image.php
md5sum /var/www/html/uploads/image.php

# 查看文件元数据
stat /var/www/html/uploads/image.php

# 查看文件的访问日志
grep "image.php" /var/log/nginx/access.log

# 提交 hash 到 VirusTotal 查询
# 或使用 vt-cli:vt file <hash>

Step 4:生成报告

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 汇总所有发现
cat << 'REPORT' > /tmp/yara_report.txt
============================================
YARA 扫描报告
扫描时间: 2026-04-02
扫描范围: /var/www/html, /tmp, /var/tmp, /dev/shm
使用规则: 自定义规则 + signature-base

发现的恶意文件:
1. /var/www/html/uploads/image.php
- 匹配规则: PHP_Webshell_Generic
- SHA-256: <hash>
- 创建时间: <timestamp>
- 分析: 包含 eval() + base64_decode(),疑似蚁剑 Webshell

2. /tmp/.cache/kworker
- 匹配规则: CryptoMiner_Generic
- SHA-256: <hash>
- 创建时间: <timestamp>
- 分析: XMRig 挖矿程序,连接矿池 pool.minexmr.com

建议措施:
- 立即隔离受影响的文件
- 查找文件的上传来源(分析 Web 日志)
- 检查是否有其他被植入的文件
- 修复导致文件上传的漏洞
============================================
REPORT

6.3 注意事项

YARA 扫描可能产生误报,发现匹配后要人工确认

大规模扫描时注意对系统性能的影响(使用 nice/ionice 降低优先级)

1
2
# 降低扫描优先级,减少对业务的影响
nice -n 19 ionice -c 3 yara -r rules.yar /var/www/

定期更新规则库,新的恶意软件不断出现

高度混淆的恶意文件可能绕过 YARA 规则,需要结合其他分析手段

参考与延伸

官方资源

YARA 官方文档:https://yara.readthedocs.io/

YARA GitHub:https://github.com/VirusTotal/yara

Loki:https://github.com/Neo23x0/Loki

规则编写参考

《YARA in a Nutshell》- 快速入门指南

VirusTotal Hunting - 在线测试 YARA 规则

下一步:学习 31-自动化排查脚本,将 YARA 集成到自动化排查流程中


上一章 目录 下一章
29-取证工具 Linux应急响应 31-自动化排查脚本