官方网址:https://yara.readthedocs.io/
github地址:https://github.com/VirusTotal/yara/releases
1 概述
YARA 是一种旨在(但不限于)帮助恶意软件研究人员识别和分类恶意软件样本的工具。使用 YARA,您可以基于文本或二进制模式创建恶意软件系列(或任何您想描述的内容)的描述。每个描述,也就是规则,由一组字符串和一个确定其逻辑的布尔表达式组成。
举例:任何包含三个字符串之一的文件都必须报告为 Silent_banker
rule silent_banker : banker
{
meta:
description = "This is just an example"
threat_level = 3
in_the_wild = true
strings:
$a = {6A 40 68 00 30 00 00 6A 14 8D 91}
$b = {8D 4D B0 2B C1 83 C0 27 99 6A 4E 59 F7 F9}
$c = "UVODFRYSIHLNWPEJXQZAKCBGMT"
condition:
$a or $b or $c
}
1.1 yara支持的格式
字符串格式:$my_text_string = “text here”
十六进制格式:$my_hex_string = { E2 34 A1 C8 23 FB }
正则表达式格式:$re1 = /md5: [0-9a-fA-F]{32}/
2 YARA规则
YARA 中的每条规则都以关键字开头,rule 后跟规则标识符。
标识符必须遵循与 C 编程语言相同的词汇约定,它们可以包含任何字母数字字符和下划线字符,但第一个字符不能是数字。规则标识符区分大小写,不能超过 128 个字符。
规则通常由两部分组成:字符串定义和条件。
如果规则不依赖于任何字符串,则可以省略字符串定义部分,但始终需要条件部分。字符串定义部分是定义将成为规则一部分的字符串的地方。
2.1 字符串定义部分
每个字符串都有一个标识符,由 $ 字符后跟一系列字母数字字符和下划线组成,这些标识符可用于条件部分以引用相应的字符串。例如$a = {6A 40 68 00 30 00 00 6A 14 8D 91}
字符串可以以文本或十六进制形式定义,例如:
$my_text_string = “text here”
$my_hex_string = { E2 34 A1 C8 23 FB }
2.2 条件定义部分
条件部分是规则逻辑所在的地方。该部分必须包含一个布尔表达式,说明在何种情况下文件或进程满足规则。
通常,条件将通过使用它们的标识符来引用先前定义的字符串。在这种情况下,字符串标识符充当布尔变量,如果在文件或进程内存中找到字符串,则该变量评估为真,否则为假。
例如:
condition:
$my_text_string or $my_hex_strins
2.3 注释
单行://
多行:/* */
2.4 字符串
YARA 中有三种类型的字符串:
- 十六进制字符串
- 文本字符串
- 正则表达式。
2.4.1 十六进制字符串
十六进制字符串允许使用三种特殊结构:
- 通配符:放入字符串中的占位符,表明某些字节是未知的,它们应该匹配任何内容。占位符是问号 (?),例如:$hex_string = { E2 34 ?? C8 A? FB }
- 跳转:不知道长度时,使用跳转。例如:$hex_string = { F4 23 [4-6] 62 B4 }。这个跳转表示任何 4 到 6 个字节的任意序列都可以占据跳转的位置。任何跳转 [XY] 都必须满足条件 0 <= X <= Y。
将匹配以下:
F4 23 01 02 03 04 62 B4
F4 23 00 00 00 00 00 62 B4
F4 23 15 82 A3 04 45 22 62 B4
FE 39 45 [6-6] 89 00 等于 FE 39 45 ?? ?? ?? ?? ?? ?? 89 00
FE 39 45 [10–] 89 00 10-无穷大
FE 39 45 [–] 89 00 0-无穷大
- 替代:十六进制有不同的替代方案。例如:$hex_string = { F4 23 ( 62 B4 | 56 ) 45 }
2.4.2 文本字符串
例如: $text_string = “foobar”
可以包括:ASCII 编码、区分大小写的字符串
文本字符串可以附带一些有用的修饰符,这些修饰符可以改变字符串的解释方式。这些修饰符附加在由空格分隔的字符串定义的末尾,如下所述。
\" |
双引号 |
\\ |
反斜杠 |
\r |
回车 |
\t |
Tab |
\n |
换行 |
\xdd |
十六进制表示法中的任何字节 |
2.4.2.1 不区分大小写的字符串
YARA 中的文本字符串默认区分大小写,但是您可以通过nocase在字符串定义的末尾附加修饰符来将字符串转换为不区分大小写的模式
例如: $text_string = “foobar” nocase
2.4.2.2 宽字符串
该wide修改器可以用于搜索与每个字符两个字节,事中许多可执行二进制码典型的编码字符串。
如果您想同时搜索 ASCII 和宽格式的字符串,您可以将ascii修饰符与wide结合使用,例如:$wide_and_ascii_string = “Borland” wide ascii
2.4.2.3 异或字符串
xor关键字可以搜索该字符串的异或,例如:$xor_string = “This program cannot” xor,搜索“This program cannot”的明文以及,每个单字节异或后结果。
以上就等效于:
$xor_string_00 = “This program cannot”
$xor_string_01 = “Uihr!qsnfs`l!b`oonu”
$xor_string_02 = “Vjkq\”rpmepco\”acllmv”
甚至可以结合使用:
$xor_string = “This program cannot” xor wide ascii
如果要设定范围,则: $xor_string = “This program cannot” xor(0x01-0xff)=》在搜索时将从 0x01 到 0xff 的字节应用到字符串中。
2.4.2.4 Base64字符串
base64关键字搜索该字符串base64后的结果。
例如:$a = “This program cannot” base64
会搜索三排
2.4.2.5 搜索完整词
修饰符fullword,保证字符串仅在出现在由非字母数字字符分隔的文件中时才匹配。
例如将domain定义为fullword,则在www.mydomain.com中无法匹配,以为不是以非字母分割的,但是在www.my-domain.com和www.domain.com中匹配。
2.4.3 正则表达式
正则表达式用”/”括起来,例如$re1 = /md5: [0-9a-fA-F]{32}/
$re2 = /state: (on|off)/
\ | 引用下一个元字符 |
^ | 匹配文件的开头 |
$ | 匹配文件末尾 |
| | 交替 |
() | 分组 |
[] | 带括号的字符类 |
* | 匹配 0 次或多次 |
+ | 匹配 1 次或多次 |
? | 匹配 0 或 1 次 |
{n} | 完全匹配 n 次 |
{n,} | 至少匹配 n 次 |
{,m} | 最多匹配 m 次 |
{n,m} | 匹配 n 到 m 次 |
*? | 匹配 0 次或多次,非贪婪 |
+? | 匹配 1 次或多次,非贪婪 |
?? | 匹配 0 次或 1 次,非贪婪 |
{n}? | 精确匹配 n 次,非贪婪 |
{n,}? | 匹配至少 n 次,非贪婪 |
{,m}? | 最多匹配 m 次,非贪婪 |
{n,m}? | 匹配 n 到 m 次,非贪婪 |
\t | 标签 (HT, TAB) |
\n | 新线 (LF, NL) |
\r | 返回 (CR) |
\f | 换页 (FF) |
\a | 警钟 |
\xNN | 序数为给定十六进制数的字符 |
\w | 匹配一个单词字符(字母数字加“_”) |
\W | 匹配一个非单词字符 |
\s | 匹配一个空白字符 |
\S | 匹配一个非空白字符 |
\d | 匹配一个十进制数字字符 |
\D | 匹配一个非数字字符 |
\b | 匹配单词边界 |
\B | 除了在单词边界处匹配 |
2.4.4 私有字符串
2.4.5 字符串修饰符总结
关键词 | 支持的字符串类型 | 概括 | 限制 |
---|---|---|---|
nocase | 文本,正则表达式 | 忽略大小写 | 不能与xor、base64、 或base64wide一起使用 |
wide | 文本,正则表达式 | 通过交错空 (0x00) 字符来模拟 UTF16 | 无 |
ascii | 文本,正则表达式 | 匹配 ASCII 字符,仅在wide使用时才需要 | 无 |
xor | 文本 | 匹配具有单字节键的 XOR 文本字符串 | 不能与nocase、base64、 或base64wide一起使用 |
base64 | 文本 | base64 编码的字符串(分割成3条) | 不能与nocase、xor、 或fullword一起使用 |
base64wide | 文本 | base64 编码的字符串(分割成3条),然后交错空字符,如 wide | 不能与nocase、xor、 或fullword一起使用 |
fullword | 文本,正则表达式 | 匹配前后没有字母数字挨着的字符(串) | 不能与base64或一起使用base64wide一起使用 |
private | 十六进制、文本、正则表达式 | 匹配不包含在输出中 | 无 |
2.5 适应性
优先级 | 操作 | 描述 | 性质 |
---|---|---|---|
1 |
[] . |
Array subscripting 数组下标 Structure member access 结构成员访问 |
从左到右 |
2 |
– ~ |
Unary minus 按位减 Bitwise not 按位非 |
从右到左 |
3 |
* \ % |
Multiplication 乘法 Division 除法 Remainder 取余 |
从左到右 |
4 |
+ – |
Addition 加法 Subtraction 减法 |
从左到右 |
5 |
<< >> |
Bitwise left shift 按位左移 Bitwise right shift 按位右移 |
从左到右 |
6 | & | Bitwise AND 按位与 | 从左到右 |
7 | ^ | Bitwise XOR 按位异或 | 从左到右 |
8 | | | Bitwise OR 按位或 | 从左到右 |
9 |
< <= > >= |
Less than 小于 Less than or equal to 小于等于 Greater than 大于 Greater than or equal to 大于等于 |
从左到右 |
10 |
== != contains icontains startswith istartswith endswith iendswith matches |
Equal to 等于 Not equal to 不等于 String contains substring 包含 Like contains but case-insensitive 包含不区分大小写 String starts with substring 以开始字符串 Like startswith but case-insensitive 以开始字符串不区分大小写 String ends with substring 以结尾字符串 Like endswith but case-insensitive 以结尾字符串区分大小写 String matches regular expression 正则表达式 |
从左到右 |
11 | not | Logical NOT 逻辑非 | 从右到左 |
12 | and | Logical AND 逻辑与 | 从左到右 |
13 | or | Logical OR 逻辑或 | 从左到右 |
例如:
rule Example
{
strings:
$a = "text1"
$b = "text2"
$c = "text3"
$d = "text4"
condition:
($a or $b) and ($c or $d)
}
2.5.1 字符串计数
rule CountExample
{
strings:
$a = "dummy1"
$b = "dummy2"
condition:
#a == 6 and #b > 10
}
2.5.2 字符串偏移或虚拟地址
rule AtExample
{
strings:
$a = "dummy1"
$b = "dummy2"
condition:
$a at 100 and $b at 200
}
rule InExample
{
strings:
$a = "dummy1"
$b = "dummy2"
condition:
$a in (0..100) and $b in (100..filesize)
}
2.5.3 匹配长度
使用字符 ! 将匹配的长度用作条件的一部分。!a[1] 是 $a 第一次匹配的长度,!a[2] 是第二次匹配的长度,依此类推。!a 是 !a[1] 的缩写形式。
2.5.4 文件大小
rule FileSizeExample
{
condition:
filesize > 200KB
}
2.5.5 可执行入口点
rule EntryPointExample1
{
strings:
$a = { E8 00 00 00 00 }
condition:
$a at entrypoint
}
rule EntryPointExample2
{
strings:
$a = { 9C 50 66 A1 ?? ?? ?? 00 66 A9 ?? ?? 58 0F 85 }
condition:
$a in (entrypoint..entrypoint + 10)
}
2.5.6 访问给定位置的数据
int8(<offset or virtual address>)
int16(<offset or virtual address>)
int32(<offset or virtual address>)
uint8(<offset or virtual address>)
uint16(<offset or virtual address>)
uint32(<offset or virtual address>)
int8be(<offset or virtual address>)
int16be(<offset or virtual address>)
int32be(<offset or virtual address>)
uint8be(<offset or virtual address>)
uint16be(<offset or virtual address>)
uint32be(<offset or virtual address>)
rule IsPE
{
condition:
// MZ signature at offset 0 and ...
uint16(0) == 0x5A4D and
// ... PE signature at offset stored in MZ header at 0x3C
uint32(uint32(0x3C)) == 0x00004550
}
2.5.7 字符串集
rule OfExample1
{
strings:
$a = "dummy1"
$b = "dummy2"
$c = "dummy3"
condition:
2 of ($a,$b,$c)
}
rule OfExample2
{
strings:
$foo1 = "foo1"
$foo2 = "foo2"
$foo3 = "foo3"
condition:
2 of ($foo*) // equivalent to 2 of ($foo1,$foo2,$foo3)
}
rule OfExample3
{
strings:
$foo1 = "foo1"
$foo2 = "foo2"
$bar1 = "bar1"
$bar2 = "bar2"
condition:
3 of ($foo*,$bar1,$bar2)
}
rule OfExample4
{
strings:
$a = "dummy1"
$b = "dummy2"
$c = "dummy3"
condition:
1 of them
}
rule OfExample4
{
strings:
$a = "dummy1"
$b = "dummy2"
$c = "dummy3"
condition:
1 of ($*)
}
all of them // all strings in the rule
any of them // any string in the rule
all of ($a*) // all strings whose identifier starts by $a
any of ($a,$b,$c) // any of $a, $b or $c
1 of ($*) // same that "any of them"
2.5.8 对多个字符串应用相同的条件
for expression of string_set : ( boolean_expression )
for any of ($a,$b,$c) : ( $ at pe.entry_point )
for all of them : ( # > 3 ) 次数
for all of ($a*) : ( @ > @b ) 第一个偏移量
2.5.9 使用匿名字符串of和for..of
rule AnonymousStrings
{
strings:
$ = "dummy1"
$ = "dummy2"
condition:
1 of them
}
2.5.10 迭代字符串
rule Occurrences
{
strings:
$a = "dummy1"
$b = "dummy2"
condition:
for all i in (1,2,3) : ( @a[i] + 10 == @b[i] )
}
for all i in (1..3) : ( @a[i] + 10 == @b[i]
for all i in (1..#a) : ( @a[i] < 100 ) //#a 代表 $a 出现的次数
for any i in (1..#a) : ( @a[i] < 100 )
for 2 i in (1..#a) : ( @a[i] < 100 )
2.5.11 迭代器
for any section in pe.sections : ( section.name == ".text")
for any i in (0..pe.number_of_sections-1) : ( pe.sections[i].name == ".text" )
for any k,v in some_dict : ( k == "foo" and v == "bar" )
2.5.12 引用其他规则
rule Rule1
{
strings:
$a = "dummy1"
condition:
$a
}
rule Rule2
{
strings:
$a = "dummy2"
condition:
$a and Rule1
}
2.6 规则要求
2.6.1 全局规则
global rule SizeLimit
{
condition:
filesize < 2MB
}
2.6.2 私有规则
private
在规则声明之前添加关键字。private rule PrivateRuleExample
{
...
}
2.6.3 规则标签
rule TagsExample1 : Foo Bar Baz
{
...
}
rule TagsExample2 : Bar
{
...
}
2.6.4 元数据
rule MetadataExample
{
meta:
my_identifier_1 = "Some string data"
my_identifier_2 = 24
my_identifier_3 = true
strings:
$my_text_string = "text here"
$my_hex_string = { E2 34 A1 C8 23 FB }
condition:
$my_text_string or $my_hex_string
}
2.7 模块
import "pe"
import "cuckoo"
pe.entry_point == 0x1000
cuckoo.http_request(/someregexp/)
2.8 未定义的值
import "pe"
rule Test
{
strings:
$a = "some string"
condition:
$a and pe.entry_point == 0x1000
}
如果更改为
$a or pe.entry_point == 0x1000
2.9 外部变量
rule ExternalVariableExample1
{
condition:
ext_var == 10
}
rule ExternalVariableExample2
{
condition:
bool_ext_var or filesize < int_ext_var
}
rule ContainsExample
{
condition:
string_ext_var contains "text"
}
rule CaseInsensitiveContainsExample
{
condition:
string_ext_var icontains "text"
}
rule StartsWithExample
{
condition:
string_ext_var startswith "prefix"
}
rule EndsWithExample
{
condition:
string_ext_var endswith "suffix"
}
rule MatchesExample
{
condition:
string_ext_var matches /[a-z]+/
}
2.10 包括文件
include "other.yar"
include "./includes/other.yar"
include "../includes/other.yar"
include "/home/plusvic/yara/includes/other.yar"
include "c:/yara/includes/other.yar"
include "c:\\yara\\includes\\other.yar"
3 模块
3.1 PE模块
PE 文件格式的属性和特性
https://yara.readthedocs.io/en/latest/modules/pe.html
3.2 ELF模块
ELF 文件格式的属性和特性
https://yara.readthedocs.io/en/latest/modules/elf.html
3.3 Cuckoo模块
Cuckoo 模块使您能够根据Cuckoo 沙箱生成的行为信息创建 YARA 规则。
https://yara.readthedocs.io/en/latest/modules/cuckoo.html
3.4 Magic模块
https://yara.readthedocs.io/en/latest/modules/magic.html
3.5 Hash模块
Hash 模块允许您从文件的某些部分计算哈希值(MD5、SHA1、SHA256)并根据这些哈希值创建签名。
https://yara.readthedocs.io/en/latest/modules/hash.html
3.6 Math模块
数学模块允许您从文件的某些部分计算某些值并根据这些结果创建签名。
https://yara.readthedocs.io/en/latest/modules/math.html
3.7 Dotnet 模块
dotnet 模块允许您使用 .NET 文件格式的属性和功能为 .NET 文件创建更细粒度的规则。
https://yara.readthedocs.io/en/latest/modules/dotnet.html
3.8 Time 模块
Time 模块允许您在 YARA 规则中使用时间条件。
https://yara.readthedocs.io/en/latest/modules/time.html