Трассировка вызовов и поведения

Чтобы понять, что делает программа, не обязательно читать каждую её инструкцию — достаточно посмотреть, о чём она просит операционную систему.

Трассировка (tracing) — наблюдение за программой по её внешним вызовам: какие системные вызовы к ядру и какие функции библиотек она дёргает, с какими аргументами и что получает в ответ. Это поведенческий портрет бинарника, снятый «снаружи».

Программа почти ничего не может сделать в одиночку: открыть файл, прочитать сеть, запустить процесс, получить время — для всего этого она обращается к ядру ОС через системные вызовы и пользуется функциями стандартных библиотек. Эти обращения — узкое горлышко, через которое видно намерения программы. Поймав их поток, аналитик понимает поведение целиком, даже не разбирая логику по ассемблеру. Для разбора подозрительного образца это часто первый шаг: быстро увидеть «что трогает на диске, куда ходит по сети, что запускает».

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

Поведенческий анализ — основа разбора вредоносного ПО и threat hunting. Сигнатуры можно обойти, но поведение выдаёт суть: программа, которая массово шифрует файлы пользователя, ведёт себя как вымогатель независимо от того, как написан её код. Понимая, какие системные вызовы соответствуют опасным действиям (запись в автозагрузку, обращение к чужой памяти, исходящие соединения), защитник строит детектирование и правила EDR. Трассировка в лаборатории — способ заранее узнать «индикаторы компрометации» образца.

Два уровня наблюдения: strace и ltrace

На Linux есть два классических инструмента. strace показывает системные вызовы — общение программы с ядром (открытие файлов, чтение/запись, сеть, процессы). ltrace показывает вызовы библиотечных функций — уровень выше, ближе к логике программы (например, обращения к функциям работы со строками или шифрованием). Вместе они дают картину и «что просит у системы», и «какими готовыми кирпичами пользуется».

# Концептуально: запустить программу под наблюдением вызовов
strace ./demo            # системные вызовы к ядру
ltrace ./demo            # вызовы функций библиотек
strace -f -e trace=network ./demo   # только сетевые вызовы, с дочерними процессами

Под Windows прямого аналога нет, но идея та же: поведение наблюдают мониторами активности (файловой, реестровой, сетевой) и средствами sandbox-анализа, которые перехватывают вызовы Windows API. Полезно и фильтровать вывод: реальная программа делает тысячи вызовов, и без фокуса на нужном классе (файлы, сеть, запуск процессов) лента превращается в нечитаемый поток — поэтому опытный аналитик сразу сужает наблюдение до интересующей категории.

Как читать вывод трассировки

Вывод — это лента вызовов с аргументами и результатами. Каждая строка отвечает на вопрос «что программа попросила и что получила». Условный пример того, как это выглядит:

openat(AT_FDCWD, "/etc/passwd", O_RDONLY) = 3
read(3, "root:x:0:0:...", 4096)          = 1234
connect(4, {sa_family=AF_INET, ...})     = -1 ECONNREFUSED
execve("/bin/sh", ["sh", "-c", "..."], ) = 0

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

Своя мини-трассировка как пример мышления

Чтобы прочувствовать принцип, не нужен strace — идею «перехвати вызов, залогируй аргументы, передай дальше» легко показать в Python через декоратор. Точно так же концептуально работают перехватчики вызовов:

def trace(func):
    def wrapper(*args):
        print(f"-> {func.__name__}{args}")
        result = func(*args)
        print(f"<- {func.__name__} = {result}")
        return result
    return wrapper

@trace
def add(a, b):
    return a + b

add(2, 3)

Вывод:

-> add(2, 3)
<- add = 5

Реальные трассировщики делают то же на уровне ОС: становятся «прослойкой» между программой и системой, записывая каждый вызов с аргументами и результатом. Принцип идентичен — отличается лишь то, что перехватывается не функция Python, а граница процесс/ядро.

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

strace опирается на уже знакомый механизм ptrace: ядро уведомляет трассировщик на каждом системном вызове отлаживаемого процесса — до и после, — и тот читает номер вызова и аргументы из регистров. ltrace перехватывает вызовы динамических библиотек, подменяя записи в таблице переходов (PLT/GOT) так, чтобы управление сначала шло в логирующую обёртку. В обоих случаях программа выполняется как обычно, но каждый её «выход наружу» становится видимым. Цена — заметное замедление и, опять же, наблюдаемые следы: программа может догадаться, что её трассируют.

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

Для аналитика правила те же, что и с отладчиком: трассировать незнакомый бинарник только в изолированной ВМ без сети (или с контролируемой, перехватываемой сетью) и с откатом из снапшота — иначе образец может реально навредить или «позвонить домой». Для защитника инфраструктуры поведенческая телеметрия (аудит системных вызовов через auditd, Sysmon, EDR) — это рабочий слой обороны: подозрительные последовательности вызовов (массовое чтение и перезапись файлов, запись в автозагрузку, неожиданные исходящие соединения) превращаются в правила оповещения. Для разработчика вывод трезвый: раз поведение наблюдаемо, нельзя прятать секреты в «незаметных» вызовах — что программа делает с системой, всегда можно увидеть.

Юридическое напоминание: запускать и трассировать чужой исполняемый файл, особенно подозрительный, допустимо только в собственной изолированной лаборатории и в рамках законного исследования. Распространение и запуск вредоносного ПО вне таких рамок наказуемы (УК РФ ст. 273).

Итоги

  • Трассировка раскрывает поведение программы по её внешним вызовам, не требуя разбора всего кода.
  • strace показывает системные вызовы (общение с ядром), ltrace — вызовы библиотечных функций (ближе к логике).
  • Лента вызовов с аргументами и результатами читается как сюжет: какие файлы, какая сеть, какие запуски процессов.
  • Под капотом — ptrace для системных вызовов и подмена PLT/GOT для библиотечных; программа работает как обычно, но «видна».
  • Поведенческая телеметрия (auditd/Sysmon/EDR) — основа детектирования; анализ незнакомого образца — только в изолированной ВМ.
Проверьте себя
1. Чем по уровню наблюдения различаются strace и ltrace?
Astrace показывает системные вызовы (общение с ядром ОС), а ltrace — вызовы функций динамических библиотек
Bstrace работает на Windows, а ltrace — на Linux
Cstrace меняет код программы, а ltrace только читает память
DЭто одно и то же, просто разные названия
2. Почему поведенческий анализ (трассировка) ценен защитнику даже без чтения исходного кода?
AОн автоматически удаляет вредоносный код
BОн расшифровывает все строки в программе
CПоведение выдаёт суть программы (что она делает с файлами, сетью, процессами) независимо от того, как написан её код
DОн подменяет системные вызовы на безопасные