На конференции 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 комментарий

  1. LuckyTiger

    31.08.2018 at 01:54

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

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

Check Also

Эхо кибервойны. Как NotPetya чуть не потопил крупнейшего морского перевозчика грузов

Российское кибероружие, построенное на утекших у АНБ эксплоитах, маскировалось под вирус-в…