Число зарегистрированных уязвимостей переполнения буфера в NVD (CWE-119/120/121) исчисляется десятками тысяч - и это только один класс бинарных багов из десятка. Conficker, Stuxnet, EternalBlue - каждый из этих инцидентов начинался с ошибки в нативном коде, которую атакующий нашёл раньше защитников. Бинарный анализ уязвимостей - навык, отделяющий специалиста, который запускает готовый эксплойт из Metasploit, от того, кто способен вскрыть проприетарный бинарь без исходников, обнаружить 0-day и превратить его в рабочую цепочку атаки. Ниже - полная карта направления: от статического реверса до автоматизированного фаззинга, от классических переполнений стека до tcache poisoning. Каждый раздел - точка входа в отдельный детальный гайд.
| # | Подтема | Подробный разбор |
|---|---|---|
| 1 | Методология реверс-инжиниринга через MITRE ATT&CK | Reverse engineering бинарного кода |
| 2 | Stack overflow, heap exploitation, ROP/JOP | Эксплуатация бинарных уязвимостей |
| 3 | Символьное исполнение: angr, Manticore, Triton | Символьное исполнение на практике |
| 4 | Кейс: реверс закрытых бинарников до полной компрометации | От реверса бинарников до RCE |
| 5 | AFL++, libFuzzer, coverage-guided fuzzing | Фаззинг бинарных приложений |
| 6 | Фаззинг веб-приложений и API | Фаззинг для обнаружения 0-day |
| 7 | GDB, x64dbg, WinDbg: отладка бинарей | Динамический анализ: отладчики |
| 8 | Frida, PIN, DynamoRIO: динамическая инструментация | Динамический анализ: DBI-фреймворки |
Зачем пентестеру навыки бинарного анализа
На реальном пентесте или bug bounty рано или поздно встречается сервис, для которого нет публичного эксплойта. Проприетарный демон на Linux-сервере, десктопное ПО с кастомным протоколом, прошивка IoT-устройства без единой строки документации. Всё, что есть - скомпилированный бинарь. Без навыков анализа бинарных файлов пентестер упирается в стену: он может сканировать порты, фаззить HTTP-эндпоинты, но закрытый нативный код останется чёрным ящиком.В CTF-соревнованиях категория pwn стабильно собирает наименьший процент решений. Задачи уровня DEF CON CTF или pwn.college требуют не теории - нужен рабочий процесс: открыть бинарь в дизассемблере, найти уязвимый путь, написать эксплойт, обойти защиты. Каждый шаг - конкретный инструмент и понимание того, что происходит на уровне регистров и стековых фреймов.
Реверс-инжиниринг для пентеста - не отдельная специализация, а необходимый компонент kill chain. Атакующие группировки создают и приобретают эксплойты для нативного кода - в терминах MITRE ATT&CK это техники T1587.004 Develop Capabilities: Exploits и T1588.005 Obtain Capabilities: Exploits. Сбор информации об уязвимостях целевого ПО (T1588.006 Obtain Capabilities: Vulnerabilities) предшествует написанию эксплойта, а успешная эксплуатация бинарной уязвимости часто ведёт к повышению привилегий (T1068 Exploitation for Privilege Escalation). Пентестер, понимающий эту цепочку с обеих сторон, превращается из пользователя чужих инструментов в исследователя, который генерирует собственные атакующие примитивы.
Как эта цепочка выглядит на реальном кейсе - детально разобрано в гайде «От реверса закрытых бинарников до полной компрометации сервера», где анализ проприетарного кода привёл к обнаружению RCE.
Статический анализ бинарников: дизассемблирование и декомпиляция
Статический анализ - первое, что делает исследователь, получив бинарь. Файл не запускается, среда исполнения не нужна. Цель - восстановить логику работы программы по машинному коду и структуре исполняемого файла.Процесс начинается с определения формата: ELF для Linux, PE для Windows. Анализ заголовков даёт базовую информацию - архитектуру (x86, x86_64, ARM), секции (.text, .data, .bss, .rodata), таблицу импортов и экспортов, точку входа. Уже на этом этапе видно многое: какие библиотечные функции вызывает программа (наличие
gets, strcpy, sprintf без проверки длины - красный флаг), есть ли символы отладки, статически или динамически слинкован бинарь.Дизассемблирование переводит машинный код в ассемблерные мнемоники. Для опытного аналитика ассемблер - рабочий язык: по паттернам
push rbp; mov rbp, rsp идентифицируются прологи функций, по call и jmp - граф потока управления. Декомпиляция идёт дальше - транслирует ассемблер в псевдокод, приближённый к C. Компиляция необратима: имена переменных теряются, циклы разворачиваются, оптимизатор перестраивает логику. Декомпилированный код - приближение, не точная копия оригинала. Задача аналитика - понять семантику, а не восстановить исходник посимвольно.Три уровня глубины статического анализа бинарников:
- Triage - беглый осмотр:
file,strings,readelf -h/objdump -f. Занимает минуты. Цель - понять, что перед вами, и стоит ли вкладывать время. - Целевой анализ - работа в Ghidra или IDA Pro. Исследователь идёт от точки входа или от конкретной импортируемой функции (
recv,read,sscanf) к уязвимому пути. Граф вызовов, перекрёстные ссылки, типизация переменных через декомпилятор. - Полный реверс - восстановление структур данных, протоколов, алгоритмов шифрования. Необходим для анализа прошивок, малвари, закрытых серверных компонентов.
gets в импортах - перед вами учебный случай, для начала хватит за глаза. Видите stripped бинарь с Go или Rust-рантаймом - закладывайте на порядок больше времени.Подробный разбор методологии: Reverse engineering бинарного кода: системная методология анализа через MITRE ATT&CK
Динамический анализ исполняемых файлов: от брейкпоинта до DBI-фреймворков
Статический анализ показывает, как код написан. Динамический - как он работает. Разница принципиальна: самомодифицирующийся код, упакованные бинари (T1027.002 Software Packing), обфусцированные строки (T1140 Deobfuscate/Decode Files or Information) - всё это раскрывается только при запуске. Динамический анализ исполняемых файлов делится на два фундаментально разных подхода.Классическая отладка - пошаговое исполнение под контролем дебаггера. GDB с расширениями pwndbg или peda для Linux, x64dbg для Windows userland, WinDbg для ядра и драйверов. Отладчик позволяет ставить брейкпоинты на адреса и функции, инспектировать регистры и память в реальном времени, отслеживать изменения стека при вызове каждой функции. На CTF-задачах GDB с pwndbg - основной инструмент: вы видите состояние стека в момент переполнения буфера, проверяете адреса гаджетов, наблюдаете как payload перезаписывает return address.
Ограничение отладки - инвазивность. Многие защитные механизмы и малварь используют антиотладочные техники (T1622 Debugger Evasion): проверку флага
TracerPid в /proc/self/status, вызов ptrace(PTRACE_TRACEME), замер тайминга выполнения. Эти техники детектируют присутствие дебаггера и меняют поведение программы. На практике - половина малвари при обнаружении отладчика просто тихо завершается или начинает вести себя «прилично», что сбивает с толку.Динамическая бинарная инструментация (DBI) - другой подход: вместо пошаговой отладки фреймворк вставляет собственный код в поток исполнения анализируемой программы. Frida позволяет подключаться к работающим процессам и перехватывать вызовы функций через JavaScript-скрипты, PIN и DynamoRIO дают доступ к каждой исполняемой инструкции. DBI работает быстрее классической отладки - динамическая бинарная инструментация превосходит подходы на основе автоматизированной отладки на несколько порядков по производительности.
Когда что использовать:
- GDB + pwndbg - разработка эксплойтов, CTF pwn, анализ конкретного краша (Linux, x86/x86_64)
- x64dbg / WinDbg - анализ PE-бинарей и драйверов Windows. WinDbg - зверь, который может отлаживать и юзерленд, и ядро, до чего x64dbg пока не доросла
- Frida - инструментация mobile-приложений, hooking API-вызовов, распаковка (кроссплатформенно, требует root/jailbreak на мобильных)
- PIN / DynamoRIO - трассировка инструкций, покрытие кода, кастомный анализ (Linux/Windows, высокий порог входа)
Подробный разбор DBI: Frida, PIN и DynamoRIO - от трассировки до распаковки
6 классов бинарных уязвимостей, которые эксплуатируются на практике
Поиск уязвимостей в нативном коде сводится к обнаружению ошибок, позволяющих нарушить целостность памяти или контрольного потока. Ниже - классы, которые составляют основу как реальных CVE, так и CTF-задач категории pwn.Переполнение буфера (стек). Классика бинарного эксплойта, живёт и здравствует уже 30+ лет. Программа записывает данные за границы выделенного на стеке буфера, перезаписывая сохранённый адрес возврата (return address). Атакующий подставляет контролируемый адрес - и поток управления перехвачен. По данным NVD, уязвимостей переполнения буфера (CWE-119/120/121) зарегистрированы десятки тысяч. Conficker (CVE-2008-4250, MS08-067) эксплуатировал stack-based buffer overflow в функции NetpwPathCanonicalize службы Server Service (в NVD классифицирован как CWE-94), поразив, по различным оценкам, от 9 до 15 млн устройств.
Переполнение кучи (heap overflow, UAF, double free). Современные бинарные эксплойты всё чаще нацелены на аллокатор кучи. Use-After-Free возникает, когда программа обращается к памяти после её освобождения через
free() - dangling pointer указывает на область, которую аллокатор мог отдать под новые данные. Double free позволяет дважды освободить один chunk, нарушая внутренние структуры аллокатора (tcache, fastbins в glibc). Через эти примитивы атакующий получает arbitrary write - самый ценный примитив для построения эксплойта.Атака форматной строки (format string). Если пользовательский ввод попадает в первый аргумент
printf (или sprintf, fprintf) без спецификатора формата, атакующий передаёт %x, %s, %n и получает чтение/запись стековой памяти. На CTF встречается реже, чем переполнения, но в легаси-коде - сплошь и рядом.Целочисленное переполнение/недополнение (integer overflow/underflow). Арифметическая операция выходит за границы типа:
-1 в unsigned int становится 4 294 967 295. Это не крашит программу напрямую, но может привести к выделению буфера недостаточного размера или обходу проверки длины - и далее к классическому переполнению. Коварная штука: код выглядит корректно, компилятор не ругается, а malloc(0xFFFFFFFF) уже летит.Race condition. Уязвимость состояния гонки возникает, когда программа проверяет условие (check) и затем выполняет действие (use) с временным зазором между ними (TOCTOU). Атакующий подменяет ресурс (файл, дескриптор) между проверкой и использованием. На практике встречается в многопоточных сервисах и при работе с файловой системой.
Return-Oriented Programming (ROP). Не уязвимость, а техника эксплуатации: когда прямое внедрение шелл-кода заблокировано (NX-бит), атакующий выстраивает цепочку из коротких фрагментов существующего кода (гаджетов), каждый из которых заканчивается инструкцией
ret. Цепочка гаджетов выполняет произвольные действия, не записывая ни одного байта исполняемого кода. По сути - программирование из кусков чужого кода, как мозаика.Подробный разбор с PoC и обходом современных защит: Эксплуатация бинарных уязвимостей: stack overflow, heap exploitation, ROP/JOP
Фаззинг бинарных приложений: автоматизация поиска крашей
Ручной реверс и поиск уязвимостей в нативном коде - процесс медленный. Фаззинг радикально меняет уравнение: вместо чтения каждой функции мы генерируем тысячи мутированных входных данных и смотрим, какие из них вызывают краш.Coverage-guided fuzzing - доминирующий подход. Фаззер инструментирует бинарь (на этапе компиляции или через DBI), отслеживает, какие ветви кода покрыты каждым тест-кейсом, и отдаёт приоритет мутациям, открывающим новые пути. AFL++ - индустриальный стандарт для C/C++ приложений: поддерживает компиляторную инструментацию (afl-gcc, afl-clang-fast), режим QEMU для бинарей без исходников, persistent mode для ускорения. libFuzzer интегрируется в проект как библиотека и хорош для фаззинга отдельных функций - написал harness, собрал с
-fsanitize=fuzzer, запустил.Ключевые решения при запуске фаззинга:
- С исходниками или без? С исходниками - компиляторная инструментация (быстрее в 2-5 раз). Без - QEMU mode AFL++ или DynamoRIO-бэкенд (медленнее, но работает для закрытых бинарей).
- Harness или фаззинг целого приложения? Harness (обёртка, вызывающая целевую функцию) даёт скорость и фокус. Фаззинг целого приложения - больше покрытие, но медленнее на порядки.
- Sanitizers. AddressSanitizer (ASAN) и UndefinedBehaviorSanitizer (UBSAN) превращают «тихие» ошибки памяти в воспроизводимые краши. Без санитайзеров многие уязвимости останутся незамеченными - баг есть, а краша нет, и фаззер его пропускает.
Подробный разбор: AFL++, libFuzzer и coverage-guided fuzzing на практике
Применение этих же инструментов к веб-приложениям и API описано в гайде Фаззинг веб-приложений и API: от AFL++ и LibFuzzer до обнаружения 0-day.
Символьное исполнение: автоматизация поиска уязвимостей без перебора
Фаззинг хорош, но слеп: мутации случайны, а «магическое число» в глубоком ветвлении (if (input == 0xDEADBEEF)) фаззер может искать часами. Символьное исполнение решает задачу иначе: вместо конкретных значений переменных использует символические, а вместо выполнения кода строит систему математических ограничений (constraints) для каждого пути. SMT-солвер (Z3, Boolector) определяет, существуют ли входные данные, удовлетворяющие условиям конкретной ветки - включая ту, которая приводит к переполнению буфера или обходу аутентификации.angr - самый популярный фреймворк символьного исполнения для бинарного анализа. Работает с бинарями напрямую (без исходников), поддерживает x86, x86_64, ARM, MIPS, содержит встроенную эмуляцию системных вызовов. На CTF-задачах angr часто решает за секунды то, что требовало бы десятков минут ручного анализа: найти вход, при котором программа выводит флаг, обойти проверку лицензионного ключа, восстановить пароль. Я видел, как на CTF человек скриптом на angr в 15 строк решал задачу, над которой соседняя команда ковырялась полтора часа в GDB.
Ограничение символьного исполнения - экспоненциальный рост числа состояний (state explosion). Каждое ветвление удваивает количество путей для анализа. На реальных бинарях с сотнями функций и циклами полный символьный анализ невозможен. На практике символьное исполнение применяется точечно: для конкретного участка кода, конкретного входа, конкретного ограничения.
Комбинация фаззинга и символьного исполнения (concolic testing) - направление, которое уже даёт результаты: фаззер находит новые пути, символьный движок «прорубает» сложные ветвления, результаты обмениваются.
Подробный разбор: Символьное исполнение для поиска уязвимостей: angr, Manticore и Triton на практике
Инструменты бинарного анализа: trade-off таблица для выбора стека
Выбор инструментов - одно из первых решений, которое определяет продуктивность. Ниже - сравнение ключевых инструментов по критериям, важным на практике.| Инструмент | Преимущества | Ограничения | Когда использовать | Когда не использовать |
|---|---|---|---|---|
| Ghidra (NSA, бесплатный) | Декомпилятор на уровне, скриптование на Java/Python, активная разработка | Медленнее IDA на крупных бинарях, UI тяжеловеснее | CTF, исследование без бюджета, командная работа | Когда критична скорость интерактивного анализа |
| IDA Pro + Hex-Rays | Индустриальный стандарт, огромная база плагинов, лучший FLIRT | Стоимость лицензии, проприетарный формат баз | Профессиональный пентест, malware analysis, крупные проекты | Учебные задачи, ограниченный бюджет |
| Binary Ninja | Лучший API для автоматизации, промежуточные IL (LLIL, MLIL, HLIL) | Декомпилятор уступает Hex-Rays, меньше плагинов | Массовый автоматизированный анализ, написание плагинов | Quick triage, если нет времени на настройку |
| GDB + pwndbg | Бесплатный, гибкий, нативная интеграция с Linux | Только CLI, крутая кривая обучения | Разработка эксплойтов для Linux, CTF pwn | Windows-бинари, GUI-ориентированный анализ |
| Frida | Кроссплатформенная инструментация, JavaScript API | Требует root/jailbreak на мобильных, overhead | Mobile hooking, runtime-перехват, распаковка | Статический анализ без запуска |
| AFL++ | Coverage-guided, QEMU mode, persistent mode | Нужен harness, не все интерфейсы фаззятся | Парсеры, библиотеки, файловые форматы | Сложные stateful-приложения без адаптера |
| angr | Символьное исполнение без исходников, поддержка многих архитектур | State explosion на реальных бинарях | CTF автосолверы, точечный анализ ветвлений | Полный анализ больших приложений |
| ropper | Поиск ROP/JOP гаджетов, программный API, фильтрация bad bytes | Только поиск гаджетов, не строит полные цепочки автоматически | Построение ROP-цепочек при разработке эксплойтов | Этапы, не связанные с контролем потока |
Для начала достаточно связки Ghidra + GDB с pwndbg + pwntools. Этот стек бесплатен, покрывает статику и динамику, позволяет решать CTF-задачи и проводить аудит реальных бинарей. Коммерческие инструменты имеет смысл осваивать, когда бесплатные начинают тормозить рабочий процесс на конкретных задачах - а не потому что «все так делают».
Бинарный анализ в цепочке атаки: от разведки до эскалации привилегий
Бинарный анализ уязвимостей - не изолированная дисциплина, а компонент наступательной цепочки. Вот как конкретные техники MITRE ATT&CK связаны с этапами работы исследователя.Resource Development (подготовка ресурсов). Прежде чем атаковать, нужно найти уязвимость или получить эксплойт. Сбор информации об уязвимостях целевого ПО (T1588.006 Vulnerabilities) - этап, на котором аналитик скачивает бинарь, определяет версию, ищет известные CVE. Если публичного эксплойта нет - начинается разработка собственного (T1587.004 Exploits): реверс, поиск уязвимости, написание PoC. Если эксплойт доступен в публичных источниках - его адаптация под конкретную среду (T1588.005 Exploits).
Initial Access / Execution. Рабочий эксплойт бинарной уязвимости даёт первичный доступ или выполнение кода на целевой системе. Переполнение буфера в сетевом сервисе - классический вектор initial access. Process injection (T1055) - внедрение кода в чужой процесс - часто следует сразу за первичной эксплуатацией.
Privilege Escalation. Локальная бинарная уязвимость в SUID-бинаре, драйвере ядра или системном сервисе - путь от пользователя к root/SYSTEM (T1068 Exploitation for Privilege Escalation). Именно для этого этапа чаще всего ищут бинарные баги при пентесте: foothold уже есть, нужны привилегии.
Defense Evasion. Анализ упакованных и обфусцированных бинарей (T1027.002 Software Packing, T1140 Deobfuscate) - задача, требующая навыков динамического анализа. Малварь и эксплойты скрывают свою логику; аналитик восстанавливает её через распаковку и деобфускацию.
Понимание позиции каждого этапа в kill chain определяет, какой метод анализа применять и с какой глубиной.
NX, ASLR, Canary, RELRO: защитные механизмы и их обход
Современные компиляторы и ОС выстраивают несколько уровней защиты бинарей от эксплуатации. Перед написанием эксплойта нужно знать, какие из них включены - для этого естьchecksec. С помощью библиотеки ropper это делается программно:
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Каждая защита закрывает конкретный вектор, но ни одна не универсальна. На реальном пентесте комбинация
checksec + анализ версии glibc + проверка ядра даёт карту доступных обходов.Какой метод анализа выбрать: decision tree под задачу
Выбор подхода зависит от трёх факторов: что вы анализируете, какой результат нужен и сколько времени есть.CTF pwn (категория binary exploitation):
checksec- определить включённые защиты- Ghidra/IDA - статический анализ, найти уязвимую функцию
- GDB + pwndbg - подтвердить уязвимость, вычислить offset
- pwntools - написать эксплойт
- Если ветвление сложное - angr для поиска нужного пути
- Triage:
file,strings,checksec- быстрая оценка поверхности атаки - Фаззинг AFL++ (если есть исходники) или QEMU-mode (без исходников) - автоматический поиск крашей
- Triage крашей: GDB для анализа каждого уникального краша
- Статический анализ в Ghidra - восстановить root cause
- Написание PoC-эксплойта
- Извлечение файловой системы (binwalk)
- Идентификация архитектуры (ARM, MIPS) и ОС
- Статический анализ ключевых бинарей в Ghidra (сетевые демоны, CGI-обработчики)
- Frida или эмуляция через QEMU user-mode для динамического анализа
- Фаззинг входных интерфейсов (HTTP, UART, custom protocol)
- Динамический анализ: запуск в sandbox, снятие дампа после распаковки
- Frida/PIN для автоматической распаковки (T1027.002)
- Статический анализ дампа в IDA/Ghidra
- Восстановление C2-протокола, извлечение IOC
Куда движется бинарный анализ: тренды 2025-2026
Интеграция LLM в дизассемблеры - уже реальность: плагины для Ghidra и IDA используют языковые модели для автоматического переименования функций и переменных в stripped-бинарях, генерации аннотаций к декомпилированному коду. Это не замена аналитику, но ускорение triage в разы. На практике - экономит час-два на крупном бинаре, хотя качество именования пока нестабильное.Фаззинг смещается в сторону structure-aware подходов: AFL++ с grammar-based мутациями, LibAFL как модульный фреймворк для построения кастомных фаззеров. Порог входа снижается - количество обнаруженных 0-day через автоматизированный фаззинг растёт.
Аппаратные митигации (ARM MTE, Intel CET) меняют правила эксплуатации. Memory Tagging Extension детектирует heap corruption на аппаратном уровне, Control-flow Enforcement Technology реализует Shadow Stack без программного overhead. Эти технологии уже в серийных процессорах - через 2-3 года они станут стандартом, и техники эксплуатации будут вынуждены адаптироваться. Но пока MTE включён далеко не везде, а CET обходится через data-only атаки - так что запас времени у атакующих ещё есть.
Для пентестера вывод прямой: инвестиции в навыки бинарного анализа уязвимостей окупаются сейчас, пока автоматизация не закрыла все low-hanging fruit, а новые аппаратные защиты ещё не стали повсеместными.
Прокачайте навыки бинарной эксплуатации на практике
Теория бинарного анализа обретает смысл только при регулярном решении задач. Платформы для отработки: pwn.college (академические лабораторные от ASU), HackTheBox (категория pwn), picoCTF для начинающих. Если хотите выстроить системный путь от основ до продвинутого heap exploitation - на курсах Codeby Academy по наступательной безопасности бинарная эксплуатация разбирается на реалистичных лабораторных стендах с разбором каждого этапа kill chain.Большинство команд, которые занимаются пентестом, вкладывают 90% усилий в веб-уязвимости и AD-атаки. Это логично с точки зрения ROI - OWASP Top 10 закрывает основной объём типичных проектов. Но когда на периметре появляется кастомный бинарный сервис или нужно поднять привилегии через уязвимый SUID-бинарь, команда оказывается без инструментов. Формируется слепая зона: уязвимость существует, но найти её некому, потому что в команде нет человека, способного открыть Ghidra и дойти от дизассемблера до рабочего PoC. На моей практике один человек с навыками бинарного анализа в красной команде из шести специалистов меняет результат проекта радикальнее, чем ещё два веб-пентестера. Причина проста: бинарные уязвимости реже ищут - и реже патчат. Они живут в продакшене годами. Тренд на Rust и memory-safe языки постепенно сужает поверхность атаки в новом коде, но legacy на C/C++ никуда не денется в ближайшие десять лет - а с ним останутся переполнения буферов, UAF и все остальные классы ошибок, которым нет дела до модных языков. Кто инвестирует в эти навыки сейчас, тот будет на рынке ещё долго - специалистов по бинарной эксплуатации не хватает, и дефицит только нарастает.