Силуэт оператора в зеленоватом свечении монитора с дизассемблером. Экран отображает листинг Ghidra с метками обхода антиотладки, зернистость и блики CRT создают атмосферу ночной работы.


Три уровня защиты в одном бинаре: TLS callback с IsDebuggerPresent, CPUID-запрос на наличие гипервизора, кастомный XOR с динамическим ключом поверх. Стандартная картина для категории reverse на средних и крупных CTF. Ручной разбор каждого слоя в Ghidra - от получаса. angr-скрипт на 15 строк выдаёт флаг за секунды. Разница между «решил два таска за восемь часов» и «закрыл шесть за то же время» определяется не талантом, а пониманием паттернов anti-analysis и умением автоматизировать рутину.

Здесь - конкретные техники, которые авторы CTF-заданий тащат из реального malware, и инструменты для обхода каждой из них.

Место reverse/malware-заданий в цепочке CTF-атаки​

Перед тем как препарировать конкретные приёмы, зафиксируем операционный контекст: где reversing сидит в «kill chain» CTF-соревнования и как навыки переносятся в реальный malware analysis.

Типичная цепочка решения reverse-таска на Jeopardy CTF:
  1. Триаж - file ./binary, strings, checksec. Определяем архитектуру (x86/x64/ARM), тип линковки, наличие символов. 30 секунд работы, но экономит минуты дальше.
  2. Статический анализ - загрузка в Ghidra или IDA, поиск main, анализ Control Flow Graph, идентификация anti-analysis барьеров и шифрования.
  3. Динамический анализ - x64dbg для Windows, GDB + pwndbg для Linux. Breakpoints на ключевые проверки, обход anti-debug.
  4. Автоматизация - angr для символьного выполнения, Frida для перехвата и патчинга. Включается, когда ручной анализ жрёт слишком много времени.
  5. Извлечение флага - расшифровка, декодирование, получение строки формата flag{...}.
В терминах MITRE ATT&CK reverse/malware задания CTF используют те же техники, что и боевой malware. Обфускация флага - Obfuscated Files or Information (T1027, Defense Evasion). Anti-debug проверки - Debugger Evasion (T1622, Defense Evasion / Discovery). Anti-VM - Virtualization/Sandbox Evasion (T1497, Defense Evasion / Discovery). Это не академическое упражнение: навыки переносятся напрямую в работу с ransomware, RAT и загрузчиками. Программа FLARE Team на REcon 2026 строит лабораторные работы по анализу реального malware на тех же принципах - обход anti-analysis, разбор криптографии Conti v2 и Babuk, автоматизация через скрипты.

Техники из статьи работают в CTF-заданиях от новичковых (picoCTF, HTB Easy) до финалов крупных соревнований. В реальном malware analysis - на загрузчиках (droppers), инфостилерах и ransomware. Разница в масштабе, не в подходе.

Anti-debug техники в CTF reverse engineering заданиях​

Debugger Evasion (T1622, Defense Evasion / Discovery) - первый барьер, который выстраивают авторы CTF-заданий. Примечание: в каталоге MITRE ATT&CK техника T1622 описана преимущественно для Windows; для Linux аналогичные приёмы (ptrace-проверки, /proc/self/status) формально относятся к другим техникам. Цель: заставить бинарь вести себя иначе под отладчиком - выдавать фальшивый результат, зацикливаться или молча завершаться.

Windows API: IsDebuggerPresent и NtQueryInformationProcess​

Самая частая проверка на easy-medium уровне - вызов IsDebuggerPresent() через Windows Native API (T1106, Execution; техника T1106 в каталоге MITRE описана для Windows, macOS и Linux, но этот пример - только Windows). Функция читает поле BeingDebugged из PEB (Process Environment Block). В дизассемблере выглядит как вызов kernel32!IsDebuggerPresent, за которым следует test eax, eax / jnz exit_or_fake_flag. Ghidra декомпилирует это в if (IsDebuggerPresent() != 0) { goto fail; }.

Вариант посерьёзнее - NtQueryInformationProcess с классами ProcessDebugPort (0x7) и ProcessDebugObjectHandle (0x1E). Эти проверки идут через syscall, и простым патчем PEB их не обойти.

Обход в x64dbg: breakpoint на IsDebuggerPresent, после срабатывания - EAX = 0. Универсальнее - плагин ScyllaHide (GitHub: x64dbg/ScyllaHide, проект активен), который автоматически патчит PEB и перехватывает NtQueryInformationProcess.

ScyllaHide покрывает большинство стандартных Windows anti-debug приёмов, но бессилен против кастомных timing checks на RDTSC в inline assembly - для них нужен Frida или ручной патч.

Timing checks и TLS callbacks​

Timing checks - измерение времени между двумя точками выполнения. Под отладчиком single-step занимает на порядки больше. Реализуется через инструкцию RDTSC (Read Time-Stamp Counter), вызовы QueryPerformanceCounter или GetTickCount. Дельта выше порога - бинарь решает, что его отлаживают.

TLS callbacks - функции, которые исполняются до main(). Авторы CTF суют туда anti-debug проверки: к моменту, когда реверсер ставит breakpoint на main, данные уже испорчены. В IDA/Ghidra TLS callbacks видны в секции .tls или через PE-заголовок (IMAGE_TLS_DIRECTORY).

Обход timing checks: в x64dbg - Hardware Breakpoint на адрес RDTSC и подмена значения TSC в регистрах. Через Frida - перехват QueryPerformanceCounter с возвратом фиксированного значения.

Обход TLS callbacks: x64dbg: Options → Events → галочка на TLS Callbacks. Breakpoint на callback, NOP-инг anti-debug кода. Для Linux ELF аналогичную роль играют .init_array и [B]attribute[/B]((constructor)) (эти приёмы в MITRE ATT&CK не покрываются T1622 - она описана только для Windows).

Decision tree обхода anti-debug​

Что видим в дизассемблереТехника (MITRE)Обход
Вызов IsDebuggerPresentPEB flag (T1622)EAX = 0 или ScyllaHide
NtQueryInformationProcess с классом 0x7/0x1EKernel-level debug check (T1622)ScyllaHide или Frida hook на ntdll
RDTSC / QueryPerformanceCounter между блокамиTiming check (T1622)Hardware BP + подмена или Frida hook
Код в .tls / .init_array до mainTLS/init callback (T1622)Break on TLS + NOP
int 2Dh / OutputDebugStringException-based (T1622)SEH analysis + NOP

Эти техники встречаются в CTF категорий reverse и malware на платформах HTB, CTFtime, picoCTF. В боевом malware analysis тот же набор используют инфостилеры и загрузчики первого этапа. Продвинутый malware (APT-уровень) уходит глубже - прямые syscalls, NtSetInformationThread(ThreadHideFromDebugger) - но в CTF на уровне medium это редкость.

Anti-VM обход в CTF: System Checks и их нейтрализация​

Virtualization/Sandbox Evasion (T1497) и конкретно System Checks (T1497.001) в CTF встречаются реже anti-debug, но на medium-hard уровне - регулярно. Бинарь проверяет, запущен ли он в виртуальной машине, и меняет поведение.

Типичные проверки:
  • CPUID с EAX=1 - бит 31 регистра ECX (hypervisor present bit). Установлен - гипервизор обнаружен.
  • CPUID с EAX=0x40000000 (доступен при установленном hypervisor present bit CPUID.1:ECX[31]) - возвращает 12-байтовый vendor ID гипервизора: VMwareVMware, Microsoft Hv, KVMKVMKVM.
  • Реестр Windows - ключи HKLM\SOFTWARE\VMware, Inc.\VMware Tools, HKLM\SOFTWARE\Oracle\VirtualBox Guest Additions.
  • MAC-адрес - OUI: 00:05:69, 00:0C:29, 00:1C:14, 00:50:56 (VMware, последний - manually assigned/ESXi), 08:00:27 (VirtualBox), 00:15:5D (Hyper-V).
  • Имена процессов - vmtoolsd.exe, VBoxService.exe.
  • RDTSC delta - в VM выполняется медленнее из-за VM-exit.
Проект al-khaser (GitHub: LordNoteworthy/al-khaser, активно поддерживается) собирает публичные anti-VM и anti-debug техники из реального malware - его часто берут как референс при создании CTF-заданий.

Если задание проверяет гипервизор через CPUID - проще запустить бинарь на bare metal. Нет такой возможности - в VirtualBox: --paravirtprovider none скрывает только paravirt-интерфейс (KVM/Hyper-V leaves), но hypervisor present bit (CPUID.1:ECX[31]) остаётся; для его скрытия нужна маскировка CPUID через VBoxManage setextradata "VM" "VBoxInternal/CPUM/HostCPUID/Standard/0x00000001/ecx" <значение с очищенным битом 31>. Для VMware: hypervisor.cpuid.v0 = FALSE в VMX - этот флаг действительно скрывает hypervisor bit.

ПроверкаЧто ищетОбход в CTF
CPUID hypervisor bitБит 31 ECX при EAX=1Bare metal или CPUID-маскировка (VBoxManage setextradata HostCPUID leaf / VMware: hypervisor.cpuid.v0=FALSE)
Registry keysVMware Tools, VBox GAFrida hook на RegOpenKeyEx
MAC OUI00:05:69, 00:0C:29, 00:1C:14, 00:50:56, 08:00:27Смена MAC в настройках VM
Process namesvmtoolsd, VBoxServiceОстановить сервисы перед запуском
RDTSC deltaЗамедление в VMFrida hook + фиксированный return

Современные песочницы (Cuckoo, Any.Run, Triage) скрывают большинство артефактов гипервизора. Продвинутый malware (APT-группы) комбинирует десятки проверок - отдельная тема, выходящая за рамки CTF.

Кастомные шифры в реверс инжиниринге CTF​

Шифрование флага - ядро большинства reverse-заданий. Авторы используют Obfuscated Files or Information (T1027) для сокрытия строки, а задача реверсера - Deobfuscate/Decode Files or Information (T1140).

Типовые паттерны и как их распознать​

XOR с фиксированным ключом (easy). Флаг XOR-ится одно- или многобайтовым ключом. Распознаётся по паттерну xor reg, imm8 в цикле. Однобайтовый ключ - brute force 256 вариантов, Python-скрипт справляется за секунды.

XOR с динамическим ключом (medium). Ключ генерируется в рантайме - хэш от имени процесса, результат системного вызова, производное от другой переменной. Статический анализ тут не вывозит - нужен angr или Frida.

RC4 (medium-hard). Распознаётся по инициализации S-box: массив 256 байт, два вложенных цикла. Первый - заполнение значениями 0–255, второй - перемешивание с ключом (KSA). Видите такую структуру в Ghidra - скорее всего RC4, но проверьте через Findcrypt.

TEA/XTEA (hard). Feistel-сеть с характерной константой 0x9E3779B9 (golden ratio). Если эта константа торчит в бинаре - практически однозначный маркер.

Кастомные конструкции - авторы CTF комбинируют примитивы: ((flag[i] ^ key) + offset) % 256, вложенные циклы, lookup-таблицы. Готового алгоритма нет - реверсить полностью.

Быстрая идентификация алгоритма​

  1. Искать характерные константы - 0x9E3779B9 (TEA), 0x61707865 (ChaCha/Salsa), статический массив 256 элементов (RC4, AES S-box).
  2. Использовать Findcrypt - плагин для IDA и Ghidra, автоматически определяет криптографические константы в бинаре.
  3. Искать циклы с XOR - for + xor в теле = почти наверняка шифрование или обфускация.
  4. Обратить внимание на размер блока - операции над 8-байтовыми блоками = блочный шифр (DES, TEA), побайтовая обработка = потоковый (RC4, XOR).
По программе SANS FOR710 (Reverse-Engineering Malware: Advanced Code Analysis), раздел 2 целиком посвящён криптографии в malware - шифрование файлов, защита ключей, обфускация C2-коммуникаций. Те же навыки идентификации алгоритмов по константам, отработанные на CTF, применяются при вскрытии реальных образцов один в один.

Angr: символьное выполнение для CTF reverse engineering​

angr (версия 9.2.208, GitHub: angr/angr, 7000+ звёзд, активно поддерживается) - фреймворк символьного выполнения. Вместо конкретных значений переменных использует символические, исследует все пути выполнения и находит ввод, который приводит к нужному состоянию - адресу с puts("Correct!").

Когда angr решает задачу мгновенно​

angr идеален для CTF-заданий с линейной проверкой ввода (посимвольное сравнение), множеством условных переходов и кастомными шифрами, где нужен ключ по известному выходу.

Типичный скрипт (пример для демонстрации концепции):
Python:
import angr

proj = angr.Project('./crackme', auto_load_libs=False)
state = proj.factory.entry_state()
simgr = proj.factory.simulation_manager(state)
# find= адрес "Correct!", avoid= адрес "Wrong!"
simgr.explore(find=0x401234, avoid=0x401250)
if simgr.found:
    print(simgr.found[0].posix.dumps(0))
auto_load_libs=False не загружает библиотеки - ускоряет анализ. Адреса find и avoid берутся из Ghidra: find - адрес строки «Correct», avoid - адрес «Wrong» или exit(). На простых CrackMe (100–200 строк кода) результат появляется за 5–40 секунд.

Когда angr не работает​

Path explosion - бинарь с глубокими циклами, хэш-функциями (SHA256, MD5), криптографическими операциями. Количество путей растёт экспоненциально, angr зависает или падает по памяти. Типичный признак: RAM растёт до 8+ ГБ без результата.

Тяжёлое взаимодействие с ОС - файловые операции, сеть, GUI. Нужна ручная настройка SimProcedures - замена системных вызовов заглушками.

Anti-angr задания - opaque predicates, хэш-проверки, VM-based обфускация. Встречается на hard-уровне крупных CTF.

Практическое правило: если angr не выдал результат за 2–3 минуты - переключайтесь на Frida или ручной анализ. Ковыряние с constraints для сложных случаев отнимает больше времени, чем динамический подход.

Frida для динамического анализа малвари в CTF​

Frida (GitHub: frida/frida, 14000+ звёзд, активно поддерживается) - фреймворк Dynamic Binary Instrumentation. Инъектирует JavaScript-код в работающий процесс: перехват вызовов функций, чтение и модификация памяти, патч кода в рантайме. Установка: pip install frida frida-tools.

Перехват крипто-функций и строковых сравнений​

Если бинарь шифрует флаг и сравнивает с эталоном - перехват момента сравнения выдаёт обе строки. Frida-скрипт для перехвата strcmp (пример для демонстрации концепции):
JavaScript:
Interceptor.attach(Module.getExportByName(null, "strcmp"), {
    onEnter: function(args) {
        console.log("strcmp: " +
            args[0].readUtf8String() + " vs " +
            args[1].readUtf8String());
    }
});
Запуск: frida -l hook.js -f ./crackme. Одна из строк, переданных в strcmp, может быть расшифрованным флагом или эталоном для сравнения. Аналогично перехватываются memcmp, strncmp, bcrypt и любые пользовательские функции сравнения по адресу.

Патчинг anti-debug и anti-VM в рантайме​

Вместо статического патча бинаря (который может проверять собственную целостность через CRC) Frida меняет поведение в памяти:
JavaScript:
// Работает только если бинарь вызывает IsDebuggerPresent через IAT.
// Если MSVC инлайнит чтение PEB (mov eax, fs:[30h]; movzx eax, [eax+2]),
// hook на экспорт не сработает - нужно патчить PEB напрямую
// или ставить Interceptor.attach на конкретный адрес инструкции.
Interceptor.replace(
    Module.getExportByName("kernel32.dll", "IsDebuggerPresent"),
    new NativeCallback(function() { return 0; }, 'int', [])
);
Тем же способом перехватываются NtQueryInformationProcess, CheckRemoteDebuggerPresent, GetTickCount для обхода timing checks, RegOpenKeyExA для обхода anti-VM проверок реестра.

Если бинарь слинкован статически, Module.getExportByName не найдёт функцию. Определяйте адрес через Ghidra и используйте Interceptor.attach(ptr("0xADDRESS"), ...).

Для CTF обнаружение Frida несущественно, но в реальном malware analysis - учитывайте: инъекция создаёт модуль frida-agent в списке загруженных библиотек. Продвинутый malware палит Frida через перечисление модулей или имён потоков. Альтернативы - Pin, DynamoRIO или кастомные сборки Frida с переименованными модулями.

Обфускация кода и пакеры в CTF-заданиях​

Помимо anti-debug, anti-VM и шифрования, авторы CTF используют обфускацию кода (T1027) и пакинг (Software Packing, T1027.002).

UPX - самый частый пакер в CTF. Распаковка: upx -d packed_binary. Если заголовок UPX модифицирован (изменены magic bytes) - ручная распаковка: в x64dbg hardware breakpoint на запись в секцию .text, ждём завершения распаковки, дамп через Scylla. На Linux - аналогичный подход через GDB.

Opaque predicates - условные переходы с предопределённым результатом, которые статический анализ не может разрешить. Пример: if ((x * x + x) % 2 == 0) - всегда true, но Ghidra покажет два пути. Засоряют CFG, мешают angr. Обход: NOP ненужной ветки в IDA или параметр avoid в angr для мёртвых путей.

Control Flow Flattening - все базовые блоки перемещаются в один switch-case, порядок определяется переменной-диспетчером. Встречается на hard-уровне. Для CTF часто проще пустить Frida для трассировки реального порядка исполнения (Stalker API), чем восстанавливать CFG вручную.

VM-based обфускация - бинарь содержит собственную виртуальную машину с кастомным байткодом. Самый злой тип заданий. Подход: реверсить диспетчер (fetch-decode-execute loop), восстановить набор инструкций, написать дизассемблер для кастомного байткода. На крупных CTF (CTFtime рейтинг топ-50) такие задачи регулярно дают максимальные баллы.

Когда что применять: decision tree и trade-off автоматизации реверс инжиниринга​

Главный вопрос на CTF при ограниченном времени - какой инструмент доставать первым.

Decision tree для типичного reverse-задания:
  1. file + strings - определить тип, наличие читаемых строк и флагов «в открытую».
  2. Ghidra - найти main, оценить сложность. Есть anti-debug? Переход к п.3. Нет? К п.4.
  3. Anti-debug/anti-VM - ScyllaHide (Windows) или Frida hook. Возврат к п.4.
  4. Логика проверки линейная (серия if или посимвольное сравнение)? - angr. Нет? К п.5.
  5. Логика сложная (хэши, криптография, lookup-таблицы)? - Frida для перехвата результатов + ручной анализ.
  6. angr работает дольше 3 минут? - Остановить, переключиться на Frida или ручной подход.

Trade-off: angr vs Frida vs ручной анализ​

КритерийangrFridaРучной (Ghidra + отладчик)
Скорость на простых CrackMeСекундыМинутыДесятки минут
Path explosion (циклы, хэши)ЗависаетНе применимоЕдинственный вариант
Anti-debug обходНе нужен (нет ОС)Hook в 3 строкиScyllaHide или ручной патч
Перехват крипто в рантаймеНетОсновная силаBreakpoint + dump
Статически слинкованные бинариРаботаетОграничено (нет экспортов)Работает
VM-based обфускацияПлохоТрассировка через StalkerЕдинственный полноценный подход
Кривая обученияСредняя (Python, концепция SMT)Низкая (JavaScript)Высокая (asm, архитектура)
Когда использоватьЛинейные проверки, keygenAnti-debug, API-мониторинг, криптоСложная логика, VM-обфускация
Когда НЕ использоватьХэши, тяжёлая криптографияСтатические бинари без символов20 тасков и 4 часа до конца CTF

Требования к окружению​

ОС: Windows 10/11 x64 для PE-бинарей, Linux Ubuntu 22.04+ для ELF. Рекомендация: FlareVM (Windows, набор для malware analysis) и REMnux (Linux). Для чисто CTF-фокуса хватит одной Linux VM.

RAM: минимум 8 ГБ на хостовой машине с одной VM. 16 ГБ, если запускаете angr на бинарях с широким пространством состояний - символьное выполнение активно жрёт память.

Инструменты:

ИнструментВерсияУстановкаНазначение
Ghidra11.xБесплатно, ghidra-sre.orgСтатический анализ
x64dbg / GDB + pwndbgАктуальныеБесплатноОтладка
angr9.2.208pip install angrСимвольное выполнение
FridaАктуальнаяpip install frida frida-toolsDBI, перехват, патчинг
Python3.10+-Скрипты

Сетевые требования: все инструменты работают offline. Для pip-установки нужен интернет однократно.

angr и Frida конфликтуют с некоторыми зависимостями. Используйте виртуальное окружение: python -m venv rev-env && source rev-env/bin/activate && pip install angr frida frida-tools.

Точка зрения​

Основная ошибка тех, кто приходит в CTF reverse, - попытка решить всё вручную. Сидят в IDA, трассируют каждый байт, тратят час на таск, который angr закрывает за 30 секунд. Вторая ошибка - противоположная: пытаются засунуть в angr задачу с SHA256-проверкой и удивляются, что он «завис». Инструмент - не замена пониманию, а мультипликатор. Без базового чтения ассемблера и понимания, что делает код, ни angr, ни Frida не помогут - вы просто не будете знать, какой адрес передать в find или какую функцию перехватить.

Те, кто утверждает, что «CTF бесполезен для реальной работы» - скорее всего, решали задачи по гайдам и не анализировали паттерны. Боевой malware использует те же anti-debug приёмы (IsDebuggerPresent, timing checks, TLS callbacks), те же пакеры (UPX, модифицированный UPX, кастомные), те же шифры (XOR, RC4, AES). Программа FLARE Team на REcon 2026 построена ровно на этом: shellcode analysis, anti-analysis bypass, ransomware cryptography - каждый модуль начинается с того же, что делает CTF-игрок категории reverse. Разница в том, что после CTF вы переходите к следующему таску, а в malware analysis - пишете отчёт и YARA-правило. Но навык декомпозиции бинаря на слои защиты и последовательного снятия каждого - идентичен. На WAPT эту механику - разбор защит, автоматизация, переход от теории к эксплуатации - проходят с лабами, где каждый вектор нужно отработать самому, а не прочитать в writeup.
 
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab