Yara规则与C语言语法十分相像, 以下是一个简单的规则, 这个规则没有进行任何操作:

rule HelloRule
{condition:false
}

规则标识符

规则标识符是上面简单规则示例中跟在rule后的词, 比如单词"dummy"也可以是一个规则标识符, 标识符命名有如下要求:

  • 是由英文字母或数字组成的字符串
  • 可以使用下划线字符
  • 第一个字符不能是数字
  • 对大小写敏感
  • 不能超出128个字符长度

Yara关键字

下面这些词不能用作规则标识符, 因为这些单词在yara语言里有特定用处

all, and, any, ascii, at, condition, contains entrypoint, false, filesize, fullword, for, global, in import, include, int8, nt16, int32, int8be, int16be int32be, matches, meta, nocase, not, or, of private, rule, strings, them, true, uint8, uint16 uint32, int8be, uint16be, uint32be, wide

通常yara规则有两部分: 字符串定义条件

rule HelloRule2    // This is an example
{strings:$my_text_string = "text here"$my_hex_string = { E2 34 A1 C8 23 FB }condition:$my_text_string or $my_hex_string
}

当发现有规则里定义的任意字符串, 规则就会生效. 如你所见, 你还可以在规则里添加注释.

十六进制字符串

通配符

十六进制字符串可以用通配符表示, 通配符符号用"?"表示

rule GambitWildcard
{strings:$hex_string = { EF 44 ?? D8 A? FB }condition:$hex_string
}

这个规则可以匹配下面的两个字符串

EF 44 01 D8 AA FB
EF 44 AA D8 AB FB

不定长通配符

不定长的字符串可以用下面这个方法表示

rule MarioJump
{strings:$hex_string = { F4 23 [4-6] 62 B4 }condition:$hex_string
}

这个规则可以匹配下面的两个字符串

F4 23 01 02 03 04 62 B4
F4 23 AA BB CC DD EE FF 62 B4

当然无限长的字符串也是可以的.

rule BuzzLightyear
{strings:$hex_string = { F4 23 [-] 62 B4 }condition:$hex_string
}

这个规则可以匹配下面的两个字符串

F4 23 AA FF 62 B4
F4 23 AA AA AA AA AA...FF FF 62 B4

有条件的字符串

你可以创建一个字符串应对多种情况

rule WorriedRabbit
{strings:$hex_string = { BA 21 ( DA BC | C6 ) A5 }condition:$hex_string
}

这个规则可以匹配下面的两个字符串

BA 21 DA BC A5
BA 21 C6 A5

混合

当然, 你也可以将上面这几种方法结合起来.

rule WorriedGabmitLightyearJump
{strings:$hex_string = { BA ?? ( DA [2-4] | C6 ) A5 }condition:$hex_string
}

这个规则可以匹配下面的三个字符串

BA 01 DA 01 02 03 04 A5
BA AA C6 A5
BA FF DA 01 02 A5

文本字符串

除开使用十六进制字符串, 我们也还可以使用文本字符串

rule KimPossible
{strings:$alert_string = "Whats the Sitch"condition:$alert_string
}

你也可以像C语言那样使用如下的转义符:

\" 双引号
\\ 反斜杠
\t 水平制表符
\n 换行符
\xdd 以十六进制表示的任何字节

修饰符

不区分大小写的字符串

Yara规则默认对大小写敏感, 但你可以使用修饰符将其关闭

rule ThickSkin
{strings:$strong_string = "Iron" nocasecondition:$strong_string
}

宽字符串

wide修饰符可以用来搜寻以2字节表示1字符这种方式编码的字符串, 这种宽字符串在许多二进制文件中都有出现. 如果字符串"FatTony"以2字节表示1字符的方式编码并在二进制文件中出现, 我们就可以使用wide修饰符将其捕获. 因为"FatTony"也可能是"fattony", 我们也可以添加nocase修饰符以免错过.

rule FatTony
{strings:$fat_villain = "FatTony" wide nocasecondition:$fat_villain
}

[!]重要提示: 请记住, 该修饰符只是将字符串中字符的ASCII码和\x00交错起来组成宽字符, 它并不支持包含非英文字符的UTF-16字符串. 要想对既有ASCII字符和宽字符的字符串进行搜索, 请使用如下命令:

rule ASCIIFatTony
{strings:$fat_villain = "FatTony" wide ascii nocasecondition:$fat_villain
}

字符串默认是ASCII编码, 所以如果你想单独用ascii搜索"FatTony", 你并不需要添加ascii修饰符

rule ASCIIFatTony
{strings:$fat_villain = "FatTony"condition:$fat_villain
}

如果你想在不使用widenocase修饰符的情况下进行搜索, 上述这个规则可以生效.

Fullwords修饰符

该修饰符可用于匹配那些前后没有附加其他字符的单词(全词匹配).

rule ShadyDomain
{strings:$shady_domain = "faceebook" fullwordcondition:$shady_domain
}

这个规则可以匹配下面的三个字符串

www.faceebook.com
www.myportal.faceebook.com
https://secure.faceebook.com

但这个规则不能匹配以下的字符串:

www.myfaceebook.com
thefaceebook.com

两者区别在于匹配的全词前后可以附加特殊字符, 不能是普通字符.

正则表达式

yara规则允许使用正则表达式, 不过要用正斜杠而非双引号括起来使用(像Perl编程那样)

rule RegularShow
{strings:$re1 = /md5: [0-9a-fA-F]{32}/$re2 = /state: (on|off)/condition:$re1 and $re2
}

该规则将捕获任何状态下找到的所有md5字符串.

你也可以在正则表达式中使用文本修饰符, 如nocase,ascii,widefullword.

元字符

元字符是一个字符对计算机程序有特定含义(而非字面含义)的字符. 在正则表达式中, 有以下含义:

** 引用下一个元字符
^ 匹配文件的开头
$ 匹配文件的末尾
| 多选
() 分组
[] 方括号字符类

也可以使用以下量词:

* 匹配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 十六进制代码为NN的字符

也可以使用以下字符类:

\w 匹配单词字符 (单词可由字母数字加"_"组成)
\W 匹配非单词字符
\s 匹配空白符
\S 匹配非空白字符
\d 匹配一个十进制数字字符
\D 匹配一个非数字字符
\b 匹配单词边界
\B 匹配非单词边界

字符串集

如果你想要中列表中选择一定数量的字符串, 你可以执行以下操作:

rule MigosPresent
{strings:$m1 = "Quavo"$m2 = "Offset"$m3 = "Takeoff"condition:2 of ($m1,$m2,$m3)
}

如果$m1$m2$m3任意存在两个, 那么就满足上述规则中的条件.

你还可以使用通配符来表示一个字符集. 像如下这样使用通配符*

rule MigosPresent
{strings:$m1 = "Quavo"$m2 = "Offset"$m3 = "Takeoff"condition:2 of ($m*)
}

要表示strings中的所有变量, 你可以使用关键字them

rule ThreeRappersPresent
{strings:$m1 = "Quavo"$m2 = "Offset"$m3 = "Takeoff"$q1 = "Cardi B"condition:3 of them // equivalent to 3 of ($*)
}

你可以使用任何返回数值的表达式. 以下是使用关键字anyall的一个示例

rule Squad
{strings:$m1 = "Quavo"$m2 = "Offset"$m3 = "Takeoff"$q1 = "Cardi B"condition:3 of them // equivalent to 3 of ($*)all of themany of ($*) and 2 of ($*)    // Fancy way of using any in a rule that requires 3.
}

带有of和for...of的匿名字符串

如果你没有专门引用字符串的事件, 你可以仅使用$来将它们全部引用.

rule AnonymousStrings
{strings:$ = "dummy1"$ = "dummy2"condition:1 of them
}

条件

Yara规则允许通过and, or, 和not等相关运算符来表示布尔表达式, 算术运算符(+,-,*,%)和位运算符(&, |, <<, >>, ~, ^)也可用于数值表达式中.

布尔运算

字符串标识符也可在条件中充当布尔变量, 其值取决于文件中相关字符串是否存在.

rule Example
{strings:$hero1a = "Batman"$hero1b = "Robin"$hero2a = "Edward"$hero2b = "Alphonse"condition:($hero1a or $hero1b) and ($hero2a or $hero2b)
}

计数字符串实例

有时我们不仅需要知道某个字符串是否存在, 还需要知道字符串在文件或进程内存中出现的次数. 每个字符串的出现次数由一个变量表示, 变量名是用#代替$的字符串标识符. 例如:

rule Ransomware
{strings:$a = "encrypted"$b = "btc"condition:#a == 2 and #b > 2
}

这个规则会匹配任何包含两个字符串$a以及出现至少两次字符串$b的文件或进程.

字符串偏移(虚拟地址)

在大多数情况下, 当在条件中使用字符串标识符, 我们都只需知道关联的字符串是否在文件或进程内存内就行了. 但有时我们还是需要知道该字符串是否在文件的某个特定偏移处, 或是在进程地址空间的某个虚拟地址处. 在这种情况下, 我们就需要操作符at.

rule Offset
{strings:$a = "encrypted"$b = "btc"condition:$a at 100 and $b at 200
}

如果在文件的偏移100处(或者在一个正在运行的进程中, 位于虚拟地址100位置)发现了字符串$a, 我们的规则就能捕获到该字符串. 当然字符串$b也要在偏移200位置上才行. 你也可以使用十六进制表示而不一定要十进制.

rule Offset
{strings:$a = "encrypted"$b = "btc"condition:$a at 0x64 and $b at 0xC8
}

at操作符指定到一个具体的偏移量, 而你可以使用操作符in来指定字符串的位置范围.

rule InExample
{strings:$a = "encrypted"$b = "btc"condition:$a in (0..100) and $b in (100..filesize)
}

字符串$a必须在偏移0-100之间才能找到, 而$b则必须是在偏移100到文件末尾位置(才能找到).

你也可以使用@a[i]来取得字符串$ai个字符的偏移量或虚拟地址. 字符串索引以1开头 , 故第1个字符是@a[1], 第2个是@[a2]并依此类推, 而不是以@a[0]开始. 如果你提供的索引值大过字符串总共出现的次数. 那结果就将是值NaN(Not a Number, 非数字).

匹配长度

对于包含跳转的许多正则表达式和十六进制字符串, 匹配长度用一个变量表示. 如果你有一个正则表达式/fo*/, 可以匹配字符串fofoofooo, 那么各个的匹配长度都是不同的.

在字符串标识符前加一个!得到匹配长度, 你就可以将匹配长度作为你条件的一部分. 跟你获取偏移时使用字符@类似, !a[1]是第一个匹配到的字符串$a的长度, 而!a[2]就是第二个匹配到的字符串的长度, 依此类推. !a!a[1]的缩写.

rule Hak5
{strings:$re1 = /hack*/    // Will catch on hacker, hacked, hack, hack*condition:!re1[1] == 4 and !re1[2] > 6
}

该规则可以匹配如下字符串:

We hack things. We are hackers.

第一个hackre1[1]且其长度等于4. 第二个hack长度则至少为6

文件大小

字符串标识符并不是唯一可以在条件中出现的变量(实际上, 可以不定义任何字符串来编写一个规则), 还可以使用其他变量. filesize就保存着正在扫描的文件的大小. 大小以字节为单位.

rule FileSizeExample
{condition:filesize > 200KB
}

我们可以使用后缀KB将文件大小设置为200KB, 它会自动将常量的值乘上1024, 后缀MB会可以将值乘以2^20. 这两个后缀都只能用于十进制常量

[!]重要提示: filesize仅在规则应用于文件的时候生效. 如果应用于正在运行的进程, 那么它会永远都匹配不了.

可执行程序入口点

如果我们正扫描的文件是一个PE或ELF文件, 那么变量entry_point会存有可执行文件的入口点偏移值. 而如果我们正扫描一个运行的进程, 那么entry_point会存有可执行文件入口点的虚拟地址. 变量entry_point的经典用法是用于搜索入口点的一些pattern, 以检测壳或简单的感染病毒. 目前使用entry_point的方式是通过导入PE和/或ELF的库并使用它们各自的功能. Yara的entrypoint函数自第3版开始就已经过时了. 以下是它在第3版之前的样子.

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)
}

[!]重要提示: 再次强调, 不要使用yara的entrypoint, 请在导入PE或ELF文件后使用对应的pe.entry_pointelf.entry_point

访问指定位置的数据

如果你想从特定偏移位置读取数据, 并将其存为一个变量. 那么你可以使用以下任何一个方式:

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>)

数据存储默认以小端序, 如果你想要读取大端序的整形数, 请使用下面几个以be结尾的对应函数.

参数<offset or virtual address>可以是任何一个返回无符号整数的表达式, 包括可以是uintXX函数的返回值.

rule IsPE
{condition:// MZ signature at offset 0 and ...uint16(0) == 0x5A4D and// ... PE signature at offset stored in MZ header at 0x3Cuint32(uint32(0x3C)) == 0x00004550
}

for…of: 对许多字符串应用同一个条件

要用for循环来检查一组字符串是否满足特定条件, 请使用如下语法:

for num of string_set : ( boolean_expression )

对每个string_set的字符串, 都会计算boolean_expression的值, 并且这些值必须至少有1个为真.

当然你也可以使用其他关键字, 如allany代替num来使用.

for any of ($a,$b,$c) : ( $ at elf.entry_point  )

$表示集合中的所有字符串. 本例中, 它是字符串$a$b$c.

你也可以使用符号#@来引用每一个字符串的出现次数和首字符偏移量.

for all of them : ( # > 3 )
for all of ($a*) : ( @ > @b )

迭代字符串出现次数

如果你想对偏移迭代并测试条件. 你可以如下操作:

rule Three_Peat
{strings:$a = "dummy1"$b = "dummy2"condition:for all i in (1,2,3) : ( @a[i] + 10 == @b[i] )
}

这个规则说的是, $b出现前三个的字符串应当分别隔$a出现的前三个的字符串10个字节远. 另外一种写法如下:

for all in (1..3) : ( @a[i] + 10 == @b[i] )

我们也可以使用表达式. 在本例中, 我们迭代每一次出现的$a(记住, #a代表$a的出现次数). 该规则指定, 每一次$a都应当出现在文件的前100个字节内.

for all in (1..#a) : ( @a[i] < 100 )

你也可以指定字符串的某一次出现需要满足条件(而非全部).

for any i in (1..#a) : ( @a[i] < 100 )
for 2 i in (1..#a) : ( @a[i] < 100 )

引用其他规则

就像C语言中引用函数那样. 函数, 或是这里说的规则, 都必须在使用前进行定义.

rule Rule1
{strings:$a = "dummy1"condition:$a
}rule Rule2
{strings:$a = "dummy2"condition:$a and Rule1
}

Yara要点

全局规则

Yara规则允许用户在所有规则中进行约束. 如果你希望所有规则都忽略掉那些超出特定大小限制的文件, 那么你可以对规则进行必要的修改, 或是编写一条像以下这样的全局规则:

global rule SizeLimit
{condition:filesize < 2MB
}

你可以根据需要定义各种全局规则. 这些规则会在其他规则之前运行.

私有规则

私有规则在匹配时没有任何输出. 当和其它规则成对引用时, 这样就可以使输出更为清楚. 比如为了判断文件是否恶意, 有这样一条私有规则, 要求文件必须是ELF文件. 一旦满足这个要求, 随后就会执行下一条规则. 但我们在输出里想看的并不是该文件它是不是ELF, 我们只想知道文件是否恶意, 那么私有规则就派上用场了. 要想创建一条私有规则, 只需要在rule前添加一个private即可.

private rule PrivateRule
{...
}

规则标签

如果你只想查看ruleName类型的规则输出, 你可以对你的规则打上标签

rule TagsExample1 : Foo Bar Baz
{...
}rule TagsExample2 : Bar
{...
}

元数据

Yara允许在规则中存储一些额外数据.

rule MetadataExample
{meta:my_identifier_1 = "Some string data"my_identifier_2 = 24my_identifier_3 = truestrings:$my_text_string = "text here"$my_hex_string = { E2 34 A1 C8 23 FB }condition:$my_text_string or $my_hex_string
}

使用模块

一些模块由YARA官方发布, 比如PECukoo模块. 这些模块就如python那样导入即可, 不过在导入时模块名需要添加双引号

import "pe"
import "cuckoo"

一旦模块成功导入, 你就可以在函数前加模块名, 来使用这些功能.

pe.entry_point == 0x1000
cuckoo.http_request(/someregexp/)

未定义的值

一些值在运行时保留为undefined. 如果以下规则在ELF文件上执行并找到对应的字符串, 那么它的结果相当于TRUE & Undefined.

import "pe"rule Test
{strings:$a = "some string"condition:$a and pe.entry_point == 0x1000
}

所以在用的时候要注意咯!

外部变量

外部变量允许你定义一些, 依赖于第三方提供值的规则.

rule ExternalVariable1
{condition:ext_var == 10
}

ext_var是一个外部变量, 它在运行时会分配有一个值, (见命令行的-d选项以及yara-python中compilematch方法的参数). 外部变量可以是intstrboolean类型

外部变量可以和操作符containsmatches一起使用. contains在字符串包含特定子串的情况下返回true. 而matches在字符串匹配给定的正则表达式时返回true.

rule ExternalVariable2
{condition:string_ext_var contains "text"
}rule ExternalVariable3
{condition:string_ext_var matches /[a-z]+/
}

你也可以将matches操作符和正则表达式一起使用

rule ExternalVariableExample5
{condition:/* case insensitive single-line mode */string_ext_var matches /[a-z]+/is
}

/[a-z]+/is中的i表示匹配时不区分大小写. s表示是在单行(single line)模式

记住, 你必须在运行时定义好所有的外部变量. 你可以使用-d参数来指定.

文件包含

当然在yara规则里你可以使用类似C语言的导入方式(#include, 不过yara中并不使用#号来包含所需的文件, 而是用双引号引起来)来包含其他文件. 你可以在包含时使用相对路径或绝对路径. 如果是windows系统, 甚至还可以是驱动设备的路径.

include "Migos.yar"
include "../CardiB.yar"
include "/home/user/yara/IsRapper.yar"
include "c:\\yara\\includes\\oldRappers.yar"
include "c://yara/includes/oldRappers.yar"

总结

好吧. 现在你应该知道如何写一些Yara规则了.
这里有一些恶意软件的仓库, 规则和工具, 可以让你来生成yara规则. 如果你安装了yarGem, 你只需要将它指向到恶意软件, 它就会为该恶意软件生成一个签名. 如果你想捕捉一个恶意软件家族, 你最好是将规则推广到整个家族去.

编写yara规则,检测恶意软件(自定义yara规则)相关推荐

  1. 编写yara规则 检测恶意软件

    Yara规则与C语言语法十分相像, 以下是一个简单的规则, 这个规则没有进行任何操作: rule HelloRule { condition: false } 规则标识符 规则标识符是上面简单规则示例 ...

  2. GO请求参数规则校验(自定义校验规则、规则中文化)

    文章目录 1 简介 2 简单校验 3 自定义字段类型 4 结构层校验 5 翻译和自定义错误 6 国际化成中文 ​ 参数校验是开发中不可或缺的重要组成部分,本章节我们将介绍参数的校验,采用的是 go-p ...

  3. CobaltStrike YARA规则 检测 环境搭建

    1.搭建环境 下载yara.exe可执行程序 Releases · VirusTotal/yara · GitHub 2.下载谷歌开源项目 https://github.com/chronicle/G ...

  4. java自定义findbugs规则_findbugs自定义规则并配置实现检测

    findbugs不过多介绍了,对于这个主题找了一些资料,没有找到一个完整的介绍,要么是介绍怎么写detector,要么就是没有完整的介绍怎么配置生效,下面主要介绍一下怎么配置其生效,至于怎么写这个de ...

  5. Java黑皮书课后题第6章:**6.18(检测密码)一些网站对于密码具有一些规则。编写一个方法检测字符串是否是一个有效密码。编写一个程序,提示用户输入一个密码,如果符合规则,则显示…否则显示…

    6.18(检测密码)一些网站对于密码具有一些规则.编写一个方法检测字符串是否是一个有效密码.编写一个程序,提示用户输入一个密码,如果符合规则,则显示-否则显示- 题目 题目描述 破题 代码 运行示例 ...

  6. JSR303校验的简单使用以及自定义校验规则的代码编写

    文章目录 一.JSR303校验 1.简介 2.相关注解 3.JSR303依赖包 二.JSR303自带的校验规则 1.在JavaBean上添加校验规则 2.生效校验规则 2.1 controller返回 ...

  7. 如何编写snort的检测规则

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 摘要  ...

  8. yara 模式匹配 android,恶意软件模式匹配利器 – YARA

    YARA是一款旨在帮助恶意软件研究人员识别和分类恶意软件样本的开源工具(由virustotal的软件工程师Victor M. Alvarezk开发),使用YARA可以基于文本或二进制模式创建恶意软件家 ...

  9. 自动规避代码陷阱——自定义Lint规则

    目录 一.Lint是什么? 二.Lint的使用 三.为什么要使用自定义Lint规则? 四.新建module 五.在lintjar中定义规则 六.配置lintjar中gradle 七.配置LintAar ...

最新文章

  1. Hadoop 统计单词字数的例子
  2. python爬虫之美女图片爬取
  3. 第四篇 Python循环
  4. 用Swashbuckle(swagger-ui)显示API帮助并进行调试
  5. 项目建立数据库初始环境脚本文件的示例
  6. 蓝桥杯第六届C语言B——积分之谜
  7. html广告悬浮窗口,JS实现悬浮移动窗口(悬浮广告)的特效
  8. mysql无法启动如何备份文件_mysql 5.7 停电导致无法启动、如何备份数据,重新安装mysql...
  9. [转]numpy 100道练习题
  10. Ubuntu 11.10为何值得我们期待?
  11. 博弈论1(正则型博弈)
  12. 阿拉伯数字转换成人民币大写金额的方法
  13. 企业微信管理员可以看到打卡位置吗
  14. 三年经验前端开发面试总结
  15. 鸿蒙系统1004无标题,win10 10041更新提示错误怎么处理
  16. python替换word中的图片_python如何提取word内的图片
  17. 手机卖了 微信如何关掉订阅服务器,微信订阅号消息怎么关闭?详细方法介绍
  18. adb命令设置输入法
  19. Stata常见问题解答
  20. java stringbuilder 替换字符串_StringBuilder修改字符串内容,增,删,改,插

热门文章

  1. iphone怎么看wifi密码_无线网密码正确但是手机连接不上wifi怎么回事?
  2. 【深度学习】empty() received an invalid combination of arguments - got (tuple, dtype=NoneType, device=None
  3. 无监督学习 | 层次聚类 之凝聚聚类原理及Sklearn实现
  4. 解决“Class org.apache.hadoop.hdfs.DistributedFileSystem not found“问题
  5. android 滚动条自定义样式,IScroll的使用-方向键绑定自定义滚动条样式
  6. P2651 添加括号III(python3实现)
  7. mysql批量查询并替换或者更新某个字段
  8. 点到直线的距离c语言程序,点到线段的距离 题解(C++)
  9. ios html 禁止下拉,ios禁止页面下拉
  10. MySQL笔记-InnoDB中Record Lock与Gap Lock