
P³-Shellcode Loader — это загрузчик, реализующий технику внедрения кода, которая использует структуру Process Parameters в качестве места выполнения и промежуточного хранения для инъекции шеллкода в удаленные процессы, не активируя стандартные механизмы обнаружения.
Авторы: Макс Хиршбергер и Огулкан Угур
P³-Shellcode Loader — это загрузчик, реализующий технику внедрения кода, которая использует структуру параметров процесса (отравление параметров процесса) в качестве места выполнения и временного хранения для внедрения шелл-кода в удалённые процессы, не запуская типичные механизмы обнаружения.
Похожая концепция была описана исследователем безопасности modexp, который показал, что аргументы, передаваемые в API CreateProcess, могут быть использованы для этой цели [1].
Злоумышленники стремятся сделать свои действия менее подозрительными. С помощью внедрения в процесс они могут выполнять свои действия из другого, более доверенного процесса или такого, который ожидаемо выполняет данное действие, тем самым снижая подозрения.
Ниже перечислены типичные шаги, необходимые для внедрения кода в другой процесс:
OpenProcess / NtOpenProcess или CreateProcess / NtCreateProcess).VirtualAllocEx или NtAllocateVirtualMemory).WriteProcessMemory / NtWriteVirtualMemory).VirtualProtectEx / NtProtectVirtualMemory).CreateRemoteThread или NtCreateThreadEx).Дополнительные техники внедрения включают, помимо прочего, следующие:
NtSetContextThread).NtQueueApcThread).RtlCreateProcessReflection, реализующим ветвление процессов.
В ходе нашего тестирования мы заметили, что большинство EDR ориентируются на определённую телеметрию для обнаружения внедрения процессов. EDR в первую очередь отслеживают использование WriteProcessMemory и VirtualAllocEx, а также их базовые системные вызовы ядра NtWriteVirtualMemory, NtAllocateVirtualMemory и NtAllocateVirtualMemoryEx.Windows предоставляет функцию API CreateProcessW для создания новых процессов, показанную в листинге 1. Первые три её параметра — lpCommandLine, lpEnvironment и lpStartupInfo — важны для описываемой техники внедрения, поскольку они используются для передачи данных в новый процесс.```c
BOOL CreateProcessW(
[in, optional] LPCWSTR lpApplicationName,
[in, out, optional] LPWSTR lpCommandLine,
[in, optional] LPSECURITY_ATTRIBUTES lpProcessAttributes,
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] BOOL bInheritHandles,
[in] DWORD dwCreationFlags,
[in, optional] LPVOID lpEnvironment,
[in, optional] LPCWSTR lpCurrentDirectory,
[in] LPSTARTUPINFOW lpStartupInfo,
[out] LPPROCESS_INFORMATION lpProcessInformation
);
*Листинг 1: Определение функции CreateProcessW Windows API*
Параметр `lpCommandLine` задает командную строку для нового процесса. Он ограничен максимумом 32 767 символов Unicode, включая завершающий нулевой символ Unicode. Для варианта Unicode необходимо предоставить строку, в которую функция может выполнять запись. Если передается константная строка, любые попытки записи со стороны API-функции приведут к нарушению прав доступа к памяти. Если значение равно `NULL`, командная строка процесса будет взята из параметра `lpApplicationName`. Если `lpApplicationName` равен `NULL`, она должна быть указана в поле `lpCommandLine` и ограничена `MAX_PATH` символами.
Параметр `lpEnvironment` предоставляет процессу список переменных окружения. Если значение равно `NULL`, будет использоваться окружение создающего процесса. Список переменных окружения состоит из последовательных строк, завершающихся нулевым символом, в формате `NAME=VALUE` с еще одним нулевым символом в конце.
Параметр `lpStartupInfo` представляет собой структуру, показанную в Листинге 2, с такими полями, как оконная станция, рабочий стол, дескрипторы стандартного ввода и вывода, а также поля, настраивающие главное окно нового процесса. Согласно документации Microsoft, поле `lpReserved` зарезервировано для внутреннего использования и не документировано. В ходе анализа с помощью отладчика WinDbg удалось связать этот параметр с переменной `ShellInfo` типа `UNICODE_STRING` в новом процессе.```c
typedef struct _STARTUPINFOW {
DWORD cb;
LPWSTR lpReserved; // Copied to ShellInfo (UNICODE_STRING)
LPWSTR lpDesktop;
LPWSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
// (...) additional fields
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
// (...) additional fields
} STARTUPINFOW, *LPSTARTUPINFOW;
Листинг 2: Структура данных STARTUPINFOW