Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
YARA-Performance-Guidelines — 高速かつメモリ効率の良いYARAルールの書き方に関するガイド | Kitploit
ツール/GitHubGitHub/neo23x0/yara-performance-guidelines
静的分析マルウェア分析学習と教育
GitHubneo23x0/yara-performance-guidelines

YARA-Performance-Guidelines

高速かつメモリ効率の良いYARAルールの書き方に関するガイド

リポジトリを見る
174231年前Kitploit レビュー済み

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

YARAパフォーマンスガイドライン

効率的なYARAルールを作成することは、高速で正確なスキャンパフォーマンスを維持するために不可欠です。このガイドでは、ルールを最適化し、不要な計算を減らし、よくある落とし穴を回避するための主要な原則とベストプラクティスを提供します。Victor M. Alvarez氏、WXS氏など業界の専門家の知見と、YARAコミュニティからの貢献が組み込まれています。

  • リビジョン1.6(2025年2月)は、3.7より新しいすべてのYARAバージョンに適用されます。

重要なポイント

このセクションでは、YARAパフォーマンスのベストプラクティスの簡潔なまとめを提供します。詳細な説明と例については、以下の完全なガイドを参照してください。

YARAのスキャンプロセスを理解する

「YARAは2段階のプロセスとして考えてください。まず、stringsにリストされたすべてのパターンを検索し、次にconditionを評価します。適切に作成されたconditionで、不適切に選択された文字列を補うことはできません。」
— Wesley Shields

YARAはファイルをスキャンする際、4つの主要なステップを実行します:

  1. ルールのコンパイル – 定義された文字列からアトム(4バイトの部分文字列)を抽出します。
  2. Aho-Corasick検索 – ファイル内でそれらのアトムを検索します。
  3. バイトコードエンジン – 完全な文字列一致を検証します。
  4. conditionの評価 – 追加のルールロジックをチェックします。

文字列の選択 – 最も重要な要素

YARAは最初に文字列を検索するため、文字列の選択はルールの効率にとって最も重要な単一の要素です。

✅ 文字列に関するベストプラクティス:

  • 短い文字列を避ける(4バイト未満)– 誤検知が多くなりすぎます。
  • 一意な4バイトアトムを使用する – YARAは高速スキャンのためにこれらに依存します。
  • 16進文字列のワイルドカードを最小限にする – 少なくとも1つの長い具体的なセグメントを維持します。
  • 正規表現は控えめに使用する – 必要な場合は、効率を向上させるために固定の4バイトアンカーを含めます。
  • 単一バイトの繰り返しパターンを避ける – 例:\x00\x00\x00\x00は出現頻度が高すぎます。
  • nocaseは慎重に使用する – 検索バリエーションが指数関数的に増加します。

conditionの最適化とショートサーキット

YARAはconditionを順番に評価し、最初の失敗で停止します。

✅ conditionに関するベストプラクティス:

  • 高速なチェックを最初に置く(例:filesize < X)– 高コストなconditionの前に置きます。
  • 大量のデータに対するループを避ける(for all i in (1..filesize)は非効率です)。
  • シーケンスチェックには、正規表現の代わりに直接オフセット(@)を使用する。

⚠ 注記: 正規表現のconditionはショートサーキットされず、常に最後に評価されます。

モジュール – 注意して使用する

pe、elf、magicなどのモジュールは、評価の前にファイル全体を解析する必要があり、スキャン時間が増加します。

✅ 代替案:

  • pe.is_peの代わりにuint16(0) == 0x5A4Dを使用してPEファイルを識別します。
  • 深いファイル検査が必要でない限り、モジュールの使用を避けます。

「Too Many Matches」とスキャン速度低下への対処

過剰な一致はスキャンを遅くし、「too many matches」エラーを引き起こす可能性があります。

✅ 非効率な一致の修正:

  • 正規表現の量指定子を確認する – 上限のない.*、.+、{x,}を避けます。
  • 16進文字列のワイルドカードを減らす。
  • 可能であれば、代替(alternation)を個別の文字列に分割する。

ビデオチュートリアル

@herrcore が、このパフォーマンスガイドで説明されているトピックをカバーする役立つビデオチュートリアルを作成しました。

YARA入門 - 効率的なYARAルールの作成

基本

YARAのパフォーマンスをどこでどのように最適化できるかをより深く理解するには、スキャンプロセスを理解することが役立ちます。これは基本的に4つのステップに分かれており、次のサンプルルールを使って非常に簡略化して説明します:

root@kitploit:~
import "math"
rule example_php_webshell_rule
{
    meta:
        description = "Just an example php webshell rule"
        date = "2021/02/16"
    strings:
        $php_tag = "<?php"
        $input1   = "GET"
        $input2   = "POST"
        $payload = /assert[\t ]{0,100}\(/
    condition:
        filesize < 20KB and
        $php_tag and
        $payload and
        any of ( $input* ) and
        math.entropy(500, filesize-500) >= 5
}

1. ルールのコンパイル

このステップは実際のスキャンの前に行われます。YARAは、Aho-Corasickオートマトンに供給するために、検索文字列内のいわゆるatoms(アトム)を探します。詳細はアトムの章で説明されていますが、ここでは、それらが最大4バイト長であり、YARAが過剰な一致を避けるためにそれらを非常に賢く選択するということだけを知っていれば十分です。この例では、YARAは次の4つのアトムを選択する可能性があります:

  • <?ph
  • GET
  • POST
  • sser(assertから)

2. Aho-Corasickオートマトン

ここでスキャンが開始されます。ステップ2〜4はすべてのファイルに対して実行されます。YARAは、Aho-Corasickオートマトンと呼ばれるプレフィックスツリーを使用して、上記で定義した4つのアトムを各ファイル内で探します。一致したものはすべてバイトコードエンジンに引き渡されます。

3. バイトコードエンジン

例えばsserに一致した場合、YARAはその前にaが付き、続いてtが続くかをチェックします。それが真であれば、正規表現[\t ]{0,100}\(に従って処理を続けます。この賢いアプローチにより、YARAは低速な正規表現エンジンでファイル全体を処理することを避け、特定の部分だけを選んで詳しく調べます。

4. condition

すべてのパターンマッチングが完了した後、conditionがチェックされます。

YARAにはもう1つの最適化メカニズムがあり、サンプルルールのCPU負荷の高いmath.entropyチェックは、その前の4つのconditionが満たされた場合にのみ実行されます。詳細はconditionとショートサーキット評価の章で説明されています。

conditionが満たされると、一致が報告されます。スキャンはステップ2で次のファイルに続行されます。

アトム

YARAは、文字列から最大4バイト長の短い部分文字列を抽出します。これらは「アトム」と呼ばれます。これらのアトムは文字列内の任意の場所から抽出でき、YARAはファイルのスキャン中にそれらのアトムを検索します。アトムのいずれかが見つかった場合、YARAは文字列が実際に一致するかどうかを検証します。

例えば、次の文字列を考えてみましょう:

root@kitploit:~
/abc.*cde/

=> 可能なアトムはabcとcdeで、どちらか一方を使用できます。現在はabcアトムが優先されます。これは、両者の品質が同じで、abcが2つのうち最初に現れるためです。

root@kitploit:~
/(one|two)three/

=> 可能なアトムはone、two、thre、hreeで、thre(またはhree)だけを検索することも、oneとtwoの両方を検索することもできます。threアトムが優先されます。これは、oneやtwo(これらはより短い)よりも潜在的な一致が少なく、eの重複を含まないためです(より一意な文字ほど良い)。

YARAは各文字列から最良のアトムを選択するために最善を尽くします。例えば:

root@kitploit:~
{ 00 00 00 00 [1-4] 01 02 03 04 }

=> ここでは、00 00 00 00はあまりに一般的なため、YARAはアトム01 02 03 04を使用します。

root@kitploit:~
{ 01 02 [1-4] 01 02 03 04 }

=> 01 02 03 04は01 02よりも長いため、優先されます。

つまり、重要な点は、文字列に優れたアトムが含まれている必要があるということです。

次の文字列は、短すぎるアトムまたは一般的すぎるアトムを含むため、悪い文字列です:

root@kitploit:~
{00 00 00 00 [1-2] FF FF [1-2] 00 00 00 00}
{AB  [1-2] 03 21 [1-2] 01 02}
/a.*b/
/a(c|d)/

最悪の文字列は、アトムをまったく含まない文字列です。例:

root@kitploit:~
/\w.*\d/
/[0-9]+\n/

これらの正規表現は、アトムとして使用できる固定部分文字列をまったく含まないため、ファイルのすべてのオフセットで一致するかどうかを評価する必要があります。

ループの反復回数が多すぎる

もう1つの重要な推奨事項は、反復回数が多すぎるループを避けることです。特に、ループ内のステートメントが複雑すぎる場合は避けてください。例:

root@kitploit:~
strings:
	$a = {00 00}
condition:
	for all i in (1..#a) : (@a[i] < 10000)

このルールには2つの問題があります。1つ目は、文字列$aが一般的すぎることです。2つ目は、$aが一般的すぎるために#aが非常に大きくなり、何千回も評価される可能性があることです。

次のconditionも非効率です。反復回数がfilesizeに依存し、filesizeも非常に大きくなる可能性があるためです:

root@kitploit:~
for all i in (1..filesize) : ($a at i)

Magicモジュール

Windowsプラットフォームでは利用できない「magic」モジュールの使用は避けてください。「magic」モジュールを使用するとスキャンは遅くなりますが、正確な一致を提供します。

カスタムGIFマジックヘッダー定義:

root@kitploit:~
rule gif_1 {
  condition:
    (uint32be(0) == 0x47494638 and uint16be(4) == 0x3961) or
    (uint32be(0) == 0x47494638 and uint16be(4) == 0x3761)
}

「magic」モジュールを使用する場合:

root@kitploit:~
import "magic"
rule gif_2 {
  condition:
    magic.mime_type() == "image/gif"
}

短すぎる文字列

短すぎる文字列の定義は避けてください。4バイト未満の文字列は、多くのファイルに出現するか、XOR処理されたファイル内の均一なコンテンツとして出現する可能性が高いです。

均一なコンテンツ

中には十分に長いのに、別の理由(均一性)により使用すべきでない文字列もあります。ファイル内で「too many matches」を引き起こす可能性があるため使用すべきでない文字列の例をいくつか示します。

root@kitploit:~
$s1 = "22222222222222222222222222222222222222222222222222222222222222"
$s2 = "\x00\x20\x00\x20\x00\x20\x00\x20\x00\x20\x00\x20\x00\x20"  // wide formatted spaces

エラーメッセージは次のようになります:

root@kitploit:~
error scanning yara-killer.dat: string "$mz" in rule "shitty_mz" caused too many matches

文字列に関するアドバイス

文字列定義はできるだけ狭く記述するようにしてください。可能であれば「nocase」属性は避けてください。多くのアトムが生成されて検索されるためです(メモリ使用量の増加、反復回数の増加)。修飾子がない場合、デフォルトで「ascii」が想定されることを覚えておいてください。可能な組み合わせは次のとおりです:

LOW(低) - アトムが1つだけ生成されます

root@kitploit:~
$s1 = "cmd.exe"		       // (ascii only)
$s2 = "cmd.exe" ascii          // (ascii only, same as $s1)
$s3 = "cmd.exe" wide           // (UTF-16 only)
$s4 = "cmd.exe" ascii wide     // (both ascii and UTF-16) two atoms will be generated 
$s5 = { 63 6d 64 2e 65 78 65 } // ascii char code in hex

HIGH(高) - YARAが選択した4バイトについて、大文字と小文字のすべての組み合わせがアトムとして生成されます

root@kitploit:~
$s5 = "cmd.exe" nocase      (all different cases, e.g. "Cmd.", "cMd.", "cmD." ..)

スクリプトコマンドをマッチさせたい場合は、nocaseを使用する前に、その言語がそもそも大文字と小文字を区別しないかどうか(例:php、Windowsバッチ)を確認してください。1文字か2文字だけの大文字小文字の違いだけが必要な場合は、正規表現を使用する方がよいでしょう。例:

root@kitploit:~
$re = /[Pp]assword/

次のような代替(alternation)を扱うときは注意してください:

root@kitploit:~
$re = /(a|b)cde/
$hex = {C7 C3 00 (31 | 33)}

これらの文字列は短いアトムを生成するため、スキャンを遅くする可能性があります。 バリアントの数が少ない場合は、文字列を個別に記述することをお勧めします:

root@kitploit:~
$re1 = /acde/
$re2 = /bcde/
$hex1 = {C7 C3 00 31}
$hex2 = {C7 C3 00 33}

正規表現

必要な場合にのみ正規表現を使用してください。正規表現の評価は、プレーンな文字列マッチングよりも本質的に遅く、かなりの量のメモリを消費します。ジャンプとワイルドカードを持つ16進文字列で問題を解決できる場合は、正規表現を使用しないでください。

正規表現を使用しなければならない場合は、貪欲な.*や、控えめな量指定子.*?も避けてください。代わりに、.{1,30}や.{1,3000}のような正確な数値を使用してください。また、上限を忘れないでください(例:.{2,}を避ける)。

量指定子を使用する場合、2つの状況が発生する可能性があります:

正規表現の先頭が1つの位置に固定され、変化し得るのが接尾辞だけの場合、YARAは可能な限り長い一致をマッチします。.*、.+、.{2,}のような場合、これは大きな文字列につながり、スキャン速度の低下という問題を引き起こす可能性があります。

正規表現の先頭として可能な箇所が複数ある場合、YARAはそれらすべてをマッチします。

root@kitploit:~
$re1 = /Tom.{0,2}/		// will find Tomxx in "Tomxx"
$re2 = /.{0,2}Tom/      // will find Tom, xTom, xxTom in "xxTom"

短い一致の数は簡単に上限を超え、「too many matches」エラーを引き起こす可能性があります。

次の例は、電子メールアドレスの正規表現です。[-a-z0-9._%+]を量指定子と共に使用すると、YARAは1つのアドレスに複数回マッチしますが、これは理想的ではありません。この場合は、分析に十分な情報を提供する、適度に小さなアドレスのサブセットを見つけることをお勧めします。

使用

root@kitploit:~
/[-a-z0-9._%+]@[-a-z0-9.]{2,10}\.[a-z]{2,4}/
OR
/@[-a-z0-9.]{2,10}\.[a-z]{2,4}/ 

使用を避ける

root@kitploit:~
/[-a-z0-9._%+]*@[-a-z0-9.]{2,10}\.[a-z]{2,4}/
/[-a-z0-9._%+]+@[-a-z0-9.]{2,10}\.[a-z]{2,4}/
/[-a-z0-9._%+]{x,y}@[-a-z0-9.]{2,10}\.[a-z]{2,4}/

例えばexecの後に/bin/shが続くことを確認したい場合は、@記号によって提供されるオフセットを使用できます。以下は遅い正規表現バージョンです:

root@kitploit:~
$ = /exec.*\/bin\/sh/

以下はより高速なオフセットを使用する方法です:

root@kitploit:~
strings:
  $exec = "exec" 
  $sh   = "/bin/sh"
conditions:
  $exec and $sh and
  @exec < @sh

また、マッチングの進行においてアンカーとして機能する長い文字列シーケンスを含めるようにしてください。繰り返しますが、長ければ長いほど良いです。

悪い例

root@kitploit:~
$s1 = /http:\/\/[.]*\.hta/	// greedy [.]*

より良い例

root@kitploit:~
$s1 = /http:\/\/[a-z0-9\.\/]{3,70}\.hta/ 	// better, with an the upper bound

最良の例

root@kitploit:~
$s1 = /mshta\.exe http:\/\/[a-z0-9\.\/]{3,70}\.hta/

「Too Many Matches」エラーとスキャン速度低下

「Too many matches」エラーは、入力にあまりに頻繁に出現するあまりに一般的な文字列によって引き起こされるか、YARAが1つのインスタンスに複数回マッチすることによって引き起こされます。

スキャン速度の低下は、短すぎるアトムを生成する文字列、またはアトムをまったく生成しない文字列によって引き起こされます。その結果、YARAは単純な(naïve)パターンマッチングアルゴリズムを使用することになり、それが速度低下の原因となります。

これらの問題はどちらも、場合によっては次の手順で修正できます:

  1. 量指定子.*、.+、.*?がないか確認する
  2. 上限のない量指定子(x{14,}など)がないか確認する
  3. 範囲が大きすぎないか確認する(例:x{1,300000})
  4. 16進文字列の大きなジャンプがないか確認する
  5. ワイルドカード文字を確認する – より精密に指定できないか、またはワイルドカード文字を省略して文字列を2つに分割できないか?
  6. 代替(alternation)を確認する:2つ以上の文字列に分割できるか?
  7. 単語マッチングの指定(fullword、\bなど)を追加してみる

次の章conditionとショートサーキット評価では、conditionに関するいくつかのヒントが紹介されています。ただし、それらの変更は「too many matches」エラーやスキャン速度低下エラーを解決しません。

conditionとショートサーキット評価

「False」になる可能性が最も高い要素が最初に配置されるように、conditionステートメントを記述してください。conditionは左から右に評価されます。エンジンがルールの不成立を識別するのが早いほど、現在のルールをスキップして次のルールを評価するのも早くなります。このようにconditionステートメントを並べることで得られる速度向上は、各ステートメントの処理に必要なCPUサイクルの差に依存します。すべてのステートメントのコストがほぼ同等であれば、ステートメントの並べ替えによる顕著な改善はありません。いずれかのステートメントを非常に高速に処理できる場合は、それを最初に配置することをお勧めします。最初のステートメントがFALSEの場合に、高コストなステートメントの評価をスキップできるためです。

次のステートメントの順序を変更しても、大きな改善にはなりません:

root@kitploit:~
$string1 and $string2 and uint16(0) == 0x5A4D

ただし、ステートメントの実行時間が大きく異なる場合は、ショートサーキットをトリガーするように並べ替えることで、スキャン速度が大幅に向上します:

SLOW(遅い)

root@kitploit:~
// EXPENSIVE and CHEAP
math.entropy(0, filesize) > 7.0 and uint16(0) == 0x5A4D

FAST(速い)

root@kitploit:~
// CHEAP and EXPENSIVE
uint16(0) == 0x5A4D and math.entropy(0, filesize) > 7.0

ショートサーキット評価は、高コストなステートメント、特に「for」ステートメントの最適化を支援するために導入されました。次の例のようなconditionを使用している人もいました:

root@kitploit:~
strings:
	$mz = "MZ"
	...
condition:
	$mz at 0 and for all i in (1..filesize) : ( whatever )

filesizeは非常に大きな数になり得るため、「whatever」が何度も実行され、実行が遅くなる可能性があります。ショートサーキット評価により、「for」ステートメントはconditionの最初の部分が満たされた場合にのみ実行されるため、このルールが遅くなるのはMZファイルのみです。さらなる改善としては次のようなものがあります:

root@kitploit:~
$mz at 0 and filesize < 100KB and for all i in (1..filesize) : ( whatever )

これにより、反復回数に上限が設定されます。

バージョン3.10以降、整数範囲ループも最適化されました:

root@kitploit:~
for all i in (0..100): (false)
for any i in (0..100): (true)

Both of these loops will stop iterating after the first time through.

正規表現にはショートサーキットはない

残念ながら、これは正規表現には機能しません。正規表現はすべて最初に文字列マッチングエンジンに供給されるためです。次の例は、filesizeが200バイト未満のファイルだけでなく、すべてのファイルの検索を遅くします:

root@kitploit:~
strings:
  $expensive_regex = /\$[a-z0-9_]+\(/ nocase
conditions:
  filesize < 200 and
  $expensive_regex

この「ショートサーキット」評価は、YARAバージョン3.4以降で適用されます。

メタデータ

メタデータセクション内のデータは、すべてYARAによってRAMに読み込まれます。(ルールに100,000個のハッシュを挿入し、その前後のYARAスキャンのRAM使用量を確認することで、これを簡単にテストできます。)もちろん、ルールからメタデータを恒久的に削除したいわけではないでしょう。しかし、RAMが不足している場合は、スキャンの直前のワークフローで不要な部分をいくつか削除してもよいでしょう。

ツールをダウンロード