Содержание статьи
- Правила
- Шестнадцатеричные строки
- Текстовые строки и их модификаторы
- Регулярные выражения
- Условия (condition)
- Специальные переменные
- Чтение данных по смещению
- Ссылки на другие правила
- Структура правила целиком
- Модификаторы правил
- Теги
- Метаданные
- Модули YARA
- PE — анализ файлов PE
- ELF — анализ файлов ELF
- dotPeek — анализ сборок .NET
- Hash — криптографические хеши
- Math — математика и статистика
- Cuckoo — поведенческий анализ
- Time — временные условия
- Console — отладка правил
- String — работа со строками модулей
- Практика: сканирование файлов
- Установка yara-python
- Формулировка критериев
- Написание правил
- Скрипт сканирования
- Интерпретация результатов
YARA — это популярный инструмент для поиска и классификации малвари. Он работает на основе специальных правил, которые движок может применять к процессам и файлам. YARA создал Виктор Альварес (Victor Alvarez) во время работы в VirusTotal. Сегодня инструмент служит стандартом де‑факто для описания сигнатур вредоносных программ.
Понимание его внутренней работы дает представление о том, как устроены антивирусные сигнатуры и почему они выглядят именно так. Движок легко расширяется за счет пользовательских модулей на C, что позволяет добавлять произвольную логику анализа. На примере YARA легко проследить эволюцию антивирусных технологий: от простейших скан‑строк эпохи DOS до современных составных правил с вложенными условиями и данными от нативных модулей. В этой главе рассматривается YARA 4.5.8 — актуальная версия на момент подготовки текста.
Книга «Обход антивирусов на практике»
Это первая глава из книги «Обход антивирусов на практике».

Часть глав будет опубликована на сайте, а полная версия выйдет на бумаге. В первых частях рассматриваются алгоритмы детектирования, за ними следуют слепой поиск сигнатур и разбор методов обхода современных антивирусных движков.
Правила
В основе YARA лежит концепция правил (rules). Каждое правило описывает набор признаков — строк, последовательностей байтов, регулярных выражений, а также логических условий, при выполнении которых срабатывает детектирование. По сути, аналитик формализует свои знания о конкретном семействе малвари в виде правила YARA, после чего его можно автоматически применять к любым семплам.
rule MD5_API {
meta:
author = "_pusher_"
description = "Looks for MD5 API"
date = "2016-07"
strings:
$advapi32 = "advapi32.dll" wide ascii nocase
$cryptdll = "cryptdll.dll" wide ascii nocase
$MD5Init = "MD5Init" wide ascii
$MD5Update = "MD5Update" wide ascii
$MD5Final = "MD5Final" wide ascii
condition:
($advapi32 or $cryptdll) and ($MD5Init and $MD5Update and $MD5Final)
}
Например, это правило детектирует применение функций WinAPI, специализирующихся на расчете MD5-хеша. Оно ищет строчки с модификаторами wide — вариации с любым регистром, в однобайтовом (ASCII) или двухбайтовом (wide) бинарном представлении, после чего проверяет истинность условия (condition) — наличие хотя бы одной из двух DLL и всех указанных API.
Работу YARA можно разделить на компиляцию и сканирование. При компиляции движок разбирает правила, компилирует условия и извлекает из строк атомы — короткие последовательности байтов, по которым удобно быстро находить возможные совпадения. Из атомов строится автомат Ахо — Корасик. Мы рассмотрим его в одной из следующих глав. Во время сканирования он ищет эти последовательности в файле, после каждого совпадения проверяет полный строковый или байтовый шаблон, вычисляет условия и выводит сработавшие правила.
Сила YARA — в гибкости описания паттернов. В секции strings поддерживаются три типа сигнатур: шестнадцатеричные строки, текстовые строки и регулярные выражения. В синтаксисе YARA они называются просто строками. Каждый тип обладает набором конструкций и модификаторов, позволяющих описывать как точные, так и нечеткие совпадения.
Шестнадцатеричные строки
Шестнадцатеричные строки описывают последовательности байтов и служат основным инструментом для работы с бинарным содержимым — машинным кодом, заголовками файловых форматов, «магическими» и криптографическими константами. Записываются в фигурных скобках как пары шестнадцатеричных цифр, разделенных пробелами.
rule RawBytes
{
strings:
$hex = { E2 34 A1 C8 23 FB }
condition:
$hex
}
Четыре специальные конструкции — wildcard, отрицание, переходы и альтернативы — превращают примитивный побайтовый поиск в полноценный язык описания бинарных паттернов. Без них описание сигнатур байт‑кода было бы практически невозможным, потому что даже минимальные различия в сборке (другой компилятор, другая версия, другие флаги оптимизации) приводят к изменению конкретных байтов.
Wildcard (подстановочные символы)
Символ ? заменяет неизвестный полубайт (nibble). Wildcard работает именно на уровне полубайтов — это принципиально, поскольку позволяет зафиксировать старшую или младшую половину байта, оставив другую произвольной. Такая гранулярность нужна, например, при описании опкодов x86, где старший полубайт кодирует операцию, а младший — регистр.
$hex = { E2 34 ?? C8 A? FB }
Здесь:
??— любой байт целиком (от00доFF);A?— старший полубайт равенA, младший — любой (отA0доAF).
Инструкции x86 часто содержат переменные поля (ModR/M, SIB, displacement), и wildcard позволяет абстрагироваться от конкретных регистров или смещений. Например, инструкция mov 32-битного регистра кодируется байтами B8 — BF в зависимости от целевого регистра, а call — байтом E8 с четырьмя байтами относительного адреса. Запись B? здесь не подходит, поскольку она охватывает весь диапазон B0 — BF. Поэтому опкоды mov нужно перечислить явно:
( B8 | B9 | BA | BB | BC | BD | BE | BF ) ?? ?? ?? ??
Для call достаточно шаблона E8 , где четыре байта wildcard заменяют относительный адрес.
NOT (отрицание)
Оператор ~ (тильда) перед байтом значит «любое значение, кроме указанного». Если wildcard — это «мне все равно, какой байт», то отрицание — это «мне все равно, какой байт, лишь бы не вот этот». Комбинация wildcard и отрицания позволяет исключать конкретные нежелательные варианты без необходимости перечислять все допустимые альтернативы.
$hex = { F4 23 ~00 62 B4 }
$hex2 = { F4 23 ~?0 62 B4 }
~00— любой байт, кроме нулевого;~0?— любой байт, у которого старший полубайт не равен 0.
Полезно для исключения конкретных вариантов инструкций или данных. Например, можно описать jmp с ненулевым смещением (EB ) или последовательность байтов, где определенное поле не должно быть пустым. Отрицание также комбинируется с полубайтовым wildcard: запись ~?0 значит «младший полубайт не равен нулю», что покрывает 240 из 256 возможных значений байта вместо 255.
Jumps (переходы)
Подстановочные символы и отрицание решают проблему неизвестного содержимого при известной длине. Но бывают ситуации, когда неизвестна сама длина промежуточного фрагмента — между двумя значимыми паттернами может находиться от парочки до сотен байтов. Для этого существуют переходы (jumps) — диапазоны в квадратных скобках:
$hex = { F4 23 [4-6] 62 B4 }Это значит: между F4 и 62 может быть от 4 до 6 произвольных байтов. Допустимые формы:
| Синтаксис | Расшифровка |
|---|---|
[ | От 4 до 6 байт |
[ | От 10 байт до бесконечности |
[ | От 0 байт до бесконечности |
Переходы критически важны в нескольких типичных сценариях.
Во‑первых, компилятор может вставлять выравнивание (padding) и инструкции NOP между функциями, и их количество непредсказуемо.
Во‑вторых, между двумя ключевыми инструкциями в функции часто находится переменное количество промежуточного кода — другие флаги оптимизации сгенерируют другое количество инструкций.
В‑третьих, данные в структурах файловых форматов могут иметь поля переменной длины (строки, массивы), и переход позволяет «перепрыгнуть» их, привязавшись к маркерам начала и конца. Неограниченный переход [ — это, по сути, утверждение «эти два паттерна встречаются в файле в указанном порядке на произвольном расстоянии».
Alternatives (альтернативы)
Конструкция ( ... задает несколько допустимых вариантов для фрагмента. Синтаксис заимствован из регулярных выражений: варианты перечисляются через | внутри круглых скобок.
$hex = { F4 23 ( 62 B4 | 56 | 45 ?? 67 ) 45 }
Продолжение доступно только участникам
Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».
Присоединяйся к сообществу «Xakep.ru»!
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
