Содержание статьи
warning
Статья имеет ознакомительный характер и предназначена для специалистов по безопасности, проводящих тестирование в рамках контракта. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Распространение вредоносных программ, нарушение работы систем и нарушение тайны переписки преследуются по закону.
Как устроены WinAPI Indirect Calls
Зачем изобретать что‑то новое, если есть такая техника, как Indirect Calls для вызовов WinAPI? У нее есть свои сильные стороны, она проста в реализации и хорошо документирована. В двух словах напомню, в чем ее суть.
Indirect Syscalls вызывает NTAPI не напрямую через ntdll.
, а через собственный код, который эмулирует вызов функции NTAPI: формируется стек аргументов, в eax
заносится номер системного сервиса для его вызова, далее выполняется переход по адресу инструкции syscall
в самой ntdll.
. Вот условный код:
// Ранее сформирован стек аргументов, далее сам вызов WinAPI из ntdll.dll
mov r10, rcx
mov eax, <syscall_number>
jmp <address_of_syscall_instruction_in_ntdll>
Со стороны выглядит хорошо, и это работало, пока EDR не научились использовать трассировку событий ETW для раскрутки системного стека вызовов. Все дело в том, что техника Indirect Syscalls позволяет избежать детектирования на уровне пользовательского режима, но оставляет следы в стеке вызовов. EDR может анализировать стек, раскручивая его, и обнаруживать эти аномалии.
Стек, фреймы и EDR
Для дальнейшего понимания придется немного погрузиться в матчасть и понять, как формируются и работают стековые фреймы. Стековый фрейм (или кадр стека) — это область памяти в стеке, выделяемая для выполнения каждой функции в программе. Он содержит такие данные, как параметры функции, локальные переменные, значения регистров, адрес возврата. Простой пример кода:
void func1() { int x = 10; func2(x); ... ...}void func2(int y) { int z = y + 5;}
При вызове func2(
будет сформирован фрейм:
-
RSP
— переменнаяz
; -
RBP
— базовый указатель предыдущего фрейма; -
RBP
— указатель на следующую инструкцию в+ 8 func1(
(адрес возврата);) -
RBP
— параметр функции+ 16 func2
.
Продолжение доступно только участникам
Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».
Присоединяйся к сообществу «Xakep.ru»!
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее