Stan zagrożeń w internecie znajduje się obecnie na poziomie standardowym. Nie występują duże epidemie a eksperci z Kaspersky Lab nie zanotowali żadnych poważnych incydentów związanych z bezpieczeństwem. Poziom zagrożenia: 1

Tajemnica Szkieletu Duqu

Dodany 12 marca 2012, 12:47 CET
Tagi:

Podczas analizy komponentów Duqu odkryliśmy interesującą anomalię w głównym komponencie odpowiedzialnym za jego logikę biznesową – szkodliwą funkcję (Payload DLL). Chcielibyśmy podzielić się naszymi odkryciami i poprosić o pomoc w zidentyfikowaniu kodu.

Struktura kodu

Na pierwszy rzut oka Payload DLL wygląda jak zwykły plik Windows PE DLL skompilowany przy użyciu Microsoft Visual Studio 2008 (wersja linkera 9.0). Kod punktu wejścia jest całkowicie standardowy, jest też jedna funkcja eksportowana przez liczebnik porządkowy 1, która również wygląda jak MSVC++. Funkcja ta jest wywoływana z PNF DLL i w rzeczywistości stanowi „główną” funkcję, która implementuje całą logikę kontaktowania się z serwerami C&C, otrzymując dodatkowe moduły funkcji szkodliwej oraz wykonując je. Najciekawsze jest to, w jaki sposób logika ta została zaprogramowana i jakie wykorzystano narzędzia.

Sekcja kodu Payload DLL jest typowa dla kodu binarnego, który został stworzony z kilku kawałków kodu. Składa się z „plastrów” kodu, które początkowo mogły zostać skompilowane w osobne pliki obiektowe, które następnie zostały połączone w jedną bibliotekę DLL. Większość z nich można znaleźć w dowolnym programie C++, jak funkcje STL (Standard Template Library), funkcje biblioteki dynamicznej oraz kod napisany przez użytkownika, z wyjątkiem największego plastra, który zawiera większość kodu odpowiedzialnego za interakcję z serwerem C&C.


Struktura sekcji kodu pliku Payload DLL

Plaster ten różni się od innych, ponieważ nie został skompilowany ze źródeł C++. Nie zawiera żadnych odnośników do standardowych ani napisanych przez użytkownika funkcji C++, jednak bez wątpienia jest to kod obiektowy. Nazwaliśmy go Szkieletem Duqu.

Szkielet

Funkcje

Kod implementujący Szkielet Duqu posiada kilka wyróżniających go cech:

  • Wszystko ma postać obiektów
  • Tablica funkcji jest umieszczona bezpośrednio w instancji klasy i może zostać zmodyfikowana po skonstruowaniu
  • Nie ma rozróżnienia pomiędzy klasami narzędzi (powiązane listy, hashe) a kodem napisanym przez użytkownika
  • Obiekty komunikują się przy użyciu wywołań metod, kolejek opóźnionego wykonania, a nawet wywołań zwrotnych spowodowanych wydarzeniem
  • Nie ma odwołań do funkcji biblioteki dynamicznej, zamiast tego wykorzystywane jest natywne API Windows

Obiekty

Wszystkie obiekty są instancjami pewnej klasy. Zidentyfikowaliśmy 60 klas. Każdy obiekt jest tworzony przy użyciu funkcji konstruktora, która przydziela pamięć, wypełnia tablicę funkcji i inicjuje składniki.


Funkcja konstruktora dla klasy listy powiązanej.

Struktura każdego obiektu zależy od jego klasy. Niektóre klasy wydają się mieć binarne kompatybilne tablice funkcji, nic jednak nie wskazuje na to, że posiadają wspólne klasy macierzyste (jak w innych językach obiektowych). Ponadto, lokalizacja tablicy funkcji nie jest stała: niektóre klasy mają ją na pozycji 0 instancji, inne nie.


Struktura obiektu listy powiązanej. Pierwsze 10 pól to wskazania na funkcje składowe.

Obiekty są niszczone przez odpowiednie funkcje destruktora. Funkcje te zwykle niszczą wszystkie obiekty, do których odwołują się pola składowe, i zwalniają wykorzystaną pamięć.

Odwoływanie do funkcji składowych może następować poprzez tablicę funkcji obiektu (tak jak funkcji „wirtualnych” w C++) lub mogą one być wywoływane bezpośrednio. W większości języków obiektowych funkcje składowe otrzymują parametr „this”, który odwołuje się do instancji obiektu i istnieje konwencja, która określa lokalizację parametru – w rejestrze lub w stosie. W przypadku klas Szkieletu Duqu jest inaczej – mogą one otrzymać parametr „this” w dowolnym rejestrze lub stosie.


Funkcja składowa listy powiązanej otrzymuje parametr “this” na stosie

Szkielet oparty na zdarzeniach

Struktura i implementacja obiektów w Szkielecie Duqu zdecydowanie nie jest natywna względem C++, który został wykorzystany do zaprogramowania reszty trojana. Można wyróżnić jeszcze bardziej interesującą cechę tego szkieletu występującą w całym kodzie: jest on oparty na zdarzeniach.

Istnieją specjalne obiekty, które implementują model oparty na zdarzeniach:

  • obiekty zdarzeń oparte na natywnych uchwytach API Windows
  • obiekty kontekstu wątków, które prowadzą listy zdarzeń i kolejki opóźnionego wykonania
  • obiekty odwołania zwrotnego, które są powiązane ze zdarzeniami
  • monitory zdarzeń stworzone przez każdy kontekst wątków w celu monitorowania zdarzeń oraz wykonywania obiektów odwołania zwrotnego
  • zbiornik kontekstu wątków zarządza listą aktywnych wątków i zapewnia dostęp do obiektów według kontekstu wątku

Ten model oparty na zdarzeniach przypomina Objective C oraz jego funkcje przekazywania wiadomości, jednak kod nie posiada żadnych bezpośrednich odniesień do tego języka, ani nie wygląda jakby został skompilowany przy pomocy znanych kompilatorów Objective C.


Model oparty na zdarzeniach Szkieletu Duqu

Każdy obiekt kontekstu wątków może rozpocząć „główną pętlę”, która szuka i przetwarza nowe pozycje na listach. Większość kodu Duqu opiera się na tej samej zasadzie: tworzy obiekt, wiąże kilka odwołań zwrotnych z wewnętrznymi lub zewnętrznymi zdarzeniami i wraca. Następnie uchwyty odwołań zwrotnych są wykonywane przez obiekt monitorowania zdarzeń, który jest tworzony w każdym kontekście wątków.

Poniżej przykład pseudokodu dla obiektu portu:

SocketObjectConstructor { 
NativeSocket = socket();
SocketEvent = new MonitoredEvent(NativeSocket);
SocketObjectCallback = new ObjectCallback(this, SocketEvent, OnCallbackFunc);
connect(NativeSocket, ...);
}
OnCallbackFunc {
switch(GetType(Event)) {
case Connected: ...
case ReadData: ...
...}
}

Wnioski

  • Szkielet Duqu wydaje się być napisany w nieznanym języku programistycznym.
  • W przeciwieństwie do pozostałej części ciała Duqu, nie jest to język C++ i nie został skompilowany przy pomocy Visual C++ 2008 Microsoftu.
  • Architektura oparta w wysokim stopniu na zdarzeniach wskazuje na kod stworzony z myślą o wykorzystywaniu w niemal każdym rodzaju warunków, łącznie z komutacjami asynchronicznymi.
  • Biorąc pod uwagę rozmiar projektu Duqu, nie można wykluczyć, że za szkielet odpowiadał inny zespół niż ten, który stworzył sterowniki i napisał infekcję systemu oraz exploity.
  • Tajemniczym językiem programowania z pewnością nie jest C++, Objective C, Java, Python, Ada, Lua i wiele innych języków, które sprawdziliśmy.
  • W porównaniu ze Stuxnetem (który cały został napisany w MSVC++), jest to jedna z cech charakterystycznych szkieletu Duqu.

Szkielet Duqu: Co to było?

Po długiej analizie jesteśmy w 100% pewni, że Szkielet Duqu nie został zaprogramowany przy użyciu języka Visual C++. Możliwe, że jego autorzy wykorzystali stworzony przez siebie szkielet w celu wygenerowania pośredniego kodu c lub użyli całkowicie innego języka programowania.

Apelujemy do społeczności programistów i prosimy każdego, kto rozpoznaje ten szkielet, zestaw narzędzi lub język programowania, który może wygenerować podobne konstrukcje kodu, o skontaktowanie się z nami lub napisanie komentarza na blogu. Wierzymy, że z waszą pomocą możemy rozwikłać tajemnicę historii Duqu.