Post

Malware Analysis 2 - All about Yara rules

pic

Introduction

Hi friends!

In this post we will learn how threat hunters use YARA rules to detect potential security risks, how to write them and much more about that.

pic

Explanation

YARA stands for Yet Another Ridiculous Acronym and they are used by all threat hunters as it can save a lot of time doing custom operations to decide whether a file is malicious or not. All the antivirus also use this, a full list of apps which use YARA is available on its official repo.

pic

Here are some key points about YARA rules:

  1. Structure

Rules consists of two main parts, a body and a header. The header contains metadata and the body contains the pattern to search for.

  1. Pattern matching

YARA uses regular expressions and other matching rules to search for potential malware instructions based on file and memory.

  1. Conditionals

Rules can also include conditional statements that allow for more complex matching logic. For example, a rule might only match if a certain pattern is found within a certain range of memory addresses.

  1. Variables

They can also use variables to make them more flexible. For example, a variable might be used to specify a file path or to store a particular value that is used in the matching logic.

  1. Rule priorization

YARA rules can be prioritized, so that if multiple rules match a particular file or memory segment, the rule with the highest priority will be used.

How to write YARA rules

The official “language” documentation about how to write your own YARA rules is here

Anyway, we’ll learn how YARA works and how to do most basic operations with examples

Strings

There are 3 types:

  1. Hexadecimal strings (i.e. { E2 34 D2 C8 } )
  2. Text string (i.e. “example” )
  3. Regular expressions (i.e. [4-6] )

Conditions and examples

It allows boolean (i.e. or), relational (i.e. >=), arithmetic (i.e. +) and bitwise (i.e. &) operators.

  • Counting strings

If we have the variable $a we can use #a to get how much times that string appears

  • Filesize

To get file size we also can use the filesize internal variable (note that $ is missing) which contains the value in bytes

  • Sets of strings

If we want to check if for example 2 of 3 conditions were true we can do that like this:

1
2
3
4
5
6
7
8
9
10
rule Test
{
    strings:
        $a = "example1"
        $b = "example2"
        $c = "example3"

    condition:
        2 of ($a,$b,$c) // 2 of 3 conditions are true
}

In this case, we can also use 2 of ($*) or 2 of them instead of 2 of ($a,$b,$c)

You can approach the internal operators like this:

1
2
3
4
5
6
all of them       // all strings in the rule
any of them       // any string in the rule
all of ($a*)      // all strings whose identifier starts by $a
any of ($a,$b,$c) // any of $a, $b or $c
1 of ($*)         // same that "any of them"
none of ($b*)     // zero of the set of strings that start with "$b"
  • Virtual addresses

We can get the offset of a string in a file using the @ character for example if we have $a = "example" its offset will be @a

If we want to iterate over the offsets we can do it like this:

1
2
3
4
5
6
7
8
9
rule Occurrences
{
    strings:
        $a = "example1"
        $b = "example2"

    condition:
        for all i in (1..3) : ( @a[i] + 10 == @b[i] )
}
  • Other rules

you can also create a condition which includes another rule

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
rule Rule1
{
    strings:
        $a = "example1"

    condition:
        $a
}

rule Rule2
{
    strings:
        $a = "example2"

    condition:
        $a and Rule1 // Use other rule on the condition
}

Metadata

We can also include information in our rules which isn’t interpreted but is really useful between other threat hunters as the community shares their own rules and it can provide better documentation about them, using the meta keyword

This is a real rule example you can find here:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
rule BlackEnergy_BackdoorPass_DropBear_SSH
{

    meta:
        description = "Detects the password of the backdoored DropBear SSH Server - BlackEnergy"
        author = "Florian Roth"
        reference = "http://feedproxy.google.com/~r/eset/blog/~3/BXJbnGSvEFc/"
        date = "2016-01-03"
        hash = "0969daac4adc84ab7b50d4f9ffb16c4e1a07c6dbfc968bd6649497c794a161cd"

    strings:
        $s1 = "passDs5Bu9Te7" fullword ascii

    condition:
        uint16(0) == 0x5a4d and $s1
}

Anyway, you can use the names you want for your metadata values since it doesn’t affect the code

Comments

To use them just do exactly the same as in C lang

1
2
3
4
5
6
7
8
// Single-line comment

/*

This is a
multiline comment

*/

Modules

I won’t cover this in depth but YARA also allows external modules and they’re pretty straightforward to use

To import one just do it like this:

1
import "cuckoo"

And to use a function from a module:

1
cuckoo.http_request(/someregexp/)

Where cuckoo is the module, http_request is the function and /someregexp/ stands for the argument(s)

If you want to create your own modules, check this out

How to use the rules

First of all we have to install the YARA CLI app with our package manager

Debian-based (Kali Linux, Parrot OS, Ubuntu…)

1
apt install yara

Arch-based (ArchLinux, BlackArch…)

1
pacman -S yara

These are all the rules to detect BlackEnergy malware:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/*
	Yara Rule Set
	Author: Florian Roth
	Date: 2015-02-19
	Identifier: BlackEnergy Malware
*/

rule BlackEnergy_BE_2
{

   meta:
      description = "Detects BlackEnergy 2 Malware"
      author = "Florian Roth"
      reference = "http://goo.gl/DThzLz"
      date = "2015/02/19"
      hash = "983cfcf3aaaeff1ad82eb70f77088ad6ccedee77"

   strings:
      $s0 = "<description> Windows system utility service  </description>" fullword ascii
      $s1 = "WindowsSysUtility - Unicode" fullword wide
      $s2 = "msiexec.exe" fullword wide
      $s3 = "WinHelpW" fullword ascii
      $s4 = "ReadProcessMemory" fullword ascii

   condition:
      uint16(0) == 0x5a4d and filesize < 250KB and all of ($s*)
}

rule BlackEnergy_VBS_Agent
{

    meta:
        description = "Detects VBS Agent from BlackEnergy Report - file Dropbearrun.vbs"
        author = "Florian Roth"
        reference = "http://feedproxy.google.com/~r/eset/blog/~3/BXJbnGSvEFc/"
        date = "2016-01-03"
        hash = "b90f268b5e7f70af1687d9825c09df15908ad3a6978b328dc88f96143a64af0f"

    strings:
        $s0 = "WshShell.Run \"dropbear.exe -r rsa -d dss -a -p 6789\", 0, false" fullword ascii
        $s1 = "WshShell.CurrentDirectory = \"C:\\WINDOWS\\TEMP\\Dropbear\\\"" fullword ascii
        $s2 = "Set WshShell = CreateObject(\"WScript.Shell\")" fullword ascii /* Goodware String - occured 1 times */

    condition:
        filesize < 1KB and 2 of them
}

rule DropBear_SSH_Server
 {

    meta:
        description = "Detects DropBear SSH Server (not a threat but used to maintain access)"
        author = "Florian Roth"
        reference = "http://feedproxy.google.com/~r/eset/blog/~3/BXJbnGSvEFc/"
        date = "2016-01-03"
        score = 50
        hash = "0969daac4adc84ab7b50d4f9ffb16c4e1a07c6dbfc968bd6649497c794a161cd"

    strings:
        $s1 = "Dropbear server v%s https://matt.ucc.asn.au/dropbear/dropbear.html" fullword ascii
        $s2 = "Badly formatted command= authorized_keys option" fullword ascii
        $s3 = "This Dropbear program does not support '%s' %s algorithm" fullword ascii
        $s4 = "/etc/dropbear/dropbear_dss_host_key" fullword ascii
        $s5 = "/etc/dropbear/dropbear_rsa_host_key" fullword ascii

    condition:
        uint16(0) == 0x5a4d and filesize < 1000KB and 2 of them
}

rule BlackEnergy_BackdoorPass_DropBear_SSH
{

    meta:
        description = "Detects the password of the backdoored DropBear SSH Server - BlackEnergy"
        author = "Florian Roth"
        reference = "http://feedproxy.google.com/~r/eset/blog/~3/BXJbnGSvEFc/"
        date = "2016-01-03"
        hash = "0969daac4adc84ab7b50d4f9ffb16c4e1a07c6dbfc968bd6649497c794a161cd"

    strings:
        $s1 = "passDs5Bu9Te7" fullword ascii

    condition:
        uint16(0) == 0x5a4d and $s1
}

rule BlackEnergy_KillDisk_1
{

    meta:
        description = "Detects KillDisk malware from BlackEnergy"
        author = "Florian Roth"
        reference = "http://feedproxy.google.com/~r/eset/blog/~3/BXJbnGSvEFc/"
        date = "2016-01-03"
        score = 80
        super_rule = 1
        hash1 = "11b7b8a7965b52ebb213b023b6772dd2c76c66893fc96a18a9a33c8cf125af80"
        hash2 = "5d2b1abc7c35de73375dd54a4ec5f0b060ca80a1831dac46ad411b4fe4eac4c6"
        hash3 = "c7536ab90621311b526aefd56003ef8e1166168f038307ae960346ce8f75203d"
        hash4 = "f52869474834be5a6b5df7f8f0c46cbc7e9b22fa5cb30bee0f363ec6eb056b95"

    strings:
        $s0 = "system32\\cmd.exe" fullword ascii
        $s1 = "system32\\icacls.exe" fullword wide
        $s2 = "/c del /F /S /Q %c:\\*.*" fullword ascii
        $s3 = "shutdown /r /t %d" fullword ascii
        $s4 = "/C /Q /grant " fullword wide
        $s5 = "%08X.tmp" fullword ascii
        $s6 = "/c format %c: /Y /X /FS:NTFS" fullword ascii
        $s7 = "/c format %c: /Y /Q" fullword ascii
        $s8 = "taskhost.exe" fullword wide /* Goodware String - occured 1 times */
        $s9 = "shutdown.exe" fullword wide /* Goodware String - occured 1 times */

    condition:
        uint16(0) == 0x5a4d and filesize < 500KB and 8 of them
}

rule BlackEnergy_KillDisk_2
{

    meta:
        description = "Detects KillDisk malware from BlackEnergy"
        author = "Florian Roth"
        reference = "http://feedproxy.google.com/~r/eset/blog/~3/BXJbnGSvEFc/"
        date = "2016-01-03"
        score = 80
        super_rule = 1
        hash1 = "11b7b8a7965b52ebb213b023b6772dd2c76c66893fc96a18a9a33c8cf125af80"
        hash2 = "5d2b1abc7c35de73375dd54a4ec5f0b060ca80a1831dac46ad411b4fe4eac4c6"
        hash3 = "f52869474834be5a6b5df7f8f0c46cbc7e9b22fa5cb30bee0f363ec6eb056b95"

    strings:
        $s0 = "%c:\\~tmp%08X.tmp" fullword ascii
        $s1 = "%s%08X.tmp" fullword ascii
        $s2 = ".exe.sys.drv.doc.docx.xls.xlsx.mdb.ppt.pptx.xml.jpg.jpeg.ini.inf.ttf" fullword wide
        $s3 = "%ls_%ls_%ls_%d.~tmp" fullword wide

    condition:
        uint16(0) == 0x5a4d and filesize < 500KB and 3 of them
}

rule BlackEnergy_Driver_USBMDM
{

    meta:
        description = "Auto-generated rule - from files 7874a10e551377d50264da5906dc07ec31b173dee18867f88ea556ad70d8f094, b73777469f939c331cbc1c9ad703f973d55851f3ad09282ab5b3546befa5b54a, edb16d3ccd50fc8f0f77d0875bf50a629fa38e5ba1b8eeefd54468df97eba281"
        author = "Florian Roth"
        reference = "http://www.welivesecurity.com/2016/01/03/blackenergy-sshbeardoor-details-2015-attacks-ukrainian-news-media-electric-industry/"
        date = "2016-01-04"
        super_rule = 1
        hash1 = "7874a10e551377d50264da5906dc07ec31b173dee18867f88ea556ad70d8f094"
        hash2 = "b73777469f939c331cbc1c9ad703f973d55851f3ad09282ab5b3546befa5b54a"
        hash3 = "edb16d3ccd50fc8f0f77d0875bf50a629fa38e5ba1b8eeefd54468df97eba281"
        hash4 = "ac13b819379855af80ea3499e7fb645f1c96a4a6709792613917df4276c583fc"
        hash5 = "7a393b3eadfc8938cbecf84ca630e56e37d8b3d23e084a12ea5a7955642db291"
        hash6 = "405013e66b6f137f915738e5623228f36c74e362873310c5f2634ca2fda6fbc5"
        hash7 = "244dd8018177ea5a92c70a7be94334fa457c1aab8a1c1ea51580d7da500c3ad5"
        hash8 = "edcd1722fdc2c924382903b7e4580f9b77603110e497393c9947d45d311234bf"

    strings:
        $s1 = "USB MDM Driver" fullword wide
        $s2 = "KdDebuggerNotPresent" fullword ascii /* Goodware String - occured 50 times */
        $s3 = "KdDebuggerEnabled" fullword ascii /* Goodware String - occured 69 times */
    condition:
        uint16(0) == 0x5a4d and filesize < 180KB and all of them
}

rule BlackEnergy_Driver_AMDIDE
{

    meta:
        description = "Auto-generated rule - from files 32d3121135a835c3347b553b70f3c4c68eef711af02c161f007a9fbaffe7e614, 3432db9cb1fb9daa2f2ac554a0a006be96040d2a7776a072a8db051d064a8be2, 90ba78b6710462c2d97815e8745679942b3b296135490f0095bdc0cd97a34d9c, 97be6b2cec90f655ef11ed9feef5b9ef057fd8db7dd11712ddb3702ed7c7bda1"
        author = "Florian Roth"
        reference = "http://www.welivesecurity.com/2016/01/03/blackenergy-sshbeardoor-details-2015-attacks-ukrainian-news-media-electric-industry/"
        date = "2016-01-04"
        super_rule = 1
        hash1 = "32d3121135a835c3347b553b70f3c4c68eef711af02c161f007a9fbaffe7e614"
        hash2 = "3432db9cb1fb9daa2f2ac554a0a006be96040d2a7776a072a8db051d064a8be2"
        hash3 = "90ba78b6710462c2d97815e8745679942b3b296135490f0095bdc0cd97a34d9c"
        hash4 = "97be6b2cec90f655ef11ed9feef5b9ef057fd8db7dd11712ddb3702ed7c7bda1"
        hash5 = "5111de45210751c8e40441f16760bf59856ba798ba99e3c9532a104752bf7bcc"
        hash6 = "cbc4b0aaa30b967a6e29df452c5d7c2a16577cede54d6d705ca1f095bd6d4988"
        hash7 = "1ce0dfe1a6663756a32c69f7494ad082d293d32fe656d7908fb445283ab5fa68"

    strings:
        $s1 = " AMD IDE driver" fullword wide
        $s2 = "SessionEnv" fullword wide
        $s3 = "\\DosDevices\\{C9059FFF-1C49-4445-83E8-" wide
        $s4 = "\\Device\\{C9059FFF-1C49-4445-83E8-" wide

    condition:
        uint16(0) == 0x5a4d and filesize < 150KB and all of them
}

Then we could use it like this:

1
yara rule.yar malware.exe

If you want to test this out with real malwares you should take a look at some well known Github repos like theZoo or MalwareSourceCode

Using VirusTotal

This is the best online malware analyzer (or at least the most used), with a lot of capabilities to detect potential malwares, it obviously uses YARA. https://virustotal.com

Let’s upload our malware sample there to see what it says:

pic

And it obviously gets detected as malicious

pic

See yourself the results here

References

1
2
3
4
5
6
7
8
9
https://github.com/Yara-Rules/rules
https://yara.readthedocs.io/en/stable/writingrules.html
https://medium.com/@laroshkhanpk/threat-hunting-101-hunting-with-yara-rules-82aff0898674
https://blog.apnic.net/2022/03/09/threat-hunting-with-yara-the-three-body-problem/
https://github.com/virustotal/yara
https://github.com/InQuest/awesome-yara
https://github.com/GossiTheDog/ThreatHunting
https://github.com/Neo23x0/signature-base
https://github.com/advanced-threat-research/Yara-Rules

Conclusion

I hope you’ve learned how to write your own YARA rules, how to use them in threat hunting and how they work. Overall, YARA rules are a powerful tool for identifying and classifying malware.

Source code here

Go back to top

This post is licensed under CC BY 4.0 by the author.