原文鏈接:https://yara.readthedocs.io/en/v3.7.0/writingrules.html
一個簡單的yara規則示範:
rule ExampleRule
{
strings:
$my_text_string = "text here"
$my_hex_string = { E2 34 A1 C8 23 FB }
condition:
$my_text_string or $my_hex_string
}
yara規則由rule
引導,後跟一個類似C語言變量格式的字符串作爲規則名稱,長度不能超過128字節。花括號定義規則內容。
規則中用戶定義的字符串變量由$
字符引導,變量由字母、數字或下劃線組成,不能是保留的關鍵字。
yara規則中的關鍵字:
all | and | any | ascii | at | condition | contains |
---|---|---|---|---|---|---|
entrypoint | false | filesize | fullword | for | global | in |
import | include | int8 | int16 | int32 | int8be | int16be |
int32be | matches | meta | nocase | not | or | of |
private | rule | strings | them | true | uint8 | uint16 |
uint32 | uint8be | uint16be | uint32be | wide |
字符串變量可以是由雙引號""
界定的文本內容,也可以是花括號{}
界定的十六進制字符串。
註釋
類似於C語言,支持行註釋//
和塊註釋/**/
字符串
十六進制字符串
佔位符
?
示例:{ E2 34 ?? C8 A? FB }
,?
代表任意值的半字節內容。範圍
[x-y](0<=x<=y)
示例:{ F4 23 [4-6] 62 B4 [6] EA BB [10-] FF [-]}
。
[4-6]
代表任意4-6個字節;
[6]
是[6-6]
的簡寫形式,代表6個字節;
[10-]
代表10個字節及以上;
[-]
代表任意多個字節。多選
|
示例:{ F4 23 ( 62 B4 | 56 | 45 ?? 67 ) 45 }
。
圓括號內使用|
字符分隔的內容匹配任意一個即可。
文本字符串
雙引號界定的文本內容:"foobar"
。
轉義字符:
\" |
雙引號 |
---|---|
\\ |
反斜槓 |
\t |
Tab |
\n |
換行符 |
\xdd |
定義字節 |
字符串修飾
- nocase
查找時需要忽略大小寫:$text_string = "foobar" nocase
。 - ascii
默認定義的字符串爲ascii格式,可以省略。 - wide
定義寬字符:$wide_string = "Borland" wide
。僅通過在ascii字符之間插入0字節實現,不支持非ascii字符。
同時定義寬字符和ascii字符:$wide_and_ascii_string = "Borland" wide ascii
。 - fullword
全字搜索:$text_string = "foobar" fullword
。搜索時確保字符串的前後字節不是字母。
正則表達式
元字符:
\ |
轉義元字符 |
---|---|
^ |
匹配文件開頭 |
$ |
匹配文件末尾 |
| |
多選 |
() |
分組 |
[] |
字符集 |
量詞:
* |
匹配0或多次 |
---|---|
+ |
匹配1或多次 |
? |
匹配0或1次 |
{n} |
匹配n次 |
{n,} |
匹配至少n次 |
{,m} |
匹配最多m次 |
{n,m} |
匹配n到m次 |
默認使用貪婪模式匹配,在量詞後面追加?
字符切換爲非貪婪模式。
其它轉義字符:
\t |
Tab |
---|---|
\n |
換行 |
\r |
回車 |
\f |
換頁 |
\a |
Alarm |
\xNN |
定義字節 |
字符類:
\w |
匹配一個字母數字下劃線中的字符 |
---|---|
\W |
匹配一個非字母數字下劃線中的字符 |
\s |
匹配一個空白字符 |
\S |
匹配一個非空白字符 |
\d |
匹配一個數字字符 |
\D |
匹配個非數字字符 |
\b |
匹配一個字的邊界(3.3.0) |
\B |
匹配一個非字邊界(3.3.0) |
條件
類似於編程語言的布爾表達式,支持邏輯運算符:and,or,not
,關係運算符:>=,<=,<,>,==,~=
,算術運算符:+,-,*,\,%
,位運算符:&,|,<<,>>,~,^
。條件中出現的數字默認爲十進制,如果要使用十六進制需要加上前導內容0x
。
字符串變量可以直接作爲布爾值使用,存在匹配時爲true
,否則爲false
。
示例:
rule Example
{
strings:
$a = "text1"
$b = "text2"
$c = "text3"
$d = "text4"
condition:
($a or $b) and ($c or $d)
}
匹配次數
字符串變量的前導字符$
替換成#
,代表該字符串在目標(文件或進程)出現的次數,可以直接在條件表達式中使用。
rule CountExample
{
strings:
$a = "dummy1"
$b = "dummy2"
condition:
#a == 6 and #b > 10
}
匹配文件偏移或虛擬地址
使用at
指定字符串在指定位置進行匹配。
rule AtExample
{
strings:
$a = "dummy1"
$b = "dummy2"
condition:
$a at 100 and $b at 200
//或在指定的範圍內匹配
//$a in (0..100) and $b in (100..filesize)
}
@a[i]
:獲取第i個匹配的偏移或地址。i從1開始計數。如果i超出範圍則返回一個空值。
!a[i]
:獲取第i個匹配結果的長度。i從1開始計數。!a
代表第一個匹配結果的長度。
File size
filesize
代表目標文件的長度字節,如果目標是進程則該變量無意義。
rule FileSizeExample
{
condition:
filesize > 200KB
}
KB
前面的數字只能是十進制,還支持MB
。(GB
是否支持文檔沒說)
取值
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>)
u
開頭的讀取無符號整數,be
結尾的按big-endian字節序讀取。
示例:
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
}
字符串集合
使用of
關鍵字檢查任意或多個字符串的匹配。示例:
rule OfExample1
{
strings:
$foo1 = "dummy1"
$foo2 = "dummy2"
$bar1 = "dummy3"
$bar2 = "dummy4"
condition:
2 of ($foo1,$foo2,$bar1,$bar2) //至少有兩個匹配
//或使用以下形式匹配規則內字符串變量
//2 of($foo*,$bar*)
//或使用$*匹配規則內所有字符串變量($*與them相同)
//2 of ($*)
//2 of them
//of前面的數字可以使用以下關鍵字:
//any of them //匹配任意一個
//all of them //匹配所有
//all of ($foo*)
}
多個字符串應用同一個條件
語法:for expression of string_set : ( boolean_expression )
示例:
any of ($a,$b,$c)
for any of ($a,$b,$c) : ( $ )
for all of them : ( # > 3 )
for all of ($a*) : ( @ > @b )
圓括號中的佔位符功能:
$
代表正在評估的字符串;
#
代表正在評估的字符串出現的次數;
@
代表正在評估的字符串第一個匹配所在的偏移或虛擬地址。
使用匿名變量
rule AnonymousStrings
{
strings:
$ = "dummy1"
$ = "dummy2"
condition:
1 of them
}
匹配結果遍歷
語法:for expression identifier in indexes : ( boolean_expression )
示例:
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 )
}
引用其它規則
示例:
rule Rule1
{
strings:
$a = "dummy1"
condition:
$a
}
rule Rule2
{
strings:
$a = "dummy2"
condition:
$a and Rule1
}
規則設置
全局規則
全局規則在所有其它規則之前評估,如果結果爲false
則不會再評估其它規則。允許存在多個全局規則。
示例:
global rule SizeLimit
{
condition:
filesize < 2MB
}
私有規則
私有規則不會像全局規則一樣對結果產生影響,評估後也不會提交給yara,但可以與其它規則混合使用。
示例:
private rule PrivateRuleExample
{
...
}
可以對一個規則同時定義全局和私有屬性,評估後不會提交給yara,但必須滿足條件。
規則標籤
規則後面添加標籤,用於過濾輸出。在命令行使用時通過-t <tag>
或--tag=<tag>
選項指定需要輸出的標籤。一個規則允許有多個標籤,使用空格隔開。標籤的名稱格式與變量相同。
示例:
rule TagsExample1 : Foo Bar Baz
{
...
}
rule TagsExample2 : Bar
{
...
}
元數據
僅用於存儲規則的附加信息,不能在條件中使用,支持文本、整數和布爾值字符串(true/false
)。
示例:
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
}
使用模塊
必須在規則外部導入模塊:
import "pe"
import "cuckoo"
使用<module name>.
引用模塊變量:
pe.entry_point == 0x1000
cuckoo.http_request(/someregexp/)
未定義的值
yara確保模塊中未定義的變量在使用時結果永遠爲undefined
。pe.entry_point
指向PE文件的入口地址,但是在掃描一個非PE文件時,該變量是沒有值的。示例:
import "pe"
rule Test
{
strings:
$a = "some string"
condition:
$a and pe.entry_point == 0x1000
}
該規則匹配結果始終爲undefined
。但是如果將條件改爲$a or pe.entry_point == 0x1000
,且目標不是PE文件,則以$a
的結果爲準。
擴展變量
擴展變量由外部定義,可以在條件中直接使用。
示例1:
rule ExternalVariableExample1
{
condition:
ext_var == 10
}
示例2:
rule ExternalVariableExample3
{
condition:
string_ext_var contains "text"
}
rule ExternalVariableExample4
{
condition:
string_ext_var matches /[a-z]+/is
}
正則表達式末尾追加i
表示忽略大小寫,追加s
表示只在同一行進行匹配。
外部變量必須在運行時定義。yara-python中的compile
和match
函數的externals
參數可以指定外部變量。外部變量的值支持文本、整數和布爾值。在命令行可以通過-d
選項定義。
包含文件
使用include
關鍵字包含其它規則文件。在Linux系統中允許使用相對路徑或絕對路徑,在windows中必須使用絕對路徑。
Linux系統示例:
include "./includes/other.yar"
include "../includes/other.yar"
include "/home/plusvic/yara/includes/other.yar"
Windows系統示例:
include "c:/yara/includes/other.yar"
include "c:\\yara\\includes\\other.yar"