Из­бежать обна­руже­ния полез­ной наг­рузки анти­виру­сами — важ­ней­шая задача не толь­ко вирусо­писа­телей, но и пен­тесте­ров и учас­тни­ков red team. Для это­го сущес­тву­ют раз­личные тех­ники. Сегод­ня мы под­робно рас­смот­рим две из них: Herpaderping и Ghosting. О двух дру­гих методи­ках — Hollowing и Doppelgänging — мож­но почитать в статье «Мас­киру­ем запуск про­цес­сов при помощи Process Doppelgänging».

Для прос­тоты в наших экспе­римен­тах мы будем исполь­зовать Microsoft Defender и Mimikatz.

warning

Статья име­ет озна­коми­тель­ный харак­тер и пред­назна­чена для спе­циалис­тов по безопас­ности, про­водя­щих тес­тирова­ние в рам­ках кон­трак­та. Автор и редак­ция не несут ответс­твен­ности за любой вред, при­чинен­ный с при­мене­нием изло­жен­ной информа­ции. Рас­простра­нение вре­донос­ных прог­рамм, наруше­ние работы сис­тем и наруше­ние тай­ны перепис­ки прес­леду­ются по закону.

 

Особенности процессов

Как анти­вирус узна­ет, что в сис­теме был запущен какой‑либо про­цесс? Microsoft дает воз­можность раз­работ­чикам анти­вирус­ных решений получать через API нуж­ные им события (нап­ример, PsSetCreateProcessNotifyRoutineEx). Ког­да соз­дает­ся про­цесс, Microsoft Defender (да и все осталь­ные анти­виру­сы) сра­зу узна­ет об этом, получив соот­ветс­тву­ющий callback. Теперь‑то он может про­инспек­тировать исполня­емый файл и сде­лать вывод, раз­решить этот про­цесс или нет (опус­тим этап ста­тичес­кого ана­лиза).

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

 

Важно понимать

Ис­полня­емый файл — это не про­цесс. Исполня­емый файл может быть свя­зан со мно­жес­твом про­цес­сов (в Task Manager мож­но лег­ко прос­ледить, сколь­ко про­цес­сов свя­зано, нап­ример, с RuntimeBroker.exe или svchost.exe). Каж­дый про­цесс обя­затель­но будет свя­зан с каким‑либо PE-фай­лом (.exe, .dll и дру­гие). При этом про­цес­сы пре­дос­тавля­ют ресур­сы, необ­ходимые для выпол­нения прог­раммы.

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

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

 

Создание процесса

Рас­смот­рим соз­дание про­цес­са по шагам.

  1. Сна­чала мы получа­ем дес­крип­тор (handle) для исполня­емо­го фай­ла, который запус­каем, нап­ример так: hFile = CreateFile(“C:\Windows\System32\svchost.exe”).
  2. Соз­даем image section (нап­ример, hSection = NtCreateSection(hFile, SEC_IMAGE)). Image section пред­став­ляет собой осо­бый раз­дел и слу­жит для отоб­ражения фай­ла (или час­ти фай­ла) в память. Раз­дел соот­ветс­тву­ет PE-фай­лам и может быть соз­дан толь­ко в них.
  3. Соз­даем про­цесс в image section (нап­ример, hProcess = NtCreateProcessEx(hSection)).
  4. Наз­нача­ем аргу­мен­ты и перемен­ные сре­ды (нап­ример, CreateEnvironmentBlock/NtWriteVirtualMemory).
  5. Соз­даем поток для выпол­нения про­цес­са (нап­ример, NtCreateThreadEx).

Важ­ный момент: про­цес­сы запус­кают­ся из исполня­емых фай­лов, но информа­ция внут­ри исполня­емо­го фай­ла может менять­ся отно­ситель­ного того, что находит­ся в image section (так как она кеширу­ется memory manager).

 

Сканирование процесса в поисках зловреда

Как уже было ска­зано, анти­виру­сы могут получать уве­дом­ления о событи­ях соз­дания про­цес­сов и потоков (PsSetCreateProcessNotifyRoutineEx и PsSetCreateThreadNotifyRoutineEx).

Выг­лядит это при­мер­но так:

typedef struct _PS_CREATE_NOTIFY_INFO {
SIZE_T Size;
union {
ULONG Flags;
struct {
ULONG FileOpenNameAvailable : 1;
ULONG IsSubsystemProcess : 1;
ULONG Reserved : 30;
};
};
HANDLE ParentProcessId;
CLIENT_ID CreatingThreadId;
struct _FILE_OBJECT *FileObject;
PCUNICODE_STRING ImageFileName;
PCUNICODE_STRING CommandLine;
NTSTATUS CreationStatus;
} PS_CREATE_NOTIFY_INFO, *PPS_CREATE_NOTIFY_INFO;

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

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

Подписаться
Уведомить о
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии