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 kolejną techniką uzyskiwania persistence w systemach Windows:
- WMI Event Subscription
Powyższa metoda jest nieco bardziej skomplikowana i może być trudniejsza w detekcji od serwisów i skryptów.
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, że za pomocą 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 za pomocą WMI jest całkiem proste.
Persistence za pomocą eventów WMI możemy uzyskać na dwa sposoby – z wykorzystaniem plików języka MOF (Managed Object Format) i kompilatora mofcomp.exe lub za pomocą zwykłego powershella. Język MOF opisuje klasy standardu CIM (czyli klasy WMI, który jest Microsoftową implementacją CIM), za pomocą 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.
Elevated: WMI Events Subscription – wstęp do praktyki
Stworzenie persistence za pomocą WMI polega w dużym skrócie na stworzeniu instancji klasy __EventFilter, która jest triggerem, czyli 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 CommandLineEventConsumer, 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 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ń za pomocą WMI możemy zapytać w następujący sposób:
Listując kolejne wydarzenia z dziennika zdarzeń widzimy jednak, że 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.
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. Jeżeli 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.
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 – jeżeli pojawi się nowy event w Dzienniku Zdarzeń, to pojawi się nowa instancja klasy Win32_NTLogEvent co wygeneruje zdarzenie __InstanceCreationEvent. Ponadto, za pomocą 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 za pomocą 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:
- Get-WmiObject -Namespace root\Subscription -Class __EventFilter
- Get-WMIObject -Namespace root\Subscription -Class CommandLineEventConsumer
- Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding
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.
Dla Blue Teamów – na poniższej stronie macie numery eventów, które należy śledzić, aby odnaleźć ten typ persistence w Waszej infrastrukturze.
Zakończenie
Po omówieniu Persistence przez WMI został nam już tylko COM Hijacking, ale czuje, że ten temat zasługuje na oddzielny wpis. W niedługim czasie postaram się również pokazać coś bardziej przyziemnego – RBAC, czyli Resource Based Constrained Delegation na przykładzie challengu z TryHackme. Stay tuned!
- https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-process
- https://docs.microsoft.com/en-us/windows/win32/wmisdk/determining-the-type-of-event-to-receive