Jak działa injectowanie DLL przez SetWindowsHookEx?

Hej,

Dzisiaj chciałbym w krótki sposób opisać jeden ze sposobów wstrzykiwania DLL za pomocą SetWindowsHookEx. Postaram się prześledzić cały proces działania tego mechanizmu w systemie operacyjnym Windows.

Haki (hooks) w systemie Windows służą do wstrzykiwania się w łańcuch wiadomości wysyłanych między oknami bądź jądrem a oknami systemu. Dzięki nim możliwe jest przechwytywanie klawiszy, emulowanie klawiszy, "nagrywanie" zdarzeń oraz wiele innych funkcjonalności. Można np założyć hak na zdarzenie HSHELL_TASKMAN i zwracać TRUE uniemożliwiając uruchomienie menadżera zadań.

Ale jak to ma się do DLLek ? Otóż by przechwytywanie zdarzeń mogło działać globalnie, w jakiś sposób musimy dostać się w łańcuch wywołań haków w innym procesie. To właśnie tutaj wymagane jest przygotowanie biblioteki DLL, którą system wstrzykuje do każdego procesu, który aktualnie odbiera wiadomość, którą jesteśmy zainteresowani. Z tej metody również korzysta się często, gdy nie koniecznie chcemy zbierać informacje o zdarzeniach, ale po prostu chcemy umieścić nasz kod w uruchomionych procesach, celem np. założenia inline hooka.

Przykładowy kod, łądujący bibliotekę do procesów
Korzystając z powyższego kodu, możemy wstrzykiwać DLLki do procesów. W dllce powinna być metoda CBTProc, która przyjmuje odpowiednie parametry.

Jak system ładuje naszą bibliotekę do innych procesów?

Podczas instalacji haka, wykonywany jest szereg czynności, zanim padnie faktyczne wywołanie LoadLibraryExW (bo tą funkcją ładowana jest nasza biblioteka w innym procesie). Postaram się opisać to w dużym uproszczeniu.

Najpierw wywołujemy SetWindowsHookExA API. Funkcja ta konwertuje dane na Unicode i przechodzi do wywołania _SetWindowsHookEx, które z kolei konwertuje przekazany ciąg znaków Unicode na strukturę UNICODE_STRING. Następnie jest wywołana funkcja jądra NtUserSetWindowsHookEx. Unicode string, jak zapewne łatwo się domyśleć, zawiera ścieżkę bezwzględną do biblioteki, która ma zostać załadowana.

_SetWindowsHookEx w IDA Pro Free
Następnie informacja o tym, że biblioteka ma obsługiwać dane zdarzenie trafia na odpowiedni stos w jądrze systemu (win32k.sys). Żeby jednak została załadowana do innego procesu, proces ten musi załadować bibliotekę user32.dll. Jest to konieczne, ponieważ biblioteka ta inicjuje w procedurze DllMain tablicę KernelCallbackTable. Wskaźnik do tej tablicy znajdziemy w strukturze PEB (Process Environment Block).

Inicjalizacja listy callbacków (Windows 8)
Lista callbacków jest dość pokaźna, bo jest ich aż 114. Nas interesuje tutaj właściwie jeden, czyli __ClientLoadLibrary. Doskonale widać tutaj, że chwilę po wejściu do tej procedury następuje próba załadowania biblioteki poprzez api LoadLibraryExW. W taki właśnie sposób nasza DLLka trafia do przestrzeni adresowej innego procesu!

Procedura __ClientLoadLibrary
Tak więc, dotarliśmy do końca. Oczywiście odpowiednio modyfikując ten callback możemy zablokować innym możliwość instalowania DLLki w naszym procesie w ten sposób :)

Miłego "hakowania" okienek!

Komentarze

Prześlij komentarz