Как я распаковал реальный семпл трояна на собеседовании на реверс-инженера и что спросили после

На одном из собеседований в ИБ-компанию мне передали флешку с единственным файлом и сказали: «Два часа, ноутбук, любые инструменты. Расскажите, что делает этот бинарник.» Файл весил 183 КБ. Detect It Easy показал секции UPX0 и UPX1, энтропия основной секции — 7.83. Классическая упаковка. За полтора часа я распаковал семпл, вытащил строки, восстановил таблицу импортов и показал поведение трояна. А потом начались вопросы, которые оказались сложнее самого задания. Ниже — разбор процесса и всё, что стоит знать, если готовишься к тестовому заданию реверс-инженера.
Зачем на собеседовании реверс-инженера дают реальный семпл
Тестовое задание реверс-инженера — не экзамен на знание ассемблера наизусть. Интервьюер наблюдает за процессом: как ты выстраиваешь приоритеты, с какого инструмента начинаешь, замечаешь ли упаковку по косвенным признакам, вовремя ли переключаешься между статическим и динамическим анализом. Результат важен, но путь к нему важнее.
В Лаборатории Касперского, по описанию Алексея Маланова (руководитель отдела антивирусных исследований, опубликовал детальный разбор процесса найма на Хабре), кандидату заранее высылают крэкми — компактный бинарник для домашнего анализа. Некоторые соискатели гуглят имя файла и копируют чужое решение. Вскрывается на первом же уточняющем вопросе о конкретных инструкциях внутри.
На моём собеседовании задание было серьёзнее крэкми: реальный упакованный семпл без подсказок. Вот что оценивалось:
- Триаж — умение за минуты определить тип файла, архитектуру, наличие упаковки
- Методичность — последовательная работа по шагам вместо хаотичного тыканья в дизассемблере
- Выбор инструмента — понимание, когда дизассемблер бесполезен и пора запускать отладчик
- Коммуникация — способность проговаривать вслух, что видишь и почему принял конкретное решение
Бизнес-логика задания прямая: malware analyst каждый день получает десятки подозрительных файлов. По данным IBM X-Force Threat Intelligence Index 2025, infostealers составляют 32% всего детектируемого malware — и почти каждый использует минимум один слой упаковки. Если каждый семпл анализировать часами — конвейер встанет. Интервьюер проверяет, способен ли кандидат быстро отсеять шум и сосредоточиться на реальном поведении вредоноса.
Статический анализ малвари: первые пять минут с файлом
Статический анализ — исследование файла без его запуска. Смотришь на структуру, метаданные, строки и импорты, чтобы составить первичную картину до того, как запустишь потенциально опасный код в отладчике.
Что нужно: Windows-машина или виртуалка с Detect It Easy (DIE) и PE-bear. Оба инструмента бесплатные. На Linux подойдёт radare2.
Первое действие — загрузить файл в DIE. Detect It Easy определяет компилятор, линковщик и пакер по сигнатурам. DIE покажет три вещи:
- Формат: PE32 или PE64. PE (Portable Executable) — стандартный формат исполняемых файлов Windows
- Пакер: если файл упакован UPX, ASPack, VMProtect или чем-то кастомным — DIE определит по сигнатуре
- Энтропия секций: число от 0 до 8. Значение выше 7 говорит о сжатых или зашифрованных данных. Нормальный скомпилированный код — 5–6
В моём случае DIE показал: UPX, энтропия основной секции 7.83. Названия секций подтвердили диагноз — UPX0 (пустая секция, куда распакуется код) и UPX1 (сжатые данные). По данным HackMag, имена секций — один из самых надёжных индикаторов упаковки, хотя авторы малвари могут их переименовывать, чтобы сбить автодетект.
Зачем злоумышленник упаковывает бинарник? Сигнатурный антивирус сравнивает байты файла с базой. Если те же байты сжать или зашифровать — сигнатура перестаёт совпадать. В терминах MITRE ATT&CK (открытая база тактик и техник атак; каждой технике присвоен T-код, например T1027) упаковка — техника Software Packing (T1027.002), подтехника Obfuscated Files or Information (T1027). Самый дешёвый способ обойти статическое детектирование. В реальных атаках упаковка часто становится первым слоем защиты дроппера на этапе initial access — ещё до закрепления и эксфильтрации.
Второй шаг триажа — проверить таблицу импортов. IAT (Import Address Table) — список функций из системных библиотек, которые использует программа. У упакованного файла импортов минимум: обычно только LoadLibraryA и GetProcAddress из kernel32.dll. Этого хватает стабу-распаковщику, чтобы подгрузить всё остальное в рантайме. Легитимная программа импортирует десятки функций, упакованная — две-три. Малое количество импортов плюс высокая энтропия — практически безошибочный диагноз.
Для тех, кто предпочитает командную строку, энтропию секций можно проверить в radare2:
r2 -q -c "iH" suspect.exe
Команда iH выводит заголовки PE-файла с информацией о секциях. Видишь секцию с entropy > 7.0 при минимальном числе импортов — переходи к распаковке.
Распаковка трояна вручную: пошаговый разбор
Упаковка подтверждена. Три стратегии:
- Автоматическая:
upx -d packed.exe -o unpacked.exeснимает стандартный UPX за секунду - Полуавтоматическая: QuickUnpack или RL!dePacker пытаются найти OEP и сдампить процесс универсальным алгоритмом. Работает не всегда, но иногда экономит время
- Ручная: отладчик x64dbg, пошаговое выполнение до OEP, дамп памяти, восстановление IAT
На собеседовании я сознательно не стал запускать upx -d. Интервьюер давал семпл для проверки ручных навыков — автораспаковка заняла бы 30 секунд и ничего не показала бы о квалификации. Ручной подход ниже применим и к кастомным пакерам, когда автоматика бесполезна.
Как найти OEP в отладчике
OEP (Original Entry Point) — адрес, с которого начинается выполнение оригинальной, распакованной программы. Пакер подменяет точку входа на свой стаб — небольшой фрагмент кода-распаковщика. Стаб распаковывает оригинальный код в память, восстанавливает импорты и передаёт управление на OEP.
Механика стаба в упрощённом виде:
; Стаб UPX — пример для демонстрации концепции
pushad ; сохранить все регистры в стек
mov esi, UPX1_addr ; источник: сжатые данные
mov edi, UPX0_addr ; назначение: пустая секция
call unpack_loop ; цикл распаковки
popad ; восстановить регистры
jmp OEP ; передать управление оригинальному коду
Что нужно: x64dbg (бесплатный отладчик для Windows, де-факто стандарт для динамического анализа малвари) установлен в изолированной виртуальной машине. Семпл загружается строго в VM — никогда на хостовой системе.
Шаг 1. Открой семпл в x64dbg. Программа остановится на системной Entry Point. Стаб UPX начинается с инструкции pushad — она сохраняет содержимое всех регистров общего назначения (EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI) в стек одним вызовом. Первая видимая инструкция должна быть pushad. Если вместо неё что-то другое — пакер модифицирован и стандартный трюк не сработает.
Шаг 2. Выполни pushad (F8 — Step Over). Запомни текущее значение регистра ESP — адрес вершины стека после сохранения регистров. Поставь аппаратный брейкпоинт на доступ к этому адресу: правый клик на значении ESP в панели регистров → Follow in Dump → в окне дампа правый клик на первом байте → Breakpoint → Hardware, Access → DWORD.
Логика такая: стаб сохранил регистры через pushad, провёл распаковку и перед прыжком на OEP выполнит popad — обращение к тому же адресу стека. В этот момент брейкпоинт сработает. Нажми Run (F9).
Шаг 3. Отладчик остановится вблизи инструкции popad. Сделай несколько Step Over (F8), пока не увидишь jmp 0x00XXXXXX — это прыжок на OEP. Нажми Step Into (F7) на этом jmp. Теперь регистр EIP содержит адрес первой инструкции оригинальной программы. Запиши его — понадобится для дампа.
Дамп и восстановление таблицы импортов
Код распакован в памяти, но на диске файл по-прежнему сжат. Нужно сдампить процесс — сохранить содержимое памяти как новый PE-файл — и восстановить IAT, чтобы получить пригодный для анализа бинарник.
Для этого подходит Scylla — бесплатная утилита для реконструкции импортов, встроенная в x64dbg как плагин:
- Не закрывая отладчик на OEP, открой Scylla через меню Plugins → Scylla
- Убедись, что в поле OEP указан найденный адрес. Если поле пустое — впиши вручную
- Нажми «IAT Autosearch» — Scylla просканирует память процесса и найдёт границы таблицы импортов
- Нажми «Get Imports» — на экране появится дерево восстановленных API-функций по DLL. Часть импортов помечена как невалидная? Нажми «Show Invalid» и удали битые записи
- Нажми «Dump» → укажи имя нового файла → затем «Fix Dump» — Scylla пропатчит дамп и впишет восстановленную IAT
Результат: новый PE-файл, который DIE определяет без пакера. Энтропия секций упала до 5–6. Таблица импортов теперь содержит десятки функций: CreateFileA, WriteFile, InternetOpenA, RegSetValueExA — реальное поведение трояна стало видно на уровне API.
В терминах MITRE ATT&CK троян при запуске выполняет T1140 (Deobfuscate/Decode Files or Information) — деобфусцирует собственный код в памяти. Мы повторили этот процесс под контролем отладчика и получили чистый бинарник для дальнейшего анализа.
Вопросы на собеседовании реверс-инженера после практической части
После демонстрации результатов распаковки (троян закреплялся через реестр и связывался с C2-сервером по HTTP) начались теоретические вопросы. Каждый привязан к конкретной рабочей задаче — интервьюер проверяет не эрудицию, а умение применить знание в бою.
«Как малварь определяет, что работает под отладчиком?»
Вопрос про anti-debug — техники обнаружения анализа. В MITRE ATT&CK это Debugger Evasion (T1622). Основные методы:
IsDebuggerPresent()— WinAPI-функция, проверяющая флагBeingDebuggedв PEB (Process Environment Block — служебная структура, которую ОС создаёт для каждого процесса)- Проверка
NtGlobalFlagв PEB — при отладке содержит значение 0x70 вместо нулевого - Timing checks — замер времени через инструкцию
rdtsc(считывает счётчик тактов процессора): под отладчиком пошаговое выполнение медленнее, разница во времени выдаёт дебаггер
Похожие по смыслу, но шире — проверки на виртуализацию и песочницу (T1497 — Virtualization/Sandbox Evasion). Малварь может искать артефакты VM: специфические MAC-адреса, имена процессов VMware Tools или VirtualBox Guest Additions, характерные значения CPUID.
Правильный ответ включает не только перечисление, но и способы обхода. Плагин ScyllaHide для x64dbg патчит PEB-флаги и перехватывает API-вызовы, скрывая факт отладки от проверяемого процесса.
«Что такое API hashing и зачем это нужно?»
Малварь не хранит имена функций в открытом виде (как CreateFileA), а сохраняет их хеши — числовые значения, вычисленные по имени функции. При запуске вредонос перебирает экспортируемые функции загруженных DLL, хеширует каждое имя и сравнивает результат с сохранённым значением. Совпало — функция найдена. Это убивает статический анализ: в строках и таблице импортов нет ничего читаемого.
Зачем спрашивают: если кандидат знает про API hashing, он справится с серьёзными семплами, где DIE и утилита strings ничего полезного не покажут.
«Объясни разницу между секциями .text, .data, .rdata и .rsrc в PE-файле.»
Базовый вопрос на понимание PE-формата:
| Секция | Содержимое | Права доступа |
|---|---|---|
| .text | Исполняемый код (машинные инструкции) | Execute + Read |
| .data | Изменяемые глобальные переменные | Read + Write |
| .rdata | Константы, таблица импортов | Read only |
| .rsrc | Ресурсы: иконки, строки, манифесты. Иногда — зашифрованный пейлоад второй стадии | Read only |
«Какие WinAPI-функции поставишь на брейкпоинт при анализе неизвестного семпла?»
Ключевой практический вопрос. Ответ — по категориям поведения:
| Категория | Функции для breakpoint |
|---|---|
| Файловая система | CreateFileA/W, WriteFile, DeleteFileA |
| Сеть | InternetOpenA, HttpSendRequestA, WSAStartup |
| Реестр | RegSetValueExA, RegCreateKeyExA |
| Процессы и инъекция | CreateProcessA, VirtualAllocEx, WriteProcessMemory |
| Антианализ | IsDebuggerPresent, GetTickCount, Sleep |
VirtualAlloc и VirtualProtect особенно важны при распаковке: через них малварь выделяет память и меняет права доступа перед записью распакованного кода. Брейкпоинт на VirtualProtect с аргументом PAGE_EXECUTE_READWRITE (0x40) — стандартный приём для перехвата момента, когда пейлоад готов к исполнению. Эта механика связана с Process Injection (T1055) — внедрение кода в чужой процесс для маскировки или повышения привилегий.
Что выдаёт новичка на собеседовании malware analyst
Прыжок в IDA без триажа. Кандидат открывает файл в дизассемблере и 40 минут блуждает по коду стаба пакера. Стаб — обёртка, не сам вредонос. Пять минут в DIE с проверкой энтропии и импортов сэкономили бы это время.
Незнание энтропии. На вопрос «почему решил, что файл упакован?» ответ «секции называются UPX» — слабый. Ответ «энтропия секции 7.83 указывает на сжатые данные, плюс в IAT всего два импорта из kernel32» — сильный. Авторы малвари переименовывают секции. Энтропия не обманет.
Неспособность объяснить действия. Распаковал — хорошо. Но если не можешь сказать, почему поставил брейкпоинт именно на ESP после pushad, интервьюер решит, что ты заучил рецепт без понимания механики. На собеседовании ценится не скорость, а осознанность.
Игнорирование anti-debug. Семпл завершился при запуске в отладчике — кандидат растерялся. Проверка IsDebuggerPresent (T1622) — первое, что стоит обойти. В x64dbg достаточно включить ScyllaHide с профилем Basic.
Отсутствие привычки документировать. Не записывать адреса, хеши, найденные строки по ходу анализа — через час работы кандидат не может вспомнить адрес OEP. В ежедневной работе аналитика без структурированных заметок не продержаться и дня.
Интервьюер из Касперского (по описанию Маланова) добавил бы к техническим вопросам задачу на внимательность: «Верно ли, что если 6/a < 3, то a > 2?» Ответ «верно» — ошибка: переменная a может быть отрицательной. Это не про математику, а про привычку проверять граничные условия. В реверсе один пропущенный edge case в анализе ветвления — и вся картина поведения вредоноса рассыпается.
Тестовое задание на распаковку — не финальный экзамен, а начало разговора. Реальная ценность кандидата проявляется в вопросах после: API hashing, anti-debug обход, PE-структура — всё это отделяет человека, который посмотрел один tutorial на YouTube, от того, кто разобрал двадцать семплов руками.
Моя позиция жёсткая: 90% подготовки к собеседованию на malware analyst — не зубрёжка вопросов-ответов, а практика с живыми семплами. Десять файлов с MalwareBazaar через цепочку DIE → x64dbg → Scylla → Ghidra. После пятого распакованного инфостилера процесс станет мышечной памятью, а на собеседовании ты будешь объяснять механику, а не вспоминать чужие инструкции. Через пару лет автоматизация закроет тривиальные случаи — стандартный UPX, типовой ASPack. Кастомные крипторы, VM-протекторы, многослойная упаковка по-прежнему будут требовать ручной работы — и именно эти навыки проверяют на собеседовании. Если ищешь джуниор-роль и хочешь выстроить базу системно — на codeby.school есть IB Basics, а пара десятков разобранных семплов дадут что показать на собесе.
Эту тему и смежные навыки разбирают на практике в курсе «Профессия Реверс-инженер» Codeby Academy.