poniedziałek, 31 października 2016

Wstrzykiwanie kodu do procesów

Analizując złośliwe oprogramowanie dość często spotykamy się z mechanizmem wstrzykiwania złośliwego kodu do innych procesów użytkownika bądź explorer.exe. Dzisiaj opiszemy dwie z bardziej popularnych technik. Pierwsza polega na utworzeniu nowego wątku w zdalnym procesie a druga na wykorzystaniu APC (Asynchronous Procedure Call) do modyfikacji jednego lub kilku istniejących wątków procesu.

Dla uproszczenia złośliwy kod umieszczamy w zewnętrznej bibliotece. Jej pełną ścieżkę zapisujemy w buforze.

char* buffer = "f:\\demodll.dll";

Następnie musimy pobrać id procesu w kontekście którego będziemy uruchamiali złośliwy kod. W tym celu malware często korzysta z funkcji CreateToolhelp32Snapshot() oraz Process32First() i Process32Next().
Po otrzymaniu id procesu pobieramy do niego uchwyt. Teraz możemy zaalokować pamięci w tym zdalnym procesie za pomocą funkcji VirtualAllocEx() a następnie w to miejsce zapisać zawartość bufora za pomocą funkcji WriteProcessMemory().

HANDLE hprocess = OpenProcess(PROCESS_ALL_ACCESS,
FALSE,
procID);

LPVOID pProcessMem = VirtualAllocEx(hprocess,
NULL,
                              strlen(buffer3),
                              MEM_COMMIT,
                              PAGE_READWRITE);

WriteProcessMemory(hprocess,
                              pProcessMem,
                              buffer3,
                              strlen(buffer3),
                              NULL);

Jak można zauważyć do zdalnego procesu zapisujemy jedynie bufor – czyli pełną ścieżkę do biblioteki z malware a nie zawartość biblioteki. W celu uruchomienia tej biblioteki potrzebna nam jest funkcja LoadLibraryA a właściwie jej adres.

LPVOID addr = (LPVOID)GetProcAddress(
GetModuleHandle(L"kernel32.dll"),
"LoadLibraryA");

Teraz wykorzystamy pierwszą z wspomnianych metod czyli funkcję CreateRemoteThread() która tworzy i uruchamia nowy wątek we wskazanym procesie.

HANDLE threadID = CreateRemoteThread(process,
NULL,
0,
(LPTHREAD_START_ROUTINE)addr,
pProcessMem,
NULL,
NULL);

Metoda 2 - Asynchronous Procedure Call

APC jest funkcją która wykonywana jest asynchronicznie w kontekście wątku. Złośliwe oprogramowanie za pomocą QueueUserAPC może dodać do kolejki wskazanego wątku funkcję. Gdy następnym razem wątek jest uruchamiany (przełączanie kontekstu w systemie Windows realizowane jest właśnie w oparciu o wątki a nie procesy) funkcja jest wywoływana. Funkcja nie jest uruchamiana od razu ale dopiero w momencie osiągnięcia odpowiedniego stanu (np. po wywołaniu SleepEx() czy WaitForSingleObjectEx()).
W celu identyfikacji wątku należącego do zdalnego procesu ponownie skorzystamy z funkcji CreateToolhelp32Snapshot() oraz funkcji Thread32First() oraz Thread32Next().
Następnie otwieramy uchwyt do wątku i w kolejce rejestrujemy funkcję która będzie wywołana oraz wskaźnik do parametru funkcji. 

HANDLE thread = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);

if (thstr.th32OwnerProcessID == procID)
{
HANDLE thread2 = OpenThread(THREAD_ALL_ACCESS,
0,
thstr.th32ThreadID);
               if (thread2){
                              QueueUserAPC((PAPCFUNC)addr,
thread2,
((ULONG_PTR)pProcessMem));
                             
                              return 0;
                              }
               }                           

Kod źródłowy użyty w powyższych przykładach znajduje się na https://github.com/prevenity.

Brak komentarzy:

Prześlij komentarz