Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Так как мы не знаем внутренних особенностей работы коммерческих песочниц, в некоторых случаях мы делаем double-check – вручную анализируем сэмплы, прошедшие проверку. За последнее время мы несколько раз столкнулись с тем, что некоторые коммерческие песочницы (по объективным причинам мы не можем сказать, какие) при динамическом анализе не детектировали определённые вредоносные файлы и, если статический анализатор тоже молчал, файл и вовсе пропускался.
Проверку в песочнице удалось обойти таким известным семействам вредоносного ПО, как Pony, Loki и Hawkeye. Объединяло их лишь одно — они были накрыты упаковщиком, написанным на Visual Basic.
Учитывая, что эти семейства ВПО уже давно не являются чем-то новым, «положительный» вердикт песочниц весьма удручает. Поэтому мы решили описать общий принцип работы этого упаковщика и наблюдения, сделанные нами на протяжении некоторого времени.
Общая схема работы упаковщика условно разделена на 4 стадии и изображена на схеме ниже.
Точка входа вредоносного файла выглядит типично для приложений на Visual Basic:
Мы встречали различные варианты данного упаковщика, и код VB Wrapper часто менялся, но выполняемая задача оставалась той же: передать управление коду Stage 1. В более ранних образцах передача управления производилась посредством API-функций класса Enum* (например, EnumWindows, EnumCalendarInfo и т.д), у которых в качестве параметра указывался адрес Stage 1 кода. В последнее время наблюдаем, что управление передается напрямую.
1 этап
Управление получает код Stage 1. Данный код не зашифрован, но обфусцирован. Методы обфускации варьируются от сэмпла к сэмплу, но общий алгоритм работы не меняется:
- Цикл с множеством (в том числе и мусорных) инструкций, который вырабатывает необходимый для расшифровки кода Stage 2 ключ. Особенность этого фрагмента кода заключается в том, что там отсутствуют Sleep-функции, но за счет большого количества итераций его выполнение занимает в среднем 1-2 минуты.
- Расшифровка (обычный XOR) и передача управления коду Stage 2.
На скриншоте ниже приведены примеры используемых методов обфускации:
2 этап
Основной задачей кода в Stage 2 является проверка окружения и реализация методов антиотладки. Некоторые участки кода зашифрованы (расшифровываются перед выполнением, а после – зашифровываются обратно все тем же алгоритмом XOR) для затруднения детектирования по сигнатурам. После расшифровки видны характерные признаки, по которым код Stage 2 можно узнать при ручном анализе.
Список проверок довольно большой и отличается в разных версиях упаковщика, поэтому мы приведем несколько методов, которые встречались во всех версиях, со скриншотами, а в конце перечислим весь список в таблице.
1) GetTickCount + Sleep
Берется текущая метка времени, вызывается Sleep на 2 секунды, после чего сразу же берется еще одна метка времени.
После этого проверяется разница между метками (на самом ли деле прошло 2 секунды).
2) SetErrorMode
Проверяется правильность работы API-вызова SetErrorMode. Функция вызывается два раза подряд с параметрами 0x800 и 0x0, после чего результат второго вызова проверяется: он должен быть равен 0x800.
3) SetLastError
Сначала вызывается SetLastError с параметром 0x5, после чего проверяется, что значение Last error code в TEB правильно установилось (то есть, равно 0x5).
4) Проверка движения курсора
Код входит в бесконечный цикл, ожидающий передвижения указателя мыши.
5) DbgBreakPoint и DbgUiRemoteBreakin
Данные функции модифицируются, чтобы помешать отладчику подсоединиться к процессу.
Техника |
Комментарий |
GetTickCount + Sleep |
Проверка временных меток |
SetErrorMode |
Проверка правильной работы функции |
SetLastError |
Проверка правильной работы функции |
GetCursorPos |
Проверка движения курсора |
DbgBreakPoint |
Модификация функции для запрета присоединения отладчика |
DbgUiRemoteBreakin |
Модификация функции для запрета присоединения отладчика |
Hook Deletion |
Восстанавливаются первые 5 байт функций в ntdll.dll на случай, если там стоят хуки |
NtSetInformationThread |
Параметр 0x11 (ThreadHideFromDebugger) |
GetThreadContext + check DR |
Проверяются отладочные регистры DR0-DR3, DR6, DR7 |
Check breakpoints |
Проверяются инструкции INT3 (0xCC), int 3 (0xCD 0x03) и ud2 (0x0F 0x0B) в начале некоторых функций |
cpuid (EAX=0x0) |
Проверяются регистры EAX, ECX, EDX |
cpuid (EAX=0x40000000) |
Проверяются регистры EAX, ECX, EDX |
cpuid (EAX=0x1) |
Проверяется 31-й бит ECX |
PEB (BeingDebugged) |
Проверяется значение 0x1 |
PEB (NtGlobalFlag) |
Проверяется значение 0x70 |
NtQueryInformationProcess |
Вызывается с флагами ProcessDebugPort (0x7), ProcessDebugFlags (0x1F), ProcessDebugObjectHandle (0x1E) |
Process Name Check |
Проверяются строки «sample», «sandbox», «virus», «malware», «self.» |
В случае выполнения всех техник этапа 2 происходит проверка командной строки на соответствие специальному формату. Если проверка не проходит, то выполняются следующие действия:
1) Вызывается функция CreateProcess с флагом CREATE_SUSPENDED для перезапуска текущего процесса. При этом командная строка имеет необходимый формат.
2) С помощью функций GetContextThread и SetContextThread точка входа изменяется на новую, которая находится в коде Stage 1.
3) Повторяются этапы 1 и 2 (включая длительный цикл и все проверки). В этот раз проверка командной строки проходит успешно и процесс переходит к следующему этапу.
3 этап
На этом этапе расшифровывается тело основного вируса и выполняется техника Process Hollowing на текущий процесс, после чего управление передается на точку входа основного вируса.
Lesson Learned
Точно сказать, что в данном случае вызывает проблемы у той или иной песочницы мы не можем, но хочется верить, что возможность использования вредоносным ПО техник, описанных в статье, давно предусмотрена вендорами, и проблема кроется лишь в длительной временной задержке на первом этапе работы упаковщика.
Несмотря на то, что современные песочницы в большинстве своем позиционируются как часть систем защиты от APT-атак, наши наблюдения говорят о том, что даже широко известные сообществу вредоносные семейства проникают внутрь инфраструктуры с завидным постоянством. Так как нет гарантий, что сэмпл, который обошел песочницу, не будет иметь в арсенале пару техник по обходу антивируса, полагаться только на эту связку защитных решений нельзя. В таких случаях обеспечить своевременное реагирование и минимизацию потенциального ущерба может правильно выстроенный процесс мониторинга, включающий в себя события информационной безопасности с конечных хостов.