Znajdowanie wstrzykniętego kodu

Znalezienie wstrzykniętego kodu nie jest zadaniem trywialnym. Według mnie to skuteczniejsza metoda “ukrycia się”, niż tworzenie usług lub sterowników. Można znaleźć sterowniki, można znaleźć usługi, natomiast wykrycie jakiegoś procesu, który prócz zamierzonych wykonuje dodatkowe operacje – jest nietrywialne. Oczywiście można wyeliminować problem usuwając program, który ten kod wstrzykuje (przypominam – mowa o wstrzykiwaniu kodu w trakcie działania programu, oryginalny plik wykonywalny nie zostaje zmodyfikowany, po każdym restarcie systemu “infekcja” musi nastąpić ponownie).

Najpierw kilka słów o metodach wstrzykiwania kodu, bo od wykorzystanej metody zależy to, czego w zasadzie należy szukać. Wiem o wykorzystywaniu następujących metod:

Wykorzystanie LoadLibrary

Funkcja LoadLibrary jest funkcją, która służy do ładowania bibliotek. Biblioteka załadowana w ten sposób jest widoczna na liście załadowanych do procesu modułów, dzięki czemu wykrycie takiej “podejrzanej” biblioteki jest możliwe choćby z wykorzystaniem narzędzia listdlls. Metoda ta jest prosta i skuteczna, ale również stosunkowo prosta do wykrycia.

Ładowanie biblioteki z pominięciem LoadLibrary, wstrzyknięcie shellcode

Bibliotekę można załadować również z pominięciem LoadLibrary , po prostu trzeba ją skopiować do przestrzeni adresowej docelowego procesu. Tak załadowana biblioteka nie pojawia się na liście zwracanej przez narzędzia typu listdlls. Wstrzyknięcie shellcode działa na analogicznej zasadzie z jedną drobną różnicą – o ile przy kopiowaniu biblioteki kopiuje się również nagłówek PE, o tyle w przypadku shellcode nagłówka tego może nie być (zwykle nie ma).

Wykrywanie

W przypadku, gdy biblioteka jest ładowana przy pomocy funkcji LoadLibrary “wystarczy” znaleźć procesy, które ładują “podejrzane” biblioteki. W przypadku dwóch pozostałych metod wstrzykiwania kodu, sposób jego wykrywania jest bardziej złożony. Zwykle polega on na:

Tu szybkie wyjaśnienie, flaga MMEXECUTEREADWRITE nie ma tej samej wartości PAGEEXECUTEREADWRITE. O wartościach flag MM_ można przeczytać na wiki ReactOS. Według tych informacji MMEXECUTEREADWRITE ma wartość 6.

Przykład

By lepiej zrozumieć – krótki przykład. Proces winlogon.exe prezentuje podejrzane zachowanie

TCP,winlogon.exe,412,SYN_SENT,172.16.0.55:1042,58.65.232.34:65520

Ze zrzutu pamięci za pomocą Volatility można wytypować kilka podejrzanych sekcji, między innymi tą:

VAD node @8227fc48 Start 7ff90000 End 7ff96fff Tag Vad Flags: Commit Charge: 0 Protection: 6 ControlArea @821bd7e8 Segment e105c4a0 Dereference list: Flink 00000000, Blink 00000000 NumberOfSectionReferences: 1 NumberOfPfnReferences: 0 NumberOfMappedViews: 19 NumberOfSubsections: 1 FlushInProgressCount: 0 NumberOfUserReferences: 20 Flags: HadUserReference, Commit FileObject: none WaitingForDeletion Event: 00000000 ModifiedWriteCount: 0 NumberOfSystemCacheViews: 0 First prototype PTE: e105c4d8 Last contiguous PTE: e105c4f0 Flags2: File offset: 00000000

Jak widać mamy tu poszukiwaną wartość 6 (Protection:6) oraz brak FileObject (FileObject: none). Zawartość tej sekcji nie ma jednak nagłówka pliku PE, więc prawdopodobnie jest to shellcode. Po sprawdzeniu tego na Virustotal okazuje się, że jest to wirus (choć wykrywa go tylko 20%25 programów).

Jeśli ktoś jest zainteresowany tym tematem, to polecam:

Oryginał tego wpisu dostępny jest pod adresem Znajdowanie wstrzykniętego kodu

Autor: Paweł Goleń