Перейти к содержимому
New

DeepSeek V4.1 Flash free for 7 days: 10M tokens a day after a top-up of $10 or more. Until Nov 30.

How it works

Напишите правило YARA и проверьте его на безобидном тестовом файле

Напишите первое правило YARA, добейтесь совпадения с одним безобидным тестовым файлом и отсутствия совпадения с другим и узнайте, зачем каждому правилу нужны позитивные и негативные тесты.

Начальный8 мин чтенияАвтор: NotHoly

Что делает правило YARA

YARA — инструмент поиска по шаблонам. Вы пишете правило, которое описывает, как выглядит файл, а YARA выводит файлы, подходящие под описание. Чаще всего ею пользуются аналитики вредоносного ПО. Они пишут правила для строк, структуры файлов и последовательностей байтов, а затем сканируют папки, образы дисков и дампы памяти. Тот же механизм работает на любых ваших файлах, например на шаблоне, в котором не должно быть внутренней метки, или конфиге, в котором не должно быть токена.

YARA понятия не имеет, что опасно. Она находит то, что написано в правиле. Правило — это утверждение о байтах, и качество правила определяется этим утверждением.

Проект размещён на GitHub в организации VirusTotal. Официальное руководство по написанию правил на Read the Docs служит справочником по синтаксису. VirusTotal также поддерживает YARA-X, переписанную на Rust версию, которая сохраняет большую часть языка правил. Эти два инструмента пересекаются, но не идентичны, так что прочитайте заметки о совместимости, прежде чем переносить правило с одного на другой.

Зачем нужны правила

Хеш файла отвечает на один узкий вопрос: известен ли уже именно этот файл? Измените один байт, и хеш изменится. Подробнее об этом в статье о хешах файлов. Правило YARA задаёт вопрос шире: есть ли в файле ожидаемые фрагменты? Одно правило может совпасть со многими файлами, у которых есть общая строка, структура или шаблон байтов, даже если ни у одной пары нет общего хеша.

С этого более широкого вопроса начинаются и проблемы. Хеш почти никогда не совпадает с файлом, с которым не должен. Небрежное правило может совпасть с половиной файлового сервера. Поэтому учиться надо прежде всего писать правило, которое совпадает с нужным и больше ни с чем, и доказывать это на файлах, которые вы контролируете. Синтаксис здесь вторичен.

Устройство правила

У каждого правила есть имя, а за ним в фигурных скобках до трёх секций:

yara
rule Example_Rule {
  meta:
    description = "What this rule is for"

  strings:
    $text = "some text"

  condition:
    $text
}

Имена правил состоят из букв, цифр и подчёркиваний и не могут начинаться с цифры. Имя попадает в каждый отчёт о совпадении, поэтому выбирайте такое, по которому читателю понятно, о чём правило.

meta

В meta лежат пары ключ-значение для людей: описание, автор, дата, ссылка на исследование, на котором основано правило. YARA никогда не использует meta для решения о совпадении. Всё равно держите эти данные точными, потому что следующий человек, открывший файл, им поверит.

strings

Каждая строка получает идентификатор, начинающийся с $. Условие ссылается на строки по этому идентификатору. Строки бывают трёх видов.

Текстовые строки пишутся в двойных кавычках:

yara
$marker = "LAB-TRAINING-MARKER"

Модификаторы меняют способ сопоставления текста. nocase игнорирует регистр. wide сопоставляет текст UTF-16LE, где после каждого символа ASCII идёт нулевой байт, что обычно для бинарников Windows. fullword требует, чтобы совпадение стояло отдельно, вне более длинного слова.

Шестнадцатеричные строки пишутся в фигурных скобках и сопоставляют сырые байты:

yara
$mz = { 4D 5A }

Эти два байта — сигнатура MZ в начале многих исполняемых файлов Windows. ?? совпадает с любым одним байтом, [2-4] допускает разрыв от двух до четырёх неизвестных байтов, а ( 90 | 91 ) совпадает с любым из двух байтов.

Регулярные выражения пишутся между слешами:

yara
$version = /LAB-[A-Z]+ v[0-9]+/

Регулярка — самый гибкий вид строк, и её проще всего сделать слишком широкой. Если шаблон можно выразить обычной текстовой или шестнадцатеричной строкой, используйте её.

condition

Условие — булево выражение. Оно объединяет строки и свойства файла в один ответ: совпадение или нет.

  • $marker истинно, когда строка встречается хотя бы один раз.
  • any of them и all of them охватывают все строки правила. 2 of ($a, $b, $c) требует двух из трёх.
  • $marker at 0 требует, чтобы строка начиналась с первого байта. $marker in (0..512) требует, чтобы она была где-то в первых 512 байтах.
  • #marker > 3 считает вхождения.
  • filesize < 2KB проверяет размер файла.
  • uint16(0) == 0x5A4D читает первые два байта как целое little-endian и проверяет сигнатуру MZ.

Условие нужно каждому правилу. Правило со строками и без осмысленного условия либо сломано, либо бесполезно.

Как YARA читает правило

  1. YARA парсит файл правил и компилирует его. Синтаксическая ошибка останавливает запуск до чтения какого-либо файла.
  2. В каждом сканируемом файле YARA ищет все строки из секции strings.
  3. Затем она вычисляет условие по результатам шага 2.
  4. Если условие истинно, файл совпал. С -s YARA также печатает каждую совпавшую строку и смещение в байтах, где она найдена.

Сначала строки, потом условие. Условие вроде $a and $b строгое, потому что для совпадения правила нужно найти обе строки.

Лабораторная: один позитивный файл и один негативный

Ожидаемый вывод ниже описан словами, потому что точное форматирование в разных версиях YARA может отличаться. Сравнивайте то, что видите, с этими описаниями.

Работайте в пустой папке. В Windows выполняйте команды в Git Bash. Heredoc на шаге 3 в PowerShell работает иначе.

1. Установите yara

В Debian и Ubuntu:

bash
sudo apt install yara

В macOS через Homebrew:

bash
brew install yara

В Windows скачайте zip релиза с https://github.com/VirusTotal/yara/releases, распакуйте его и поместите исполняемый файл в PATH. Файл может называться yara64.exe. Переименуйте его в yara.exe или скопируйте под этим именем, чтобы команды ниже работали как написано.

Проверьте установку:

bash
yara --version

Вы должны увидеть номер версии. Эта статья версию не фиксирует, так что используйте последний релиз, который даёт ваш способ установки.

2. Создайте позитивный и негативный файлы

bash
mkdir yara-lab && cd yara-lab
printf 'LAB-TRAINING-MARKER v1\n' > match.txt
printf 'ordinary text file\n' > nomatch.txt

Оба файла — простой текст, написанный вами. Первый должен совпасть с правилом, второй не должен.

3. Напишите правило

Кавычки вокруг EOF важны. Без них shell заменит $m пустой переменной до того, как YARA увидит файл, и правило перестанет компилироваться.

bash
cat > lab.yar <<'EOF'
rule Lab_Training_Marker {
  meta: description = "Matches the lab training marker"
  strings: $m = "LAB-TRAINING-MARKER"
  condition: $m
}
EOF

В правиле три части. Meta говорит, для чего правило. Строка говорит, что в файле должен быть текст метки. Условие говорит, что файл совпадает, когда эта строка найдена хотя бы один раз.

4. Запустите позитивный тест

bash
yara -s lab.yar match.txt

YARA должна напечатать имя правила и путь к файлу. Из-за -s она также выводит совпавшую строку со смещением в байтах и найденным текстом. Метка начинается с первого байта match.txt, поэтому смещение должно быть 0x0.

5. Запустите негативный тест

bash
yara lab.yar nomatch.txt

Ожидаемый вывод: ничего. YARA печатает только совпадения, поэтому тишина значит, что файл не совпал.

Тишина что-то значит, только если сработал позитивный тест. Сначала выполните шаг 4. Если шаг 4 ничего не напечатал, дело в правиле или установке, и тишина на шаге 5 ни о чём не говорит.

6. Добавьте почти совпадающий файл

Почти совпадающий файл — самый полезный негативный, потому что он не проходит по одной узкой причине.

bash
printf 'LAB-TRAINING\n' > near.txt
yara lab.yar near.txt

Ожидаемый вывод: ничего. В файле есть начало метки, но нет полной строки, поэтому строка не найдена и условие ложно.

7. Просканируйте всю папку

bash
yara -r lab.yar .

Флаг -r сканирует папку рекурсивно. Ожидайте в выводе match.txt. Вероятно, вы увидите и lab.yar, сам файл правила. В файле правила есть текст метки, так что правило совпадает со своим исходником. Это частая ошибка, о ней расскажет следующий раздел. Держите правила в другой папке, отдельно от сканируемых данных.

Сделайте правило строже

Для учебной метки лабораторное правило подходит. Реальным правилам обычно нужно ограничение, которого одна строка не даёт. Допустим, вам нужны только небольшие файлы с меткой:

yara
rule Lab_Training_Marker_Small {
  strings: $m = "LAB-TRAINING-MARKER"
  condition: $m and filesize < 1KB
}

Проверьте так же. match.txt должен совпасть. nomatch.txt и near.txt не должны. С точки зрения тестов любое изменение строк или условия даёт новое правило, поэтому запускайте оба тестовых файла снова.

Как избежать правил, совпадающих со всем подряд

Это правило выглядит разумно:

yara
rule Too_Broad {
  strings: $a = "text"
  condition: $a
}

Оно совпадёт с nomatch.txt, потому что в предложении ordinary text file есть слово text. Проверить это можно на уже созданном негативном файле. Правило, совпавшее с ним, провалило собственный тест.

Шаблоны, которые совпадают со слишком многим:

  • Короткие строки или обычные слова вроде text, error, copyright или this program.
  • Однобайтовый или очень короткий шестнадцатеричный шаблон, например { 00 } или { 90 }.
  • nocase на обычном слове.
  • any of them по списку строк, каждая из которых встречается в обычных файлах.
  • Условие из одной только проверки размера, например filesize < 10KB, которому соответствует большинство небольших файлов.
  • Размытая регулярка, например /.+/.

Как ужесточить правило:

  • Выбирайте более длинные и характерные строки. Спросите себя, встретится ли строка в документе, который ваша организация пишет каждый день. Если встретится, выберите другую.
  • Требуйте больше одной строки через and или 2 of (...), чтобы результат не решала одна обычная строка.
  • Привязывайте поиск с помощью at или in, когда знаете, где должна быть строка.
  • Сочетайте проверку содержимого с проверкой заголовка или размера, например uint16(0) == 0x5A4D.

Частые ошибки

  1. Тестировать только позитивный файл. Правило, совпавшее с файлом, под который его писали, мало что доказывает. Оно может совпадать со всем.
  2. Пропускать почти совпадающие файлы. Обычные файлы редко проваливаются интересным образом. Файл, который почти совпал, ловит слишком свободную строку.
  3. Забывать кавычки в heredoc. Shell заменит $m до того, как YARA прочитает файл. См. шаг 3.
  4. Сканировать папку, где лежат правила. Файл правила совпадает со своим текстом.
  5. Верить meta. Описание со словами «детектирует X» X не детектирует. Это показывают только тестовые файлы.
  6. Править без повторного тестирования. Любое изменение строк или условия может изменить результат. После каждой правки запускайте оба теста снова.

Позитивные и негативные тесты до деплоя правила

Это самое главное правило в статье. Каждому правилу YARA нужны тестовые файлы обоих видов до того, как кто-то его задеплоит.

  • Позитивные файлы — файлы, с которыми правило обязано совпасть. В лабораторной это match.txt. В реальной работе это образцы, которые вы вправе хранить, по правилам обращения вашей организации.
  • Негативные файлы — файлы, с которыми правило совпадать не должно. Включите обычные документы, типы файлов, распространённые в вашей среде, чистые файлы с систем, которые планируете сканировать, и почти совпадающие файлы вроде near.txt.

Правило проходит, когда совпадает со всеми позитивными файлами и ни с одним негативным. Храните оба набора рядом с правилом, в системе контроля версий, если команда ею пользуется, и запускайте их после каждой правки. Правило, которое прошло позитивный тест, но ни разу не запускалось на негативных файлах, не протестировано.

Что дальше

  • Прочитайте руководство по написанию правил от начала до конца. В нём описаны модули вроде pe, с помощью которого правило проверяет заголовки и секции исполняемого файла Windows вместо сырых байтов.
  • Запустите то же лабораторное правило в YARA-X и сравните результаты. В документации YARA-X перечислено, что совместимо, а что нет.
  • Соберите чистый корпус: папку с обычными файлами с машин, которые вы контролируете. Каждое новое правило должно пройти его, прежде чем идти дальше.
  • Затем прочитайте статью о SIEM. В ней разобрана другая сторона детектирования: правила, которые работают по логам вместо файлов.

Источники

Источники

  1. YARA: Writing rules
  2. VirusTotal/yara on GitHub
  3. YARA-X documentation (VirusTotal)

Ещё по теме: Вредоносное ПО и форензика

Вредоносное ПО и форензика

Зачем использовать NotHoly для анализа malware

Статический triage в sandbox, который никогда не запускает образец, и модель, что объясняет и ложит на ATT&CK без отказа. Детонация в вашей лаборатории.

Средний3 мин чтения

Вредоносное ПО и форензика

Хеши файлов в DFIR и этика загрузки на VirusTotal

Как хеши идентифицируют файлы, почему SHA-256 сменил MD5, как NSRL отсеивает известное ПО и почему загрузка файла на VirusTotal означает его раскрытие.

Начальный8 мин чтения