Вечеринка у бассейна. Применяем технику PoolParty для инъекции в процессы

Содержание статьи

  • Windows Thread Pools
  • Захват целевого дескриптора
  • Модифицируем start routine
  • Выводы

Не­дав­но появил­ся новый вид инжектов в легитим­ные про­цес­сы. Называ­ется он PoolParty и исполь­зует Windows Thread Pools — мас­штаб­ный и слож­ный механизм управле­ния потока­ми в Windows. Пред­лагаю разоб­рать­ся, как устро­ен этот механизм и как его мож­но исполь­зовать в пен­тестер­ских целях.

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

warning

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

 

Windows Thread Pools

Ме­ханизм Windows Thread Pools приз­ван зна­читель­но упростить прог­раммис­там управле­ние потока­ми. Под капотом реша­ются задачи асин­хрон­ного вза­имо­дей­ствия и управле­ния про­изво­дитель­ностью при помощи пере­исполь­зования сущес­тву­ющих потоков — это сок­раща­ет зат­раты ресур­сов на их соз­дание и унич­тожение. Заод­но решены проб­лемы с оче­редя­ми потоков и еще вагоном мел­ких тон­костей, которые бы све­ли с ума прог­раммис­та, если бы тот пытал­ся реали­зовать все это самос­тоятель­но.

Код, управля­ющий пулами потоков, пре­иму­щес­твен­но рас­полага­ется в режиме поль­зовате­ля (ntdll.dll), и толь­ко неболь­шая его часть находит­ся в ядре — поэто­му не при­ходит­ся тра­тить ресур­сы на час­тое перек­лючение кон­тек­стов меж­ду ядром и юзер­спей­сом.

Вот основные узлы Windows Thread Pools:

  • ра­бочая фаб­рика (Worker Factory), которая управля­ет соз­дани­ем и уда­лени­ем новых потоков;
  • ра­бочие оче­реди:
    • оче­редь задач (task queue) — задачи, которые переда­ются в пул. Эти задачи могут быть как быс­тры­ми (выпол­нять­ся в течение корот­кого вре­мени), так и более дли­тель­ными. Пул потоков авто­мати­чес­ки мас­шта­биру­ется — если задач мно­го, пул может соз­дать допол­нитель­ные потоки, что­бы спра­вить­ся с наг­рузкой;
    • оче­редь вво­да‑вывода (I/O completion queue) выпол­няет задачи, свя­зан­ные с опе­раци­ями вво­да‑вывода, такие как фай­ловые опе­рации или сетевые зап­росы;
    • оче­редь тай­мера (timer queue) поз­воля­ет выпол­нять задачи через опре­делен­ные про­межут­ки вре­мени или в задан­ное вре­мя.

Имен­но эти час­ти механиз­ма Thread Pools наибо­лее инте­рес­ны с точ­ки зре­ния экс­плу­ата­ции тех­ники PoolParty.

На­до ска­зать, что все про­цес­сы, работа­ющие в Windows, исполь­зуют Thread Pools по умол­чанию. Давай поп­робу­ем в этом убе­дить­ся экспе­римен­таль­но — запус­тим Process Explorer, выберем любой про­цесс и перей­дем на вклад­ку Handles.

Фаб­рики в про­цес­се svchost.exe

Как видишь, про­цесс svchost.exe исполь­зует Worker Factory, а зна­чит, механизм Thread Pools акти­вен.

Для демонс­тра­ции тех­ники PoolParty мы поп­робу­ем ата­ковать рабочие фаб­рики. А для это­го нуж­но понять, как они соз­дают­ся.

NTSTATUS NTAPI NtCreateWorkerFactory(_Out_ PHANDLE WorkerFactoryHandleReturn,_In_ ACCESS_MASK DesiredAccess,_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,_In_ HANDLE CompletionPortHandle,_In_ HANDLE WorkerProcessHandle,_In_ PVOID StartRoutine,_In_opt_ PVOID StartParameter,_In_opt_ ULONG MaxThreadCount,_In_opt_ SIZE_T StackReserve,_In_opt_ SIZE_T StackCommit);

NtCreateWorkerFactory — фун­кция NTAPI, которая соз­дает рабочую фаб­рику Thread Pools. Обра­ти вни­мание на инте­рес­ные аргу­мен­ты — WorkerProcessHandle и StartRoutine.

StartRoutine — это ука­затель на код, который будет выпол­нен фаб­рикой при запус­ке нового потока, а WorkerProcessHandle — дес­крип­тор про­цес­са, в кон­тек­сте которо­го будут выпол­нять­ся рабочие потоки. Это может быть дес­крип­тор текуще­го про­цес­са или дру­гого для рас­пре­делен­ной обра­бот­ки. А что, если поп­робовать модифи­циро­вать код StartRoutine, что­бы он выпол­нял наш пей­лоад, таким обра­зом зас­тавляя фаб­рику работать на нас?

Но до непос­редс­твен­ной модифи­кации StartRoutine нуж­на неболь­шая под­готов­ка.

 

Захват целевого дескриптора

Вза­имо­дей­ствие с эле­мен­тами Thread Pools реали­зует­ся через дес­крип­торы. Соот­ветс­твен­но, для получе­ния дос­тупа к рабочей фаб­рике целево­го про­цес­са нуж­но сна­чала най­ти ее хендл и зах­ватить его, исполь­зуя фун­кцию WinAPI DuplicateHandle.

Источник: xakep.ru

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *