Статическая сортировка образца

Статика — это первый осмотр образца без его запуска: по хешам, строкам, импортам и энтропии аналитик решает, с чем имеет дело.

Статическая сортировка (static triage) — быстрый анализ файла без исполнения: вычисление хешей, проверка репутации, извлечение строк, разбор таблицы импортов и оценка энтропии, чтобы понять характер образца и расставить приоритеты.

Запуск опасен и не всегда нужен: огромную часть выводов можно получить, вообще не исполняя файл. Статика безопаснее динамики и часто отвечает на вопрос «стоит ли вообще тратить время на этот образец». Всё, что ниже, делается в изолированной ВМ из прошлого урока, на образцах, которые вы вправе исследовать.

Зачем это знать защитнику

Статические признаки напрямую становятся индикаторами для защиты. Хеш файла — это готовый IOC для блок-листа EDR. Строки выдают домены C2 и пути, по которым можно искать заражение в логах. Импорты намекают на возможности образца ещё до запуска. Энтропия отличает упакованный (вероятно вредоносный) файл от обычного. Всё это — материал для сигнатур, которые мы напишем в уроке про YARA.

Хеши и репутация

Криптографический хеш (MD5/SHA-1/SHA-256) — это «отпечаток» файла: одинаковые байты дают одинаковый хеш, изменение одного байта меняет его целиком. С хеша начинается любая сортировка: им идентифицируют образец и сверяют с базами известных угроз.

# Снять отпечаток образца (в изолированной ВМ)
sha256sum sample.bin
md5sum    sample.bin

VirusTotal-подход. Полученный SHA-256 проверяют по репутации: сервисы агрегации (VirusTotal и аналоги) показывают, как образец детектится десятками антивирусов, какие у него связи и поведение в чужих песочницах. Важная оговорка по OPSEC: загрузка самого файла в публичный сервис делает его доступным другим — для приватных инцидентов проверяют по хешу, а файл не выгружают. Если хеш уже известен как вредоносный — образец классифицирован, и можно сразу брать готовые индикаторы.

Строки

Утилита strings вытаскивает из бинарника последовательности печатаемых символов. Среди них часто всплывают домены и URL, пути к файлам, ключи реестра, имена функций, сообщения, иногда — куски конфигурации. Это дешёвый и богатый источник зацепок.

# Достать читаемые строки (и юникод -el) из образца
strings -n 6 sample.bin
strings -el  sample.bin   # строки в UTF-16LE, типичные для Windows

Защитник читает строки глазами «что из этого станет IOC»: домен evil-c2.example → правило для DNS-логов; путь \AppData\Roaming\svhost.exe → признак закрепления. Но строки обманчивы: вредонос их шифрует или собирает по символам, чтобы спрятаться. Пустой или бессмысленный вывод strings сам по себе подозрителен — обычно это признак упаковки, к которой мы перейдём.

Импорты

Исполняемый файл объявляет, какие функции ОС он использует, — это таблица импортов (в Windows-PE — Import Address Table). Импорты — это «список возможностей» программы. Настораживающие сочетания: VirtualAlloc + WriteProcessMemory + CreateRemoteThread (инъекция кода в чужой процесс), InternetOpen/WinHttpConnect (сетевая активность), CryptEncrypt (шифрование — подозрение на ransomware), функции работы с реестром автозапуска. Разбор заголовков и импортов (например, утилитами семейства pefile/readpe) показывает потенциал образца до запуска.

Энтропия как признак упаковки

Упаковщик (packer) сжимает и/или шифрует исполняемый код, а при запуске распаковывает его в память. Цель — спрятать строки и импорты от статики. Побочный эффект: упакованные/зашифрованные данные выглядят как случайный шум, а у случайного потока байтов высокая энтропия.

Энтропия Шеннона измеряет «непредсказуемость» байтов в битах на байт: от 0 (один символ повторяется) до 8 (все 256 значений равновероятны). Обычный текст и неупакованный код — около 4–6; упакованная или зашифрованная секция — близко к 8. Высокая энтропия не доказывает вредоносность (легальные программы тоже упаковывают), но это сильный признак, который заставляет присмотреться. Посчитаем энтропию для разных данных на чистом Python:

import math
from collections import Counter

def shannon_entropy(data: bytes) -> float:
    if not data:
        return 0.0
    counts = Counter(data)
    n = len(data)
    entropy = 0.0
    for count in counts.values():
        p = count / n
        entropy -= p * math.log2(p)
    return entropy

text   = b"AAAAAAAAAAAAAAAA"            # одна буква подряд
mixed  = b"Hello, this is plain text."  # обычный текст
packed = bytes(range(256))             # все значения байта поровну

print(f"Повтор:   {shannon_entropy(text):.2f} бит/байт")
print(f"Текст:    {shannon_entropy(mixed):.2f} бит/байт")
print(f"Упаковано:{shannon_entropy(packed):.2f} бит/байт")

Вывод:

Повтор:   0.00 бит/байт
Текст:    3.69 бит/байт
Упаковано:8.00 бит/байт

Видно шкалу: повтор одного байта — 0, обычный текст — около 3.7, равномерный «шум» — ровно 8. На практике энтропию считают посекционно: если у кода-секции PE энтропия близка к 8 и при этом таблица импортов почти пуста, а строк нет — почти наверняка перед нами упаковщик, и для полного разбора потребуется динамика (распаковка в памяти).

Как это работает под капотом

Все четыре приёма читают структуру файла, не запуская его. Хеш — это свёртка всех байтов фиксированной длины. strings сканирует байты и собирает цепочки печатаемых символов нужной кодировки. Импорты лежат в заголовке исполняемого формата (PE/ELF/Mach-O), который ОС читает при загрузке, — тот же заголовок читает и аналитик. Энтропия — статистика распределения значений байтов: чем равномернее распределение, тем выше непредсказуемость. Поскольку файл не исполняется, статика безопасна даже для активного вредоноса — он просто лежит на диске как набор байтов.

Как защититься

1. Превращайте находки в IOC. Хеши — в блок-листы, домены и пути из строк — в правила для SIEM/EDR, подозрительные импорты — в гипотезы о поведении для проверки в динамике.

2. Не выгружайте чувствительные образцы в публичные сервисы. Проверяйте по хешу; полную загрузку файла оставляйте для заведомо публичных семплов. Иначе вы раскрываете факт и детали инцидента.

3. Высокая энтропия + пустые импорты/строки = красный флаг. Помечайте такие файлы для углублённого анализа, но помните: упаковка сама по себе не приговор.

4. Автоматизируйте триаж. Скрипт, который считает хеши, тянет строки, разбирает импорты и энтропию по секциям, экономит время и единообразит сбор индикаторов на потоке образцов.

Итоги

  • Статика анализирует файл без запуска — это безопасный и быстрый первый шаг сортировки.
  • Хеш идентифицирует образец и проверяется по репутации; приватные инциденты сверяют по хешу, а не выгрузкой файла.
  • Строки дают домены, пути и ключи реестра — готовые зацепки для IOC; импорты раскрывают возможности образца.
  • Энтропия около 8 при пустых строках/импортах — сильный признак упаковки, повод для динамического анализа.
  • Все находки — это материал для сигнатур и правил обнаружения; работаем в изолированной ВМ и только с разрешёнными образцами.
Проверьте себя
1. О чём чаще всего говорит энтропия секции, близкая к 8 бит/байт, при почти пустой таблице импортов и отсутствии строк?
AО том, что образец, вероятно, упакован или зашифрован — данные выглядят как случайный шум
BО том, что файл точно безопасен, раз в нём нет читаемых строк
CО том, что файл повреждён и его нельзя анализировать
DО том, что энтропия не связана с упаковкой и это случайное совпадение
2. Почему при анализе приватного инцидента образец проверяют по хешу, а не загружают файл в публичный сервис?
AЗагрузка файла делает его и детали инцидента доступными третьим лицам, а проверка по хешу этого не раскрывает
BХеш вычисляется быстрее, чем загружается файл, и это единственная причина
CПубличные сервисы не умеют принимать файлы, только хеши
DПо хешу антивирусы детектят образец точнее, чем по самому файлу