Zararlı Yazılım Analiz ve Tespit Çalışmalarında YARA Kullanımı

YARA zararlı yazılımları belirlemek ve sınıflandırmak için kullanılan bir araçtır. Yara ile zararlı yazılımları yazısal veya binary ikili değer(binary) olarak istenildiği gibi tanımlanmaktadır. Her tanımlama bir dizi string ve mantıksal ifadelerden (boolean expressions) oluşur. Örnek vermek gerekirse;



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
}



Yukarıdaki Yara kuralı bize herhangi bir dosyanın yukarıdaki üç karakter dizisinden (string) birini içermesi gerektiğini söylüyor. Bu basit bir örnek eğer istersek daha komplex ve etkili kurallar yazabiliriz.



Yara’nın kurulumunu yaptıktan sonra, basit bir kural yazalım ve komut satırını kullanarak bazı dosyaları tarayalım.



~ echo “rule dummy { condition: true }” > my_first_rule
~ yara my_first_rule



Eğer herşey doğru yazıldı ise şöyle bir çıktı alacaksınız



~ dummy my_first_rule
Bunun anlamı: my_first_rule dosyası, dummy kuralı ile eşleşti.



Yara kurallarının yazılması ve anlaşılması kolaydır,söz dizimi kuralları (syntax) olarak da C diline çok benzer. Her kural bir anahtar kelime ile başlar. Anahtar kelimeler aşağıdaki tabloda verilmiştir.



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



Kurallar genellikle iki kısımdan oluşur; karakter dizisi tanımları ve koşullar. Bir kuralda karakter dizisi tanımları belki her zaman gerekli olmayabilir ancak koşul bölümü kesinlikle olmalıdır. Her string bir belirleyiciye (identifier) sahiptir ve her belirleyici “$” karakteri ile başlar. Her metin iki çift tırnak “…“ karakterleri arasına yazılır, her onaltılıkelime dizisi ise süslü parantezler {…}  arasına yazılır.



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 KURALLARI:



Yorum Satıları: Yorum satırları C dili ile birebir aynıdır.



/*
   Çoklu yorum satırı …
*/



rule CommentExample   // Tek yorum satırı



Strings: 3 tür string vardır.



a- Onaltılı Kelime Dizileri (Hexadecimal Strings)



Onaltılı kelime dizileri 3 özel yapı sayesinde daha esnek bir yapıya sahiptir.



rule WildcardExample
{
   strings:
      $hex_string = { E2 34 ?? C8 A? FB }

   condition:
      $hex_string
}



Wild-Cards olarak adlandırdığımız yukarıdaki yapıda, eğer kelime dizisi içerisinde bir byte belirsiz ise yani yerine herhangi birşey gelebilir ise “ ?? “ koyarız. Eğer kelime dizisinin içeriği belirli değilse, WildCard oldukça kullanışlı bir yapıya sahiptir (kelime dizisinin uzunluğu belli ise).

Ancak bu yapı her zaman kullanışlı olmayabilir. Eğer kelime dizisinin içeriği ve uzunluğu belli değilse WildCard yerine Jumps yapısını kullanırız.



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

       condition:
          $hex_string
   }



Jumps yapısında, köşeli parantezler arasına yazığımız rakamlar ( Örn [4-6] ), kelime dizisinde o pozisyona 4 ile 6 byte arasında, herhangi bir model gelebilir anlamına geliyor. Örn;



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



Jump yapısındaki kurallar: [X-Y] yapısını düşünürsek, 0 <= X < Y olmak zorundadır, Örn;



FE 39 45 [0-8] 89 00
FE 39 45 [23-45] 89 00
FE 39 45 [1000-2000] 89 00



FE 39 45 [10-7] 89 00 -> GEÇERSİZ

Aşağıdaki 3 yapı, birbiri ile tamamen aynıdır,



FE 39 45 [6] 89 00
FE 39 45 [6-6] 89 00
FE 39 45 ?? ?? ?? ?? ?? ?? 89 00



Aşağıdaki yapıların anlamları ise; [10 – sonsuz] , [0 – sonsuz]’dur.



FE 39 45 [10-] 89 00
FE 39 45 [-] 89 00



3. ve son yapı olarak da alternatif yapısına örnek vermek gerekirse:



rule AlternativesExample1
{
   strings:
      $hex_string = { F4 23 ( 62 B4 | 56 ) 45 }

   condition:
      $hex_string
}



bu yapının anlam iseı: “F42362B445“ veya “F4235645” stringlerini içeren dosya ile eşleşmek.



b- Metin Dizisi (Text String)



Metin Dizilerine aşağıdaki gibi örnek verebiliriz.



rule TextExample
{
   strings:
       $text_string = “foobar”
// $text_string = “foobar” nocase
// $text_string = “FooBar” fullword

   condition:
      $text_string
}



“ nocase “ değiştirici sayesinde foobar; Foobar, FOOBAR, fOoBAr kelime dizilerinin hepsi ile eşleşebilir.



“ fullword “ değiştiricisi sayesinde ise, domain kelimesi;



kelime dizileri ile eşleşir. Eşleşmenin sağlanması için anahtar kelimenin, diğer kelime dizilerinden alfanumerik olmayan karakterler ile ayrılmış olması yeterlidir.



c- Düzenli İfadeler ( Regular Expressions )



Bu ifadeler text stringler ile benzer yapıya sahiptir, aralarındaki tek fark, text stringler iki adet çift tırnak arasına yazılırken, düzenli ifadeler iki tane ters eğik çizgi / / arasına yazılır. Metinsel ifadelerde kullanılan nocase, ascii, fullword değiştiricileri burda da kullanılabilir.


rule RegExpExample1
{
   strings:
       $re1 = /md5: [0-9a-zA-Z]{32}/
       $re2 = /state: (on|off)/

   condition:
       $re1 and $re2
}



Koşullar (Conditions):



Koşul yapıları aynı düzenli yapılar gibi tüm programlama dillerinde bulunurlar, if komutu gibi. Kolul yapılarının içerisinde bool operatörleri (and, or, not), ilişkili ifadeler (<, >, <=, >=, ==), aritmetik ifadeler (+, -, *, /, %) ve bitsel (bitwise) ( &, |, <<, >>, ~) de yer alır.



rule Example
{
   strings:
       $a = “text1”
       $b = “text2”
       $c = “text3”
       $d = “text4”

   condition:
       ($a or $b) and ($c or $d)
}



Kelime Dizilerini Saydırma (Counting String)



Bazen sadece kelime dizisinin ne olduğuna değil de, dosyanın içerisinde o kelime dizinin kaç kere göründüğü bizim için önemli olur. Böyle durumlarda $ karakteri yerine # karakterini kullanırız.



rule CountExample
{
   strings:
       $a = “dummy1”
       $b = “dummy2”

   condition:
       #a == 6 and #b > 10
}



Bu örneğin; bir dosyanın içerisinde a kelime dizisinin 6 kere, b kelime dizisinin de en az 10 kere bulunması gerektiğini ifade etmektedir.



Kelime dizilerinin konumu veya Sanal Adresleri (String offsets or Virtual Addresses)
Bazı durumlarda, istenilen kelime dizisinin bir dosyada yada bilgisayarın belleğinde özel bir yerde olup olmadığı durumları kontrol etmek gerekir. Böyle durumlarda “at” operatörünü kullanırız. Örn:



rule AtExample
{
   strings:
       $a = “dummy1”
       $b = “dummy2”

   condition:
       $a at 100 and $b at 200
}



“$a at 100” ifadesinin anlamı, sanal adreste veya bir dosyanın içeriside a kelime dizisinin konumu 100 ise, işlemin doğruyu döndermesi(return) gerekir.
Adres işlemleri yapılırken “in” operatörü ile de aralık belirtilebilir. Örn:



rule InExample
{
   strings:
       $a = “dummy1”
      $b = “dummy2”

   condition:
      $a in (0..100) and $b in (100..filesize)
}



Bu örnekte, a kelime dizisinin konumu 0 ile 100 arasında bulunmak zorundadır. Aynı şekilde b kelime dizisinde de mantık aynıdır.



Dosya Boyutu (Filesize)



Kelime dizisi belirteçleri sadece koşul içerisinde kullanımlayabilir (Aşağıdaki örnekteki gibi, kelime dizilerinden bağımsız), bazı diğer özel değişkenler de olabilir. Örn:



rule FileSizeExample
{
   condition:
      filesize > 200KB             // e.g 200mb
}



“filesize” değişkeni, sadece dosya’nın kendisi ile ilişkilidir. Dosyanın içeriği ile bir alakası yoktur.


Pozisyonu Verilen Veriye Erişme (Accesing Data at a Given Position)



Verinin dosyadaki konumunu ve sanal bellekteki adresini kesin bir şekilde biliyorsak, koşul yazmanın bir çok yolu vardır. Örn:



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
}



Kelime Dizilerinin Setleri (Sets of Strings)



Bazı durumlarda verilen kelime dizilerinin hepsine değil de bir kısmının dosyada yer alması yeterli olabilmektedir. Örn:



rule OfExample1
{
   strings:
       $a = “dummy1”
       $b = “dummy2”
       $c = “dummy3”

   condition:
       2 of ($a,$b,$c)
}



Bu kurala göre, “of” operatörü sayesinde, yukarıda verilen a,b ve c kelime dizilerinden herhangi 2 tanesinin dosya ile eşleşmesi yeterli olacaktır.



rule OfExample2
{
   strings:
       $foo1 = “foo1”
       $foo2 = “foo2”
       $foo3 = “foo3”

   condition:
       2 of ($foo*)  /
}
Yukarıdaki örnekte kullanılan 2 of ($foo*) yapısı, 2 of ($foo1, $foo2, $foo3) yapısı ile aynıdır. İkisinde de 3 kelime dizisinden herhangi iki tanesinin eşleşmesi yeterlidir.



Kelime dizilerinin setleri yapısında aşağıdaki tüm operatörler kullanılabilir.


all of them       /* Kural içindeki tüm stringler */
any of them       /* Kural içindeki herhangi bir string */
all of ($a*)      /* Kural içindeki $a ile başlayan tüm stringler */
any of ($a,$b,$c) /* Kural içindeki $a, $b veya $c kelime dizilerinden herhangi bir tanesi*/
1 of ($*)         /* any of them ile aynı */



“of” operatörünün özel bir kullanımı da “for …. of” şeklindedir. Aşağıdaki iki ifade aynıdır.



any of ($a,$b,$c)
for any of ($a,$b,$c) : ( $ )



Bir kaç fazla örnek göstermek gerekirse:



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



Diğer kuralları referans gösterme



Yazdığımız kuralları, diğer kurallara referans gösterebiliriz yani yazdığımız bir kuralı diğer kurala bağlı yazılabilir. Örn:

rule Rule1
{
   strings:
       $a = “dummy1”

   condition:
       $a
}

rule Rule2
{
   strings:
       $a = “dummy2”

   condition:
       $a and Rule1
}



Görüldüğü üzere, kural 2’yi kural 1’e bağımlı yazılmıştır.



Kurallar hakkında birkaç fazla bilgi:



Global Kurallar:



Global kurallar, tüm olasılıklar dönmeden önce çeşitli öncelikli kısıtlamalar yapar. Örneğin bir kural yazıldı ama öncelikli olarak o kuralın boyutu daha da önceliklidir, bu gibi durumlarda global kural kullanırız.



global rule SizeLimit
{
   condition:
       filesize < 2MB
}



Yukarıdaki örnekte, öncelikli olarak dosya boyutu kısıtlaması gerçekleşir, 2mb’den büyük dosyalar kısıtlamanın dışında kaldıktan sonra global olmayan kurallar devreye girer.



Metadata:



Kelime dizisi ve koşullar bölümü dışında kurallar meta kısmını da içerir. Meta kısmında yer alan bilgiler koşullar arasında yer alamaz çünkü değişken gibi değillerdir. Görevleri sadece kurallar hakkında daha fazla bilgi vermektir. Örn:



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
}



Dıştan Gelen Değişkenler (External Variables)



Dıştan gelen değişkenler normal değişkenler ile aynı özelliğe sahiptirler. Tamsayı, kelime dizisi veya boolean olarak tanımlanabilir. Bu değişkenlerin özelliği, herhangi başka bir kuraldan bu değişkene erişim sağlanıp, kullanılabilmesidir. Örn:


rule ExternalVariableExample1
{
   condition:
      ext_var == 10
}

rule ExternalVariableExample2
{
   condition:
      bool_ext_var or filesize < int_ext_var
}



Dahil Olan Dosyalar (Including Files)



Yara’nın sahip olduğu esnekliklerden bir tanesi de, “include” kelimesini kullanarak, başka bir yara kuralını(dosyasını) istediğimiz kurala dahil edebilmemizdir. Örn:



include “other.yar”



NOT: ekleyeceğimiz dosya ile üzerinde çalıştığımız dosya aynı dizinde olması lazımdır. Aksi taktirde dizini özellikle belirtmemiz gerekmektedir.



include “/home/plusvic/yara/includes/other.yar”



MODÜLLER



Modüller, yaranın özelliklerini-niteliklerini geliştirmesini sağlar. Ayrıntılı bilgi vermek gerekirse modüller kullanılması gereken büyük, kompleks şartların yer aldığı kurallarda, veri yapıları ve fonksiyon tanımlamamıza izin verirler.



KOMUT SATIRI ILE YARA (Running Yara from the commend-line)



Yara’nın çalıştırılabilmesi için 2 şeye ihtiyaç vardır:



1 – Kullanmak istediğiniz kuralların olduğu dosya
2 – Hedef. Hedef, dosya, klasör veya bir işlem(process) olabilir.



~ yara [OPTIONS] RULES_FILE TARGET



Bazı örnekler:



~ yara /foo/bar/rules1 /foo/bar/rules2 .



  • Rules1’deki kurallar okunur, hedef dosya Rules2’dir



~ yara -t Packer -t Compiler /foo/bar/rules bazfile



  • Rules dosyasındaki kurallar okunur, o an içerisinde bulunan dosya hedef dosyadır,    raporda sadece Packer ve Compiler olarak işaretlenenler bulunur.



~ yara -r /foo



  • foo dizini ve altındaki dizinlerin içerisindeki tüm dosyalar taranır.



~ yara -d mybool=true -d myint=5 -d mystring=”my string” /foo/bar/rules bazfile



  • burada 3 tane dışarıdan gelen(external) değişken tanımlanmıştır.



Kullanılabilir Seçenekler



-t <tag(değişken)>    -> “tag” olarak etiketlenen kuralları yazdırır, geri kalanları görmezden gelir.
-i <identifier> -> sadece kuralların ismini yazdırır
-n -> boşa çıkan kuralları yazdırır
-D –print-module-data -> modülün verisini yazdırır.
-g –print-tags -> etiketlenenleri yazdırır.
-m –pintt-meta -> metadata’yı yazdırır.
-s –print-strings -> eşleşen kelime dizilerini yazdırır.
-d <identifier> -> dışarıda değişken tanımlama
-r –recursive -> dizinlerin alt dizinlerini de tarar.
-f –fast-scan -> hızlı tarama yapar
-w –disable-warnings -> hataları görmezden gelir
-v –version -> kullandığınız yara sürümünün bilgilerini yazdırır
-h –help -> yardım kısmını gösterir
Bahadır KINALI (BGA|Security Intern)