YARA——惡意軟件模式匹配利器
YARA是一款旨在幫助惡意軟件研究人員識別和分類惡意軟件樣本的開源工具(由virustotal的軟件工程師Victor M. Alvarezk開發),使用YARA可以基于文本或二進制模式創建惡意軟件家族描述信息,當然也可以是其他匹配信息。
YARA的每一條描述或規則都由一系列字符串和一個布爾型表達式構成,并闡述其邏輯。YARA規則可以提交給文件或在運行進程,以幫助研究人員識別其是否屬于某個已進行規則描述的惡意軟件家族。比如下面這個例子:
rule silent_banker : banker
{
meta:
description = "This is just an example"
thread_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
}
以上規則告訴YARA任何包含有$a、$b、$c字符串的文件都被標識為slient_banker。這僅僅是一個簡單的例子,YARA的規則可以復雜和強大到支持通配符、大小寫敏感字符串、正則表達式、特殊符號以及其他特性。
一、YARA規則編寫
YARA規則的標識符類似于C語言結構,其規則聲明以rule標識,在規則描述中可以包括字母、數字甚至下劃線字符,但字符串第一個字符不能是數字,且單條描述不能超過128個字符。和C語言一樣,YARA規則也有關鍵字:
YARA規則由字符串區域和條件區域兩部分組成,其中條件區域必須存在,字符串區域則可有可無,比如不依賴任何字符串的規則:
rule Dummy
{
condition:
false
}
字符串區域中的每條規則都由$開頭的字符串定義,其規則內容可以是字符形式或十六進制形式,所定義的字符串由條件區域引用:
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
}
與C語言一樣,字符串規則使用雙引號,而十六進制規則使用大括號引用,每個十六進制數字之間用空格間隔,且十進制數字不允許出現在十六進制規則中。
條件區域決定YARA規則的邏輯,因此該區域的描述必須包含布爾型表達式,以判別目標文件或進程是否滿足該規則。通常條件內容都會引用字符串區域中的字符串定義,比如上例中的$my_text_string和$my_hex_string。條件區域的字符串表述方式為布爾型變量,若文件或進程內存符合字符串表達式則其結果為True,否則即為False。
注釋方式
YARA規則的注釋方式和類C語言一樣,可以用//進行單行注釋,也可以用/**/進行多行注釋。
/*
This is a multi-line comment …
*/
rule CommentExample // … and this is single-line comment
{
condition:
false // just an dummy rule, don't do this
}
字符串區域
YARA規則的字符串有三種類型:文本字符串、十六進制字符串、正則表達式。文本字符串用來定義文件或進程內存中可讀型內容,十六進制字符串用來定義字節內容,正則表達式可用在文本字符串和十六進制字符串中。比如:
rule HexExample
{
strings:
$hex_string = { F4 23 ( 62 B4 | 56 | 45 ?? 67 ) 45 }
condition:
$hex_string
}
文本字符串在YARA規則中是大小寫敏感的,但可以使用nocase關鍵字來取消大小寫敏感,字符串中的特殊字符亦可以使用轉義符表達,比如:
rule NocaseTextExample
{
strings:
$text_string = "\\\"foobar\"\\" nocase
condition:
$text_string
}
以上規則中所表示的字符串內容是\"foobar"\,由于使用nocase關鍵詞,故亦可以表達\"FoObAr"\、\"FOOBAR"\等等大小寫形式。
如果在目標文件中一個字符由兩個字節表示,即寬字符形式,則可以使用wide關鍵詞來表示文本字符串。如果既想表示寬字符,也想表示ASCII碼,則可以再使用ascii關鍵詞。比如:
rule WideAsciiTextExample
{
strings:
$text_string = "\\\"foobar\"\\" nocase wide ascii
condition:
$text_string
}
如果想匹配單個詞組文本字符串,可以使用fullword關鍵詞。比如:
rule FullwordTextExample
{
strings:
$text_string = "foobar" fullword
condition:
$text_string
}
條件區域
條件區域的內容為布爾類型表達式,因此該區域可以使用的符號可以是布爾操作符and、or和not,關系操作符>、<、==、<=、>=和!=,算數操作符+、-、*、/、%和按位操作符&、|、>>、<<、^、~。比如:
rule Example
{
strings:
$a = "text1"
$b = "text2"
$c = "text3"
condition:
($a or $b) and $c
}
如果想表達字符串描述在文件或進程內存中出現的次數,則在條件表達式中將字符串定義中的$替換為#。比如:
rule CountExample
{
strings:
$a = "text1"
$b = "text2"
$c = "text3"
condition:
#a == 1 or #b > 4 and #c < 6
}
如果想表達字符串在文件中的偏移量條件或虛擬地址的條件,則使用at關鍵詞表示,且表達式中的數字類型可以是十進制或十六進制。比如:
rule CountExample
{
strings:
$a = "text1"
$b = "text2"
$c = "text3"condition:
$a at 100 and $b at 0x004C0000 and $c at 300
}
與at不同,使用in關鍵詞可以表示文件偏移范圍,比如:$a in (1..100)、$b in (100..filesize)。這里的filesize亦為關鍵詞,表示文件的大小(單位字節),但該關鍵詞僅適用于分析對象是文件形式。比如:
rule FileSizeExample
{
condition:
filesize > 200KB
}
另外一個特殊的關鍵詞是entrypoint,表示文件入口點,適用于PE文件和ELF文件,當然也可以用于在運行進程。比如:
rule FileSizeExample
{
string:
$a = {E8 00 00 00}
condition:
$a at entrypoint
}
定的文件位置表達可訪問數據也是條件表達式可以做到的,需要用到uintXX或intXX關鍵詞以及以下函數:
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>)
利用以上關鍵詞和函數,若想判斷目標文件是否為PE文件,相應的規則可寫為:
rule IsPE
{
condition:
// MZ signature at offset 0
uint16(0) == 0x5A4D and
// PE signature at offset stored in MZ header at 0x3C
uint32(uint32(0x3C)) == 0×00004550
}
此外,還可以使用of、for…of等關鍵詞表達字符串集合,使用them關鍵詞表示隱式字符串定義。比如:
rule AnonymousStrings
{
strings:
$ = "dummy1"
$ = "dummy2"
condition:
1 of them
}
其他規則
除字符串區域和條件區域外,YARA還支持其他類型規則和形式,比如全局規則、私有規則、規則標簽、元數據、額外變量。
全局規則(global rule)旨在進行規則匹配前進行全局篩選,因此比其他規則匹配優先級要高,比如在匹配目標文件之前需要先篩選出小于2MB的文件:
global rule SizeLimit
{
condition:
filesize < 2MB
}
私有規則(private rule)的使用可以避免規則匹配結果的混亂,即若使用私有規則進行匹配則YARA不會輸出任何匹配信息。比如在規則文件Rule2引用規則文件Rule1時不希望Rule1的匹配信息輸出:
:private rule Rule1
{
strings:
$a = "dummy1"
$b = "dummy2"
condition:
$a and $b
}
rule Rule2
{
strings:
$a = "dummy3"
condition:
$a and Rule1
}
規則標簽(Tag Rule)的目的在于對規則匹配結果進行篩選,僅輸出用戶感興趣的匹配結果。比如:
rule TagRule : dummy1 dummy 2
{
strings:
$a = "dummy1"
$b = "dummy2"
condition:
$a and $b
}
元數據(MetaData)的目的在于對規則描述進行額外的描述存儲,其構成方式和字符串區域一致,但不可用于條件區域引用。比如本文開頭的例子。
額外變量(External Variable)允許規則文件中存在YARA匹配時手動添加的變量內容(見下文YARA命令行參數),比如:
rule ExternalVariableExample
{
condition:
ext_var == 10
}
二、YARA命令行參數
使用YARA進行規則匹配時需要兩樣東西:規則文件和目標文件,目標文件可以是文件、文件夾或進程。
usage: yara [OPTION]… RULES_FILE FILE | PID
options:
-t <tag> print rules tagged as <tag> and ignore the rest.
-i <identifier> print rules named <identifier> and ignore the rest.
-n print only not satisfied rules (negate).
-g print tags.
-m print metadata.
-s print matching strings.
-p <number> use the specified <number> of threads to scan a directory.
-l <number> abort scanning after matching a number of rules.
-a <seconds> abort scanning after a number of seconds has elapsed.
-d <identifier>=<value> define external variable.
-r recursively search directories.
-f fast matching mode.
-w disable warnings.
-v show version information.
規則文件可以直接傳遞給YARA,也可以在規則匹配前通過YARAC進行編譯,特別是在相同的規則文件需要進行多次調用進行模式匹配時,后者可以節省許多時間。
三、平臺支持
YARA支持多平臺,可以運行在Windows、Linux、Mac OS X,并通過命令行界面或yara-python擴展的Python腳本使用。
四、YARA使用者
VirusTotal Intelligence
jsunpack-n
We Watch Your Website
FireEye, Inc.
Fidelis XPS
RSA ECAT
CrowdStrike FMS
ThreatConnect
五、下載鏈接
YARA 2.0.0:https://github.com/plusvic/yara/releases/tag/v2.0.0
漏網之余
在編寫YARA規則時可以使用任何一款文本編譯器,且文件后綴無要求,但如果使用記事本編寫,則需要在使用YARA規則匹配前去除BOM(用vi編輯并使用“set nobomb”可以去除BOM),否則會提示“error:non-ascii character”。
在命令行下使用YARA進行規則匹配后,若目標文件或進程符合規則,則輸出“<規則文件名> <目標文件名>”,否則無任何輸出,而使用YARA命令參數“-n”可以反轉輸出提示,即匹配時無輸出,不匹配時有輸出。