YARA によるマルウェア検出入門

# はじめに

YARA というマルウェアのサンプルを識別・分類するツールがあることを知ったので試してみました。

# YARA とは

YARA はマルウェアのサンプルを識別・分類するためのツールです。

 * [GitHub - VirusTotal/yara: The pattern matching swiss knife](https://github.com/VirusTotal/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
> }
> ```
> https://github.com/VirusTotal/yara より引用。

# YARA のルールを書く

YARA のルールの書き方は、以下のページで説明されています。

 * [Writing YARA rules](https://yara.readthedocs.io/en/stable/writingrules.html)

最低限の書式は次のとおりです。`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` があります。

 * [GitHub - VirusTotal/yara-python: The Python interface for YARA](https://github.com/VirusTotal/yara-python)

試しに使ってみます。

```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](https://www.eicar.org/) (トップページ)
 * [Download Anti Malware Testfile – Eicar](https://www.eicar.org/?page_id=3950) (ダウンロードページ)

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` を用いて実行してみます。

```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 検索よりも柔軟な条件を表現できました。

手元で作成したコードは以下にアップロードしました。

https://github.com/suzuki-kei/try-yara-python

# 余談: 文章校正への活用

> 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](https://github.com/VirusTotal/yara)

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 をマルウェア検出以外に活用する方法を考えてみようと思います。