Как стать автором
Обновить

Комментарии 9

«использует собственную операционную» я так понимаю, всё таки имелось ввиду «использует собственно операционную»?
уж больно сильно смысл отличается.

по названию, я так понимаю, идея в том, что засовываем в атом наш вредоносный код — и он появляется в других процессах. осталось только найти способ передать на него управление (и сохранить исполняемость этого региона памяти). Верно?

В общем, как-то самого важного — КАК работает актака — в статье и нет.
Есть какой-то маркетинговый булшит.
В общем, как-то самого важного — КАК работает актака — в статье и нет.

В заметке есть ссылка http://blog.ensilo.com/atombombing-a-code-injection-that-bypasses-current-security-solutions и там дальше https://breakingmalware.com/injection-techniques/atombombing-brand-new-code-injection-for-windows/ с картинками и https://github.com/BreakingMalwareResearch/atom-bombing
Не понял, почему нельзя запатчить NtQueueApcThread для всего кроме вайтлиста функций.

Суть не в том, что атаку нельзя детектировать, а в том, что контролируемый со стороны Security-продуктов вызов WriteProcessMemory заменили на вызов GlobalAddAtom из своего процесса и вызов GlobalGetAtomName через APC механизм NtQueueApcThread в целевом процессе.


И новая серия вызовов у Security-продуктов пока вызывает меньше подозрений или не вызывает вообще.

Цитата статьи:
В силу природы данной техники, к сожалению, вряд ли он может быть пропатчен.


Я вот с этим не понимаю. NtQueueApcThread c вызовом чего угодно кроме RtlDispatchAPC не имеет смысла (ну, возможно, есть еще 1-2 функции — в общем, передавать надо не адрес а ID функции вызываемой) — и это и есть патчинг ядра, латающий дыру.
Я вот с этим не понимаю. NtQueueApcThread c вызовом чего угодно кроме RtlDispatchAPC не имеет смысла (ну, возможно, есть еще 1-2 функции — в общем, передавать надо не адрес а ID функции вызываемой)

Уверен, что функцией NtQueueApcThread пользуются не только разработчики MS'а и писатели малвари.


и это и есть патчинг ядра, латающий дыру.

И ломает обратную совместимость.


У ядра нет дыры. Что бы выполнить NtQueueApcThread нужно обладать правом THREAD_SET_CONTEXT для нити целевого процесса. Если вы можете открыть целевую нить с такой маской доступа, то можно выполнить любой код, который загружен в адресное пространство процесса.


На x64, например, первые 4-е параметра передаются в регистрах, поэтому обладая THREAD_SET_CONTEXT можно выполнить тот же самый вызов с тремя параметрами в целевом процессе функцией SetThreadContext.


Задача детекта малвари по поведению — задача не ядра, я Security-продуктов. Именно как обход существующих Security-решений и позиционируется новая техника (https://breakingmalware.com/injection-techniques/atombombing-brand-new-code-injection-for-windows/):


I started poking around to see how hard it would be for a threat actor to find a new method that security vendors are unaware of and bypasses most security products.
QueueUserAPC — API.
Nt* — Internal
> В силу природы данной техники, к сожалению, вряд ли он может быть пропатчен.

Откуда следует такой вывод? В ангоязычных источниках вроде пишут только «практически не обнаруживается имеющимися на данный момент решениями».
Примерное описание, взято отсюда. Там же есть комменты, в которых говорят, что эта техника используется уже давно.

Функции добавления и чтения атома:
ATOM WINAPI GlobalAddAtom(
  _In_ LPCTSTR lpString
);

UINT WINAPI GlobalGetAtomName(
  _In_  ATOM   nAtom,
  _Out_ LPTSTR lpBuffer,
  _In_  int    nSize
);


Функция асинхронного вызова процедуры в user-mode (ее можно выполнить из другого процесса).
DWORD WINAPI QueueUserAPC(
_In_ PAPCFUNC  pfnAPC, 
_In_ HANDLE    hThread, 
_In_ ULONG_PTR dwData
);

VOID CALLBACK APCProc(
  _In_ ULONG_PTR dwParam
);


В atom name записывается код эксплойта. Функции в удаленном процессе вызываются через механизм APC. Нужно иметь права доступа THREAD_SET_CONTEXT на hThread.

Напрямую передать pfnAPC = GlobalGetAtomName нельзя, так как pfnAPC принимает 1 параметр, а GlobalGetAtomName 3. Но QueueUserApc использует NtQueueApcThread, которая вызывает свою callback-функцию, которая принимает 3 параметра. То есть, через NtQueueApcThread можно вызвать GlobalGetAtomName в другом процессе, которая запишет имя атома куда-нибудь в RW область этого процесса.

RW область можно найти например в конце секции данных kernelbase.dll.

Потом надо выделить память с правами RWX и скопировать туда код из области RW. Это можно сделать с помощью ROP Chain (return-oriented programming). Это когда заранее подготавливается стек с адресами возврата сразу на нужные функции, и ret из каждой функции делает переход сразу на начало другой. Последний ret переходит на начало эксплойта.

Стек также можно подготовить в RW области и вызвать NtSetContextThread для изменения ESP, тоже через APC. Она принимает 2 параметра, а не 3, и текущий стек должен сломаться, но это неважно, так как можно задать и нужный EIP.

Восстановление выполнения кода делается так же, как оно происходит при APC, с помощью вызова ZwContinue.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий