
Так как мы не знаем внутренних особенностей работы коммерческих песочниц, в некоторых случаях мы делаем double-check – вручную анализируем сэмплы, прошедшие проверку. За последнее время мы несколько раз столкнулись с тем, что некоторые коммерческие песочницы (по объективным причинам мы не можем сказать, какие) при динамическом анализе не детектировали определённые вредоносные файлы и, если статический анализатор тоже молчал, файл и вовсе пропускался.
Проверку в песочнице удалось обойти таким известным семействам вредоносного ПО, как Pony, Loki и Hawkeye. Объединяло их лишь одно — они были накрыты упаковщиком, написанным на Visual Basic.
Учитывая, что эти семейства ВПО уже давно не являются чем-то новым, «положительный» вердикт песочниц весьма удручает. Поэтому мы решили описать общий принцип работы этого упаковщика и наблюдения, сделанные нами на протяжении некоторого времени.
Общая схема работы упаковщика условно разделена на 4 стадии и изображена на схеме ниже.

Точка входа вредоносного файла выглядит типично для приложений на Visual Basic:

Мы встречали различные варианты данного упаковщика, и код VB Wrapper часто менялся, но выполняемая задача оставалась той же: передать управление коду Stage 1. В более ранних образцах передача управления производилась посредством API-функций класса Enum* (например, EnumWindows, EnumCalendarInfo и т.д), у которых в качестве параметра указывался адрес Stage 1 кода. В последнее время наблюдаем, что управление передается напрямую.
1 этап
Управление получает код Stage 1. Данный код не зашифрован, но обфусцирован. Методы обфускации варьируются от сэмпла к сэмплу, но общий алгоритм работы не меняется:
1) Цикл с множеством (в том числе и мусорных) инструкций, который вырабатывает необходимый для расшифровки кода Stage 2 ключ. Особенность этого фрагмента кода заключается в том, что там отсутствуют Sleep-функции, но за счет большого количества итераций его выполнение занимает в среднем 1-2 минуты.
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-атак, наши наблюдения говорят о том, что даже широко известные сообществу вредоносные семейства проникают внутрь инфраструктуры с завидным постоянством. Так как нет гарантий, что сэмпл, который обошел песочницу, не будет иметь в арсенале пару техник по обходу антивируса , полагаться только на эту связку защитных решений нельзя. В таких случаях обеспечить своевременное реагирование и минимизацию потенциального ущерба может правильно выстроенный процесс мониторинга, включающий в себя события информационной безопасности с конечных хостов.