На конференции Black Hat Europe 2017 был представлен доклад о новой технике запуска процессов под названием Process Doppelgänging. Вирмейкеры быстро взяли эту технику на вооружение, и уже есть несколько вариантов малвари, которая ее эксплуатирует. Я расскажу, в чем суть Process Doppelgänging и на какие системные механизмы он опирается. Заодно напишем небольшой загрузчик, который демонстрирует запуск одного процесса под видом другого.

Техника Process Doppelgänging чем-то похожа на своего предшественника — Process Hollowing, но отличается механизмами запуска приложения и взаимодействия с загрузчиком операционной системы. Кроме того, в новой технике применяются механизм транзакций NTFS и соответствующие WinAPI, например CreateTransaction, CommitTransaction, CreateFileTransacted и RollbackTransaction, которые, разумеется, не используются в Process Hollowing.

Это одновременно сильная и слабая черта новой техники сокрытия процессов. С одной стороны, разработчики антивирусов и прочего защитного софта не были готовы к тому, что для запуска вредоносного кода будут использованы WinAPI, отвечающие за транзакции NTFS. С другой стороны, после доклада на конференции эти WinAPI сразу попадут под подозрение, если будут встречаться в исполняемом коде. И неудивительно: это редкие системные вызовы, которые практически не применяются в обычных программах. Конечно, есть несколько способов скрыть вызовы WinAPI, но это уже другая история, а сейчас мы имеем неплохой концепт, который можно развивать.

 

Различия Process Doppelgänging и Process Hollowing

Широко распространенная в узких кругах техника запуска исполняемого кода Process Hollowing заключается в подмене кода приостановленного легитимного процесса вредоносным кодом и последующем его выполнении. Вот общий план действий при Process Hollowing.

  1. При помощи CreateProcess открыть легитимный доверенный процесс, установив флаг CREATE_SUSPENDED, чтобы процесс приостановился.
  2. Скрыть отображение секции в адресном пространстве процесса при помощи NtUnmapViewOfSection.
  3. Перезаписать код нужным при помощи WriteProcessMemory.
  4. Запуститься при помощи ResumeThread.

По сути, мы вручную меняем работу загрузчика операционной системы и делаем за него часть работы, попутно подменяя код в памяти.

В свою очередь, для реализации техники Process Doppelgänging нам нужно выполнить такие шаги.

  1. Создаем новую транзакцию NTFS при помощи функции CreateTransaction.
  2. В контексте транзакции создаем временный файл для нашего кода функцией CreateFileTransacted.
  3. Создаем в памяти буферы для временного файла (объект «секция», функция NtCreateSection).
  4. Проверяем PEB.
  5. Запускаем процесс через 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 проекта.

Продолжение доступно только подписчикам

Вариант 1. Оформи подписку на «Хакер», чтобы читать все материалы на сайте

Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке

Вариант 2. Купи один материал

Заинтересовала информация, но нет возможности оплатить подписку? Тогда этот вариант для тебя! Обрати внимание: этот способ покупки доступен только для материалов, опубликованных более двух месяцев назад.


1 комментарий

  1. LuckyTiger

    31.08.2018 at 01:54

    Очень понравилось. Так держать.

Оставить мнение

Check Also

Энкодеры msfvenom. Разбираемся с кодированием боевой нагрузки при бинарной эксплуатации

Генерация полезной нагрузки — неотъемлемая часть эксплуатации. При использовании модулей M…