编写 YARA 规则 — yara 4.2.0 文档 
 
 
  
 
   YARA规则易于编写和理解,并且它们的语法是 类似于 C 语言。这是您可以编写的最简单的规则 YARA,它什么都不做: 
 
 
 rule dummy
{
    condition:
        false
}一、规则标识符
   每个规则都以关键字“ 
  rule”开头,后面跟着一个规则标识符。标识符必须遵循与C语言相同的词法约定,标识符命名有如下要求: 
 
 
 -  
   英文字母、数字、下划线组成的字符串
-  
   第一个字符不能是数字
-  
   对大小写敏感
-  
   不能超出128个字符长度
   以下关键字是保留的,不能用作规则标识符: 
 
 
  
 
 二、注释
 
  // 单行注释 
 
 
  
  
  /* 
 
 
 
      多行注释 
 
 
  
  */ 
 
 
  
  
 三、字符串
   Yara中有三种类型的字符串: 
 
 
 3.1、十六进制字符串
 
  定义原始字节序列 
 
 
  
   // 通配符?:可以代替某些未知字节,与任何内容匹配 
  
 
  rule WildcardExample
{
    strings:
       // 使用‘?’作为通配符
       $hex_string = { 00 11 ?? 33 4? 55 }
    condition:
       $hex_string
}这个规则可以匹配下面的两个字符串:
 
   00 11 01 33 43 55 
  
 
   
   00 11 AA 33 4N 55 
  
 
   
   
   
   // 跳转:可以匹配长度可变的字符串 
  
 
   
   rule JumpExample 
  
 
  {
        strings:
           // 使用‘[]’作为跳转,与任何长度为0-2字节的内容匹配
           $hex_string1 = { 00 11 [2] 44 55 }
           $hex_string2 = { 00 11 [0-2] 44 55 }
           // 该写法与string1作用完全相同
           $hex_string3 = { 00 11 ?? ?? 44 55 }
        condition:
           $hex_string1 and $hex_string2
} 
   这个规则可以匹配下面的两个字符串: 
  
 
   
   00 11 01 22 44 55 
  
 
   
   00 11 AA 44 55 
  
 
   
   
   
   // 匹配无限长的字符串 
  
 
  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 AlternativesExample1
{
    strings:
       $hex_string = { 00 11 ( 22 | 33 44 ) 55 }
    condition:
       $hex_string
} 
   可以匹配以下内容: 
  
 
   
   00 11  22  55 
  
 
   
   00 11  33 44  55 
  
 
   
   
   
   // 还可以将上面介绍的方法整合在一起用 
  
 
   
   rule AlternativesExample2 
  
 
  {
    strings:
       $hex_string = { 00 11 ( 33 44 | 55 | 66 ?? 88 ) 99 }
    condition:
       $hex_string
} 
   这个规则可以匹配下面的三个字符串: 
  
 
   
   00 11 33 44 99 
  
 
   
   00 11 55 99 
  
 
   
   00 11 66 AG 88 99 
  
 
   
 3.2、文本字符串
 
  定义可读文本的部分。 
 
 
  
   转义符: 
  
 
   
       \"        双引号 
  
 
   
       \\        反斜杠 
  
 
   
       \t        制表符 
  
 
   
       \n        换行符 
  
 
   
       \xdd      十六进制的任何字节 
  
 
   
   
   修饰符: 
  
 
   
       nocase:  不区分大小写 
  
 
   
       wide:      匹配2字节的宽字符, 这种宽字符串在许多二进制文件中都有出现 
  
 
   
       ascii:      匹配1字节的ascii字符 
  
 
   
       xor:        匹配异或后的字符串 
  
 
   
       fullword: 匹配完整单词,用于匹配那些前后没有附加其他字符的单词 
  
 
   
       private:  定义私有字符串 
  
 
  rule CaseInsensitiveTextExample
{
    strings:
        // 不区分大小写
        $text_string = "foobar" nocase
        // 匹配宽字符串
        $wide_string = "Borland" wide
        // 同时匹配2种类型的字符串
        $wide_and_ascii_string = "Borland" wide ascii
        // 匹配所有可能的异或后字符串
        $xor_string = "This program cannot" xor
        // 匹配所有可能的异或后wide ascii字符串
        $xor_string = "This program cannot" xor wide ascii
        // 限定异或范围
        $xor_string = "This program cannot" xor(0x01-0xff)
        // 全词匹配(匹配:www.domain.com  匹配:www.my-domain.com  不匹配:www.mydomain.com)
        $wide_string = "domain" fullword
        // 私有字符串可以正常匹配规则,但是永远不会在输出中显示
        $text_string = "foobar" private
    condition:
        $text_string
}3.3、正则表达式
 
  定义可读文本的部分。 
 
 
 
   yara规则允许使用正则表达式, 不过要用正斜杠而非双引号括起来使用(像Perl编程那样) 
 
 
 rule RegularShow
{
    strings:
        $re1 = /md5: [0-9a-fA-F]{32}/
        $re2 = /state: (on|off)/
    condition:
        $re1 and $re2
} 
   该规则将捕获任何状态下找到的所有md5字符串。 
  
 
   
   你也可以在正则表达式中使用文本修饰符, 如nocase,ascii,wide和fullword。 
  
 
 四、条件表达式
 
  你可以在条件表达中使用如下运算符: 
 
 
  
 
 all any them
 
   all of them // 匹配规则中的所有字符串 
  
 
   
   any of them // 匹配规则中的任意字符串 
  
 
   
   all of ($a*) // 匹配标识符以$a开头的所有字符串 
  
 
   
   any of ($a,$b,$c) // 匹配a, b,c中的任意一个字符串 
  
 
   
   1 of ($*) // 匹配规则中的任意一个字符串 
  
 
 #
 
   // 匹配字符串在文件或内存中出现的次数 
  
 
   
   rule CountExample 
  
 
   
   { 
  
 
   
       strings: 
  
 
   
           $a = "dummy1" 
  
 
   
           $b = "dummy2" 
  
 
   
       condition: 
  
 
   
           //a字符串出现6次,b字符串大于10次 
  
 
   
           #a == 6 and #b > 10 
  
 
   
   } 
  
 
 @
 
   //可以使用@a[i],获取字符串$a在文件或内存中,第i次出现的偏移或虚拟地址 
  
 
   
   //小标索引从1开始,并非0 
  
 
   
   //如果i大于字符串出现的次数,结果为NaN(not a number 非数值) 
  
 
 !
 
   //可以使用!a[i],获取字符串$a在文件或内存中,第i次出现时的字符串长度 
  
 
   
   //下标索引同@一样都是从1开始 
  
 
   
   //!a 是 !a[1]的简写 
  
 
 at
 
   // 匹配字符串在文件或内存中的偏移 
  
 
   
   rule AtExample 
  
 
   
   { 
  
 
   
       strings: 
  
 
   
           $a = "dummy1" 
  
 
   
           $b = "dummy2" 
  
 
   
       condition: 
  
 
   
           // a和b字符串出现在文件或内存的100和200偏移处 
  
 
   
           $a at 100 and $b at 200 
  
 
   
   } 
  
 
 in
 
   // 在文件或内存的某个地址范围内匹配字符串 
  
 
   
   rule InExample 
  
 
   
   { 
  
 
   
       strings: 
  
 
   
           $a = "dummy1" 
  
 
   
           $b = "dummy2" 
  
 
   
       condition: 
  
 
   
           $a in (0..100) and $b in (100..filesize) 
  
 
   
   } 
  
 
 filesize
 
   // 使用关键字匹配文件大小 
  
 
   
   rule FileSizeExample 
  
 
   
   { 
  
 
   
       condition: 
  
 
   
          // filesize只在文件时才有用,对进程无效 
  
 
   
          // KB MB后缀只能与十进制大小一起使用 
  
 
   
          filesize > 200KB 
  
 
   
   } 
  
 
 entrypoint
 
   // 匹配PE或ELF文件入口点(高版本请使用PE模块的pe.entry_point代替) 
  
 
   
   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) 
  
 
   
   } 
  
 
 of
 
   // 匹配多个字符串中的某几个 
  
 
   
   rule OfExample1 
  
 
   
   { 
  
 
   
       strings: 
  
 
   
           $a = "dummy1" 
  
 
   
           $b = "dummy2" 
  
 
   
           $c = "dummy3" 
  
 
   
       condition: 
  
 
   
           // 3个字符串只需匹配任意2个 
  
 
   
           2 of ($a,$b,$c) 
  
 
   
   } 
  
 
 for xxx of xxx :(xxx)
 
   功能:对多个字符串匹配相同的条件 
  
 
   
   格式:for AAA of BBB : ( CCC ) 
  
 
   
   含义: 
  
 
   
   在BBB字符串集合中,至少有AAA个字符串,满足了CCC的条件表达式,才算匹配成功。 
  
 
   
   在CCC条件表达式中,可以使用'$'依次代替BBB字符串集合中的每一个字符串。 
  
 
   
   
   // for..of其实就是of的特别版,所以下面2个例子作用相同 
  
 
   
   any of ($a,$b,$c) 
  
 
   
   for any of ($a,$b,$c) : ( $ ) 
  
 
   
   
   // 在abc这3个字符串集合中,至少有1个字符串,必须满足字符串内容与entrypoint相同的条件。$表示集合中的所有字符串. 本例中, 它是字符串$a, $b和$c. 
  
 
   
   for 1 of ($a,$b,$c) : ( $ at entrypoint  ) 
  
 
   
   for any of ($a,$b,$c) : ( $ at entrypoint  ) 
  
 
   
   
   // 所有字符串,在文件或内存中出现的次数必须大于3,才算匹配成功。 
  
 
   
   for all of them : ( # > 3 ) 
  
 
   
   
   // 所有以$a开头的字符串,在文件或内存中第2次出现的位置必须小于9 
  
 
   
   for all of ($a*) : (@[2] < 0x9) 
  
 
 引用其它规则
 
   rule Rule1 
  
 
   
   { 
  
 
   
       strings: 
  
 
   
           $a = "dummy1" 
  
 
   
       condition: 
  
 
   
           $a 
  
 
   
   } 
  
 
   
   
   rule Rule2 
  
 
   
   { 
  
 
   
       strings: 
  
 
   
           $a = "dummy2" 
  
 
   
       condition: 
  
 
   
           $a and Rule1 
  
 
   
   } 
  
 
 全局规则
 
   // 全局规则(global rule)可以在匹配其他规则前优先筛选, 
  
 
   
   // 比如在匹配目标文件之前需要先筛选出小于2MB的文件,在匹配其他规则 
  
 
   
   global rule SizeLimit 
  
 
   
   { 
  
 
   
       condition: 
  
 
   
           filesize < 2MB 
  
 
   
   } 
  
 
 私有规则
 
   //私有规则(private rule)可以避免规则匹配结果的混乱, 
  
 
   
   //比如使用私有规则进行匹配时,YARA不会输出任何匹配到的私有规则信息 
  
 
   
   //私有规则单独使用意义不大,一般可以配合"引用其它规则"的功能一起使用。比如为了判断文件是否恶意, 有这样一条私有规则, 要求文件必须是ELF文件. 一旦满足这个要求, 随后就会执行下一条规则. 但我们在输出里想看的并不是该文件它是不是ELF, 我们只想知道文件是否恶意, 那么私有规则就派上用场了. 
  
 
   
   //私有规则也可以和全局规则一起使用,只要添加“Private”、“global”关键字即可 
  
 
   
   private rule PrivateRuleExample 
  
 
   
   { 
  
 
   
       ... 
  
 
   
   } 
  
 
 规则标签
 
   // 规则标签,可以让你在YARA输出的时候只显示你感兴趣的规则,而过滤掉其它规则的输出信息(yara -t tagname) 
  
 
   
   // 你可以为规则添加多个标签 
  
 
   
   rule TagsExample1 : Foo Bar Baz 
  
 
   
   { 
  
 
   
       ... 
  
 
   
   } 
  
 
   
   
   rule TagsExample2 : Bar 
  
 
   
   { 
  
 
   
       ... 
  
 
   
   } 
  
 
 导入模块
 
   // 使用“import”导入模块 
  
 
   
   // 你可以自己编写模块,也可以使用官方或其它第三方模块 
  
 
   
   // 导入模块后,就可以开始使用模块导出的变量或函数 
  
 
   
   import "pe" 
  
 
   
   import "cuckoo" 
  
 
   
   pe.entry_point == 0x1000 
  
 
   
   cuckoo.http_request(/someregexp/) 
  
 
 外部变量
 
   // 外部变量允许你在使用YARA -d命令时指定一个自定义数据, 
  
 
   
   // 外部变量可以是int, str或boolean类型 
  
 
   
   
   // ext_var是一个外部变量, 它在运行时会分配有一个值 
  
 
   
   rule ExternalVariableExample2 
  
 
   
   { 
  
 
   
       condition: 
  
 
   
          ext_var == 10 
  
 
   
   } 
  
 
   
   
   /* 外部变量可以和操作符contains和matches一起使用 
  
 
   
   contains:如果字符串包含指定的子字符串,返回True 
  
 
   
   matches: 如果字符串匹配给定的正则表达式时,返回True 
  
 
   
   */ 
  
 
   
   rule ExternalVariableExample3 
  
 
   
   { 
  
 
   
       condition: 
  
 
   
           string_ext_var contains "text" 
  
 
   
   } 
  
 
   
   rule ExternalVariableExample4 
  
 
   
   { 
  
 
   
       condition: 
  
 
   
           string_ext_var matches /[a-z]+/ 
  
 
   
   } 
  
 
   
   
   // 也可以将matches操作符和正则表达式一起使用 
  
 
   
   rule ExternalVariableExample5 
  
 
   
   { 
  
 
   
       condition: 
  
 
   
           // [a-z]+/is中的i表示匹配时不区分大小写. s表示是在单行(single line)模式 
  
 
   
           string_ext_var matches /[a-z]+/is 
  
 
   
   } 
  
 
 文件包含
 
   // 作用于C语言一样,可以包含其它规则到当前文件中 
  
 
   
   include "other.yar" 
  
 
   
   
   // 相对路径 
  
 
   
   include "./includes/other.yar" 
  
 
   
   include "../includes/other.yar" 
  
 
   
   
   // 全路径 
  
 
   
   include "/home/plusvic/yara/includes/other.yar" 
  
 
   
  五、参考
 
   编写 YARA 规则 — yara 4.2.0 文档 
  
 
 


















