Шрифт
Детект песочницы. Учимся определять, работает ли приложение в sandbox-изоляции
Play

Детект песочницы. Учимся определять, работает ли приложение в sandbox-изоляции

Sandbox (песочница) — изолированная программная среда, в которой задается и контролируется набор ресурсов для запущенной внутри нее программы. Как правило, ограничиваются и фильтруются вызовы WinAPI, которые отвечают за доступ к оборудованию, процессорным ядрам, определение размера памяти, а также доступ к сети и привилегированным средствам операционной системы. Сендбоксинг часто используется для запуска небезопасного кода и для анализа программ.

Проверяем запущенные процессы

Если виды песочниц нам приблизительно известны, то это облегчит детектирование. Можно просто поискать сендбоксы в списке выполняющихся процессов. Для этого используем функцию, которая перечислит все процессы и определит PID нужного по названию.

Детект песочницы Comodo Internet Security:

Процесс cmdvirth.exe обеспечивает виртуализацию в Comodo Internet Security. По тому же принципу можно задетектить песочницу Sandboxie:

Я думаю, что принцип понятен. 🙂 Если процесс не будет найден, функция вернет 0, и условие if не будет выполнено. Также функция вернет 0, если возникнут проблемы с получением первого процесса в системном снапшоте функцией Process32First либо с получением самого снапшота функцией CreateToolhelp32Snapshot .

Проверяем подключенные модули в нашем адресном пространстве

Другая интересная идея — просмотреть подключенные модули в адресном пространстве нашей программы на предмет известных модулей песочниц. Сделаем это напрямую из нашего процесса при помощи WinAPI-функции GetModuleHandle :

Проверка на песочницу Comodo Internet Security:

Или проверим на Sandboxie:

Функция GetModuleHandle() проверяет наличие DLL в адресном пространстве вызывающего процесса. Если функция не находит модуль, то возвращает ноль, условие не срабатывает.

Чтобы узнать список подключенных модулей в стороннем процессе, нужно получить его хендл, вызвав функцию WinAPI OpenProcess , затем перечислить все подключенные к процессу модули с помощью функции EnumProcessModules (в нее следует передать полученный хендл) и, наконец, получить название модуля с помощью функции WinAPI GetModuleFileNameEx .

Человеческий фактор

Что делать, если мы не знаем даже примерно, какая именно программа-песочница будет использована? Надо сказать, что очень сложно на 100% задетектить грамотно написанную песочницу, ведь она будет работать на уровне ядра, может прятать все свои процессы, подключенные модули, может даже скрывать собственный драйвер. Техники, которые будут перечислены далее, я рекомендую использовать по принципу экспертной системы для анализа результатов: чем больше будет срабатываний, тем более вероятно, что мы находимся в изолированной среде.

Первый способ косвенного обнаружения sandbox-изоляции основан на человеческом поведении. Мы допускаем, что после запуска нашей программы указатель мыши перемещался, и если это происходит, то можно предположить, что песочница не используется. Сравним координаты указателя через некоторый промежуток времени: если координаты не меняются, можно ставить один балл в пользу того, что нас исследуют внутри песочницы.

В этой функции мы берем два отрезка времени по полторы секунды каждый и, если в каком-то отрезке времени не было перемещения указателя мыши, делаем вывод, что, скорее всего, выполнение идет под бдительным взором изолированной среды.

PEB → NumberOfProcessors

Изолированные среды часто усекают число процессоров, чтобы не занять все ресурсы компьютера. Например, песочница может эмулировать одноядерный процессор. Но на дворе 2018 год, и даже в мобильных гаджетах зачастую камни с четырьмя ядрами, так что смело можем проверять, сколько ядер процессора видит наша программа. Если ядро всего одно, то это повод для подозрений.

Код для архитектуры x64:

Этот код получает содержимое поля NumberOfProcessors из PEB (Process Environment Block). Теперь легко проверить число процессоров:

Выясняем размер оперативной памяти

Другой побочный признак сендбоксинга — это малое количество оперативной памяти. В наши дни редко можно увидеть ПК с одним-двумя гигабайтами оперативки, теперь это скорее нормальный объем для смартфонов. Вот как будет выглядеть реализация проверки.

Проверяем свободное место

Мало места на жестком диске? Возможно, и правда все забито под завязку, но есть вероятность того, что это очередной признак песочницы. В этом примере мы предполагаем, что программа работает в изоляции, если доступно меньше 30 Гбайт.

Простые тайминг-атаки

Песочницы зачастую весьма требовательны к ресурсам и нередко сильно замедляют работу программы. Мы можем использовать тайминг-атаки для того, чтобы понять, используется эмуляция оборудования или нет. Один из вариантов — выполнять какой-нибудь системный вызов, который на чистой системе будет работать моментально, а в эмулируемой среде замедлен из-за драйвера песочницы. Если разница велика, то можно предположить, что используется песочница. На такой трюк ловится, например, песочница Sandboxie.

Отношение времени выполнения функции CloseHandle и GetProcessHeap() должно быть около 1 к 10. Если отношение меньше, делаем вывод о наличии фильтрации вызовов в драйвере песочницы.

Также песочницы могут оптимизировать течение времени — например, игнорировать вызовы функции Sleep() . Если сделать замеры времени выполнения до вызова Sleep() и после, то мы это увидим.

Быстрый детект гипервизоров

Мы рассмотрели детектирование известных и неизвестных программ-песочниц, но нельзя ли определить гипервизор? Здесь нам поможет инструкция __cpuid . Она запрашивает у процессора его тип и функции, которые он поддерживает. На выходе мы получаем заполненную структуру cpuInfo , которая состоит из четырех чисел, передаваемых в регистрах процессора EAX, EBX, ECX и EDX. На вход нужно подать чистую структуру cpuInfo и число function_id , которое говорит команде, какая именно информация нас интересует. Функция поддерживает как x64-, так и x86-архитектуры. Ее прототип выглядит следующим образом:

Если передать число 1 в поле function_id и посмотреть, выставлен ли 31-й бит в регистре ECX структуры cpuInfo , то можно узнать о присутствии гипервизора. Итак, код:

Помимо этого, известные гипервизоры детектируются так же, как и песочницы: можно просто посмотреть их процессы или характерные записи в реестре. Давай попробуем задетектить гипервизор Virtual PC при помощи функции, которую мы написали выше, — DWORD getPIDproc(char * pProcName) . Просто передадим в нее имя нужных процессов, характерных для Virtual PC:

Так же легко найдем гипервизор Citrix Xen:

Теперь посмотрим, как задетектить гипервизоры по характерным записям в реестре. Для этого напишем небольшую функцию, которая поможет нам определить, что программа исполняется внутри Wine.

Заключение

Вот мы и разобрали, как определять известные изолированные среды разными способами. Это не все из возможных методов, но от такого набора заготовок можно будет отталкиваться, конструируя свои методы определения (а возможно, и обхода) сендбоксинга.

📎📎📎📎📎📎📎📎📎📎