Злой двойник атакует! Маскируем запуск процессов при помощи Process Doppelgänging
https://t.me/CyberLifesСодержание статьи
- Различия Process Doppelganging и Process Hollowing
- Приступаем к работе
- Как пользоваться недокументированными NTAPI
- Заключение
На конференции Black Hat Europe 2017 был представлен доклад о новой технике запуска процессов под названием Process Doppelganging. Вирмейкеры быстро взяли эту технику на вооружение, и уже есть несколько вариантов малвари, которая ее эксплуатирует. Я расскажу, в чем суть Process Doppelganging и на какие системные механизмы он опирается. Заодно напишем небольшой загрузчик, который демонстрирует запуск одного процесса под видом другого.
Техника Process Doppelganging чем-то похожа на своего предшественника — Process Hollowing, но отличается механизмами запуска приложения и взаимодействия с загрузчиком операционной системы. Кроме того, в новой технике применяются механизм транзакций NTFS и соответствующие WinAPI, например CreateTransaction
, CommitTransaction
, CreateFileTransacted
и RollbackTransaction
, которые, разумеется, не используются в Process Hollowing.
Это одновременно сильная и слабая черта новой техники сокрытия процессов. С одной стороны, разработчики антивирусов и прочего защитного софта не были готовы к тому, что для запуска вредоносного кода будут использованы WinAPI, отвечающие за транзакции NTFS. С другой стороны, после доклада на конференции эти WinAPI сразу попадут под подозрение, если будут встречаться в исполняемом коде. И неудивительно: это редкие системные вызовы, которые практически не применяются в обычных программах. Конечно, есть несколько способов скрыть вызовы WinAPI, но это уже другая история, а сейчас мы имеем неплохой концепт, который можно развивать.
Различия Process Doppelganging и Process Hollowing
Широко распространенная в узких кругах техника запуска исполняемого кода Process Hollowing заключается в подмене кода приостановленного легитимного процесса вредоносным кодом и последующем его выполнении. Вот общий план действий при Process Hollowing.
- При помощи
CreateProcess
открыть легитимный доверенный процесс, установив флагCREATE_SUSPENDED
, чтобы процесс приостановился. - Скрыть отображение секции в адресном пространстве процесса при помощи
NtUnmapViewOfSection
. - Перезаписать код нужным при помощи
WriteProcessMemory
. - Запуститься при помощи
ResumeThread
.
По сути, мы вручную меняем работу загрузчика операционной системы и делаем за него часть работы, попутно подменяя код в памяти.
В свою очередь, для реализации техники Process Doppelganging нам нужно выполнить такие шаги.
- Создаем новую транзакцию NTFS при помощи функции
CreateTransaction
. - В контексте транзакции создаем временный файл для нашего кода функцией
CreateFileTransacted
. - Создаем в памяти буферы для временного файла (объект «секция», функция
NtCreateSection
). - Проверяем PEB.
- Запускаем процесс через
NtCreateProcessEx->ResumeThread
.
Вообще, технология транзакций NTFS(TxF) появилась в Windows Vista на уровне драйвера NTFS и осталась во всех последующих операционных системах этого семейства. Эта технология призвана помочь производить различные операции в файловой системе NTFS. Также она иногда используется при работе с базами данных.
Операции TxF считаются атомарными — пока происходит работа с транзакцией (и связанными с ней файлами) до ее закрытия или отката, она не видна никому. И если будет откат, то операция не изменит ничего на жестком диске. Транзакцию можно создать при помощи функции CreateTransaction
с нулевыми параметрами, а последний параметр — название транзакции. Прототип выглядит таким образом.
HANDLE CreateTransaction( IN LPSECURITY_ATTRIBUTES lpTransactionAttributes OPTIONAL, IN LPGUID UOW OPTIONAL, IN DWORD CreateOptions OPTIONAL, IN DWORD IsolationLevel OPTIONAL, IN DWORD IsolationFlags OPTIONAL, IN DWORD Timeout OPTIONAL, LPWSTR Description );
Приступаем к работе
Начинаем писать приложение с самого начала. Условимся, что наше приложение (пейлоад), которое необходимо будет запустить от имени другого приложения (цели), будет передаваться в качестве второго аргумента, а цель — в качестве первого.
Как пользоваться недокументированными NTAPI
В коде мы будем использовать недокументированные функции NTAPI Windows. Они получаются динамически по своему прототипу. Вот один из возможных методов получения недокументированных функций и работы с ними.
Объявляем прототип функции NtQueryInformationProcess
:
typedef NTSTATUS(WINAPI *NtQueryInformationProcess)(HANDLE, UINT, PVOID, ULONG, PULONG);
На лету получаем адрес нужной функции в библиотеке ntdll.dll по ее имени при помощи GetProcAddress
и присваиваем его переменной нашего прототипа:
pNtQueryInformationProcess NtQueryInfoProcess = (pNtQueryInformationProcess) GetProcAddress( LoadLibrary(L"ntdll.dll"), "NtQueryInformationProcess" );
Здесь используем функцию NtQueryInformationProcess
обычным образом, только через нашу переменную:
NTSTATUS Status = pNtQueryInfoProcess(...); if (Status == 0x00000000) return 0;
Так получаются и используются все необходимые недокументированные функции, которые обычно выносят в header проекта.