Kilka słów o persistence w systemie Windows – cz. 2

how2hax.pl 2 lat temu

Ostatnio obiecałem Wam kontynuację wątku o persistence w systemach Windows. W poprzednim wpisie opisałem dwie, dość proste metody:

  • Logon Script
  • Windows Service

Obydwie mają odzwierciedlenie w tablicy MITRE, ale moim zdaniem nie należą do najbardziej wyrafinowanych. Niemniej, zarówno skrypty logowania jak i persistence z wykorzystaniem Windowsowych serwisów były powszechnie wykorzystywane przez znane grupy APT, m.in. Kimsuky z Korei Północnej (obydwie techniki). W dzisiejszym wpisie chciałbym podzielić się z Wami kolejnymi technikami uzyskiwania persistence w systemach Windows:

  • Com Hijacking
  • WMI Event Subscription

Powyższe są nieco bardziej skomplikowane i mogą być nieco trudniejsze w detekcji przez zespoły Blue Team. Zacznijmy od Eventów Windows Microsoft Instrumentation.

Elevated: WMI Events Subscription – kilka słów teorii

WMI jest zestawem protokołów, który pozwala na monitorowanie i zarządzanie elementami zarówno lokalnego jak i zdalnego hosta. Część z Was pewnie wie, iż dzięki WMI (Windows Management Instrumentation) możemy wykonać również lateral movement poprzez wykonanie programów na zdalnym hoście, możemy również uzyskać dostęp do różnych informacji zarówno na lokalnym jak i zdalnym systemie. WMI opiera się na hierarchicznej strukturze przestrzeni nazw i klas, np. klasa „win32_Process” odpowiada za procesy, a win32_service za serwisy. Za tworzenie nowych procesów odpowiada np. metoda Create klasy win32_Process1, widzimy więc tu czysto obiektowe podejście. Choć sama idea WMI jako narzędzia umożliwiającego zarządzanie elementami systemu w rozproszonym środowisku może wydawać się nieco zawiła, to uzyskanie persistence dzięki WMI jest całkiem proste.

Opis klasy Win32_Process

Persistence dzięki eventów WMI możemy uzyskać na dwa sposoby – z wykorzystaniem plików języka MOF (Managed Object Format) oraz kompilatora mofcomp.exe lub dzięki zwykłego powershella. Język MOF opisuje klasy standardu CIM (czyli klasy WMI, który jest Microsoftową implementacją CIM), dzięki języka MOF możemy stworzyć nową klasę i przypisać jej metody i inne parametry, a także stworzyć instancje (obiekty) istniejących już klas.

Możemy zarządzać elementami systemu dzięki instancji klas WMI (na obrazku Win32_CDROMDrive).

Elevated: WMI Events Subscription – wstęp do praktyki

Stworzenie persistence dzięki WMI polega w dużym skrócie na stworzeniu instancji klasy __EventFilter, która jest triggerem, która definiuje nam warunki przy których ma zostać wykonana pewna czynność. Tymi warunkami może być np. otworzenie notatnika, programu Word, zainicjowanie ruchu sieciowego na konkretny port czy restart stacji. Potem, należy stworzyć instancje klasy __EventConsumer, która definiuje nam czynności, które mają się wydarzyć przy spełnieniu wcześniej opisanego warunku. Ostatnim etapem jest stworzenie obiektu klasy __FilterToConsumerBinding, która łączy, mapuje ze sobą pozostałe dwie instancje. Spróbujmy sobie więc stworzyć persistence, który polega na monitorowaniu logowania się użytkownika do systemu. Tradycyjnie, za ten event odpowiada EventCode 4624. O elementy dziennika zdarzeń dzięki WMI możemy zapytać w następujący sposób:

Listując kolejne wydarzenia z dziennika zdarzeń widzimy jednak, iż dziennik pełny jest eventów niezwiązanych z interaktywnym logowaniem użytkowników. Najczęściej widzimy logowania konta SYSTEM oraz logowania konta hosta, które wynikają z wewnętrznych mechanizmów Windowsa.

Jeden z wielu eventów generowanych przez wewnętrzne mechanizmy systemu Windows

Wprawdzie moglibyśmy ograniczyć się do wyszukania nazwy konta użytkownika w polu „Message”, ale wtedy uzyskamy persistence tylko i wyłącznie w sytuacji w której zaloguje się konkretny użytkownik – choć to też może mieć swoje zastosowanie. o ile chcemy wykonać jakieś działanie w przypadku każdego interaktywnego logowania warto przeszukać event pod kątem wystąpienia stringu „User32”, który znajduje się wtedy w polu „Logon Process”.

Okej, znaleźliśmy już sposób na przeszukanie Dziennika Zdarzeń pod kątem interaktywnych logowań użytkowników. W ten sam sposób możemy napisać triggery dla innych, dowolnych zdarzeń. Interesuje nas uptime systemu? Nic prostszego, informacje o tym jak długo system jest uruchomiony znajdziemy dzięki klasie Win32_PerfFormattedData_PerfOS_System.

Znalezienie informacji o uptime systemu

Intrinsic Events – czyli jak śledzić zmiany w danych WMI

Z reguły nie chcemy triggerować naszych payloadów w każdej sytuacji, kiedy w Event Logach będą informacje o zalogowanych użytkownikach, ponieważ taka sytuacja będzie miała miejsce zawsze. Interesuje nas zmiana pewnych danych w logach lub pojawienie się nowych. I tu znów z pomocą przychodzi nam dokumentacja Microsoftu i pojęcie tzw. Intrinsic Events2 (pol. wewnętrzne eventy (?)). Intrinsic Events to zdarzenia, które są generowane przy każdej zmianie instancji czy klasy WMI. Innymi słowy – o ile pojawi się nowy event w Dzienniku Zdarzeń, to pojawi się nowa instancja klasy Win32_NTLogEvent co wygeneruje zdarzenie __InstanceCreationEvent. Ponadto, dzięki słowa kluczowego „WITHIN” możemy wskazywać w zapytaniach WQL czas pomiędzy kolejnymi odpytaniami WMI.

Elevated: WMI Events Subscription – praktyka

Stworzenie persistence zacznijmy od wygenerowania triggera – czyli instancji klasy __EventFilter. Przykładowa instancja, która śledzi logowania kolejnych interaktywnych użytkowników w systemie wygląda następująco:

Następnie powinniśmy stworzyć instancję klasy CommandLineEventConsumer, która odpowiada za czynności, które mają zostać wykonane, gdy zostanie wywołany trigger.

Pod zmienną $StagerPayload powinna kryć się komenda, którą chcemy uruchomić gdy zostanie wygenerowany interesujący nas Event. Może być to uruchomienie biblioteki .dll dzięki rundll32.exe, bezpośrednie odwołanie do pliku wykonywalnego lub jakiekolwiek inne metody code execution jakie znacie.

Ostatnim etapem jest utworzenie instancji klasy __FilterToConsumerBinding, czyli zamapowania czynności do triggera, który ma ją wywołać.

Po wykonaniu powyższego kodu powinniśmy mieć zarejestrowane w systemie obiekty klas __EventFilter, CommandLineEventConsumer oraz __FilterToConsumerBinding. Aby sprawdzić je po kolei należy wykonać polecenia:

  1. Get-WmiObject -Namespace root\Subscription -Class __EventFilter
  2. Get-WMIObject -Namespace root\Subscription -Class CommandLineEventConsumer
  3. Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding
__EventFillter czyli trigger
Consumer, czyli czynność, która ma zostać wykonana w przypadku wyzwolenia triggera
__FilterToConsumerBinding, czyli zamapowanie czynności do triggera

Jak sami widzicie na powyższych slajdach, nazwałem swój filtr „Fileless WMI Persistence login”. Po pierwsze – żaden z niego fileless, ponieważ consumerem jest zwykły złośliwy plik .exe. Po drugie – w działaniach RT proponuję unikać sformułowań „Persistence”, bo rzuca się to w oczy prawie tak samo jak „fun.exe”.

Elevated: WMI Events Subscription – czy to w ogóle działa?

Po udanym logowaniu udało nam się otrzymać połączenie do serwera CS.

Używając programu Autoruns, możemy dowiedzieć się czy w naszym systemie mamy zarejestrowane Eventy WMI.

Wynik działania programu Autoruns

Dla Blue Teamów – na poniższej stronie macie numery eventów, które należy śledzić, aby odnaleźć ten typ Persistence w swoje infrastrukturze.

https://in.security/2019/04/03/an-intro-into-abusing-and-identifying-wmi-event-subscriptions-for-persistence

Zakończenie

Po omówieniu Persistence przez WMI został nam już tylko COM Hijacking, ale czuje, iż ten temat zasługuje na oddzielny wpis. W niedługim czasie postaram się pokazać coś bardziej przyziemnego – RBAC, czyli Resource Based Constrained Delegation na przykładzie challengu z TryHackme. Stay tuned!

  1. https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-process
  2. https://docs.microsoft.com/en-us/windows/win32/wmisdk/determining-the-type-of-event-to-receive
Idź do oryginalnego materiału