はじめに
YARA というマルウェアのサンプルを識別・分類するツールがあることを知ったので試してみました。
YARA とは
YARA はマルウェアのサンプルを識別・分類するためのツールです。
以下のようにテキストまたはバイナリのパターン($a
, $b
, $c
)を定義し、判定ロジックをブール式($a or $b or $c
)で表現します。
rule silent_banker : banker { meta: description = "This is just an example" threat_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 のルールを書く
YARA のルールの書き方は、以下のページで説明されています。
最低限の書式は次のとおりです。rule ルール名 { ... }
が 1 つのルールです。strings:
に検出したいパターン、condition:
に判定結果を決めるロジックをブール式で記述します。
rule ルール名 {
strings:
$a = "Hello"
$b = "World"
$c = {58 35 4f 21}
condition:
($a or $b) and $c
}
YARA を Python から使う
YARA を Python から利用するためのライブラリとして yara-python
があります。
試しに使ってみます。
import yara
# "rm -rf /" を検出するルール.
rules = yara.compile(source="""
rule remove_root_directory {
strings:
$s = "rm -rf /"
condition:
$s
}
""")
# "Hello" と表示するだけの無害なコードを判定する.
# (何も検出されないことが期待値)
matches = rules.match(data="""
#!/bin/bash
echo Hello
""")
print(matches)
# ルートディレクトリを削除しようとする悪意のあるコードを判定する.
# (検出されることが期待値)
matches = rules.match(data="""
#!/bin/bash
rm -rf /
""")
print(matches)
実行結果は次のとおりです。
[]
[remove_root_directory]
EICAR とは
EICAR とはウィルス対策ソフトウェアのテストに用いるファイルです。正規の DOS プログラムであり、実行すると「EICAR-STANDARD-ANTIVIRUS-TEST-FILE!」というメッセージを出力します。
- Eicar – EUROPEAN EXPERT GROUP FOR IT-SECURITY (トップページ)
- Download Anti Malware Testfile – Eicar (ダウンロードページ)
EICAR は印字可能な文字だけで構成されているため、テキストエディタでも扱いやすいです。
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
16 進数でダンプした結果は以下の通りです。
$ xxd eicar.com
00000000: 5835 4f21 5025 4041 505b 345c 505a 5835 X5O!P%@AP[4\PZX5
00000010: 3428 505e 2937 4343 2937 7d24 4549 4341 4(P^)7CC)7}$EICA
00000020: 522d 5354 414e 4441 5244 2d41 4e54 4956 R-STANDARD-ANTIV
00000030: 4952 5553 2d54 4553 542d 4649 4c45 2124 IRUS-TEST-FILE!$
00000040: 482b 482a H+H*
YARA で EICAR を検出する
まずはルールを作成します。
rule eicar {
strings:
// 出力するメッセージにマッチするパターン
$message = "EICAR-STANDARD-ANTIVIRUS-TEST-FILE!"
// 先頭 8 バイトにマッチするパターン
$leading_bytes = {58 35 4f 21 50 25 40 41}
condition:
// どちらかのパターンにマッチする場合に検出する
$message or $leading_bytes
}
yara-python
を用いて実行してみます。
import yara
# EICAR を検出するルール.
rules = yara.compile(source="""
rule eicar {
strings:
// 出力するメッセージにマッチするパターン
$message = "EICAR-STANDARD-ANTIVIRUS-TEST-FILE!"
// 先頭 8 バイトにマッチするパターン
$leading_bytes = {58 35 4f 21 50 25 40 41}
condition:
// どちらかのパターンにマッチする場合に検出する
$message or $leading_bytes
}
""")
eicar = "X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*"
matches = rules.match(data=eicar)
print(matches)
期待通り検知できました。
[eicar]
おわりに
YARA を試した結果、いくつか良いと思う点がありました。以下にまとめます。
- 学習コストの低さ - ドキュメントを読みながら進めていけば、特に詰まることなく動かすことができました。時間もそれほどかかりませんでした。
- 判定ロジックの柔軟さ - 複数のパターンにマッチさせ、その結果をブール式で表現するため、単純な grep 検索よりも柔軟な条件を表現できました。
手元で作成したコードは以下にアップロードしました。
余談: 文章校正への活用
YARA is a tool aimed at (but not limited to) helping malware researchers to identify and classify malware samples.
GitHub - VirusTotal/yara: The pattern matching swiss knife
YARA のドキュメントを読むと、「YARA はマルウェア研究者がマルウェアのサンプルを識別・分類することを助けることを目的としたツールです。ただし、それに限定されません(but not limited to)。」と書かれています。
そこでマルウェア検出以外への活用を考えました。あまり妙案ではありませんが、文章校正に活用できるかもしれないと思いました。例えば、次のように特定の口癖が多く使われている場合を検出する、という使い方です。
// "あかん" or "アカン" を 3 回以上含む場合にマッチする
rule akan {
strings:
$s1 = "あかん"
$s2 = "アカン"
condition:
#s1 + #s2 >= 3
}
// "知らんけど" or "しらんけど" を 3 回以上含む場合にマッチする
rule shirankedo {
strings:
$s1 = "知らんけど"
$s2 = "しらんけど"
condition:
#s1 + #s2 >= 3
}
他にも YARA をマルウェア検出以外に活用する方法を考えてみようと思います。