Analiza złośliwego oprogramowania niszczącego dane  - CaddyWiper

W ostatnim czasie mogliśmy zaobserwować zwiększoną ilość ataków z wykorzystaniem złośliwego oprogramowania typu wiper. Do głównych zadań tego rodzaju szkodliwego oprogramowania należy usuwanie lub niszczenie danych. Wipery mogą realizować złośliwą aktywność na kilka różnych sposobów, m.in. usuwając pliki lub nadpisując ich zawartość. W przypadku nadpisania, ingerencja
w całość lub istotną część plików sprawia, że stają się one bezużyteczne. CaddyWiper to czwarte z kolei oprogramowanie niszczące dane dotykające ukraińskich organizacji, którego działalność obserwowano od początku 2022 r. Wykorzystanie wipera odnotowano w ukraińskim sektorze finansowym i energetycznym. Ostatni z wymienionych przypadków[i] dotyczył użycia CaddyWipera
w kontekście złośliwego oprogramowania Industroyer2, wymierzonego w ukraińską sieć energetyczną[ii]. Wcześniej obserwowane ataki wiperów dotyczyły kampanii malware WhisperGate[iii], HermeticWiper[iv] oraz IsaacWiper[v].

 

CaddyWiper

Pierwsze doniesienia o złośliwym oprogramowaniu CaddyWiper pojawiły się 14 marca 2022 roku. Nazwa wydaje się pochodzić od oryginalnej nazwy pliku, w zależności od próbek caddy.exe lub caddy1.exe. CaddyWiper posiada format Portable Executable (PE), a proces niszczenia danych dokonuje się poprzez wyzerowanie początkowych 0xa00000 bajtów wybranych plików. Dodatkowo, złośliwe oprogramowanie niszczy układ partycji na 10 pierwszych dyskach fizycznych (od \\.\PHYSICALDRIVE9 do \\.\PHYSICALDRIVE0).

 

Dane ogólne

Poniższa analiza dotyczy próbki o sumie kontrolnej SHA256: a294620543334a721a2ae8eaaf9680a0786f4b9a216d75b55cfd28f39e9430ea i nazwie pliku caddy1.exe. Analizowany plik to 32 bitowa aplikacja, rozpoznawana jako posiadająca interfejs graficzny (GUI32).

Zrzut wyników otrzymanych z programu Detect It Easy [1]

 

Na zrzucie ekranu zauważalna jest zastanawiająco mała lista importów – widoczna jest tylko jedna biblioteka i tylko jedna funkcja. Warto zauważyć, że w trakcie analizy wykryta została bardzo mała ilość łańcuchów znakowych.

Tablica importów (import table) [2]

 

Lista łańcuchów znakowych [3]

 

Analiza statyczna kodu

Pierwszą charakterystyczną cechą jest brak kodu inicjalizującego CRT i ustawienia Security Cookie - program od razu rozpoczyna się od właściwego kodu.

Część właściwa funkcji entry przedstawiona za pomocą pseudokodu [4]

 

Widoczna jest duża ilość zmiennych lokalnych, z których część już na samym początku jest inicjalizowana jednobajtowymi wartościami.

Zmienne lokalne zadeklarowane na stosie funkcji [5]

 

Uwagę zwraca fakt, że widoczne wartości pochodzą z małego przedziału oraz to, że sprawiają wrażenie bycia pojedynczymi znakami pewnych ciągów liter - pierwszy jest najprawdopodobniej zapisany
w kodowaniu UTF-16 (2-bajtowe znaki, z czego jeden bajt posiada wartość null) oraz ASCII.

Obydwa łańcuchy znakowe są zakończone zerem (null-terminated string).

[6]

 

Stackstrings i Ghidra

W celu ułatwienia analizy (w tym przypadku w programie Ghidra) możemy zmienić typ pierwszego znaku w ciągu na tablicę znaków odpowiadającą jej długości przy użyciu opcji retype variable. Dzięki temu prostemu zabiegowi kod staje się dużo czytelniejszy.

[7]

 

[8]

 

Funkcjonalność

Działanie programu można umownie podzielić na 3 etapy:

  1. Uszkodzenie wszystkich plików z lokalizacji C:\\Users (wywołanie funkcji 0x004022a0 pod adresem 0x00401179)
  2. Uszkodzenie wszystkich plików z dysków od D: do Z: (wielokrotne wywoływanie w pętli funkcji 0x004022a0 pod adresem 0x004011ad)
  3. Uszkodzenie układu partycji na dyskach, zaczynając od PHYSICALDRIVE9 kończąc na PHYSICALDRIVE0 (funkcja 0x004011d0 wywołana z adresu 0x004011bf)

 

Zdekompilowany fragment funkcji entry z opisanymi funkcjonalnościami i oznaczonymi wartościami łańcuchów znakowych [9]

 

Krótki opis funkcjonalności najważniejszych funkcji programu:

Funkcja 0x00401530 - wyszukiwanie adresu funkcji w podanej bibliotece

Funkcja 0x004022a0 - niszczenie (poprzez nadpisanie) wszystkich plików w danej lokalizacji

  • 0x00402a80 - łączenie ciągów znaków
  • 0x00401a10 - przejmowanie własności plików
  • 0x00402b10 - zerowanie pamięci

Funkcja 0x004011d0 - niszczenie układu partycji

 

Dynamiczne ładowanie bibliotek DLL i wyszukiwanie adresów funkcji systemowych

Każda z funkcji przed rozpoczęciem właściwego działania wyszukuje adres funkcji z bibliotek DLL za pomocą dedykowanej funkcji 0x00401530 przyjmującej 2 parametry - nazwę biblioteki DLL oraz nazwę szukanej funkcji.

Znaleziony adres jest odkładany na stosie w celu późniejszego użycia.

[10]

Dodatkowo, wszystkie potrzebne biblioteki są ładowane na początku funkcji entry i wywołania LoadLibraryA.

 

Funkcja nadpisująca pliki - 0x004022a0

Wymieniona funkcja wyszukuje wszystkie pliki i foldery w ścieżce podanej jako parametr. W tym celu wywoływane jest FindFirstFileA (pod adresem 0x0040284d), a każdy kolejny plik z aktualnego folderu zwracany jest po użyciu FindNextFileA (0x00402a5f).

W przypadku pliku następuje kolejno: przejęcie go na własność (funkcją 0x00401a10), zadeklarowanie miejsca na stercie poprzez LocalAlloc (0x004029e1) i wyzerowanie zadeklarowanej w ten sposób pamięci funkcją 0x00402b10 (0x004029fb). W dalszej kolejności ma miejsce nadpisanie pierwszych 0xa00000 bajtów pliku lub jego całości (w zależności od tego, która wartość jest mniejsza) za pomocą funkcji WriteFile (0x00402a5f).

Jeśli złośliwe oprogramowanie natrafi na folder, jest on weryfikowany pod kątem bycia katalogiem bieżącym, ukrytym lub systemowym. Jeśli wymienione warunki nie są spełnione, funkcja wywołuje samą siebie ze ścieżką aktualnie sprawdzanego folderu (przeszukiwanie dokonuje się rekurencyjnie).

Fragment funkcji odpowiedzialnej za niszczenie danych [11]

 

Niszczenie układu partycji

Do niszczenia danych o partycjach służy funkcja 0x004011d0.

Otwiera ona uchwyt (handle) do dysku za pomocą funkcji CreateFileW (0x00401445) - należy przy tym pamiętać, że funkcje CreateFileA i CreateFileW są dedykowane zarówno do tworzenia plików, jak i otrzymywania uchwytów do plików już istniejących  (zgodnie z dokumentacją MSDN).

Kolejno wywoływana jest funkcja IOCTL - DeviceIoControl z parametrami IOCTL_DISK_SET_DRIVE_LAYOUT_EX, wyzerowaną pamięcią na stercie local_7f4 i wielkością zapisu 0x780.

Powyższa procedura jest wykonywana w pętli dla dysków fizycznych (od PHYSICALDRIVE9 do PHYSICALDRIVE0).

[12]

 

 

[i] Zob. https://cert.gov.ua/article/39518

[ii] Zob. https://www.welivesecurity.com/2022/04/12/industroyer2-industroyer-reloaded/

[iii] Zob. https://medium.com/s2wblog/analysis-of-destructive-malware-whispergate-targeting-ukraine-9d5d158f19f3

[iv] Zob. https://www.cisa.gov/uscert/ncas/alerts/aa22-057a

[v] Zob. https://securityintelligence.com/posts/new-wiper-malware-used-against-ukranian-organizations/