Debugowanie jądra systemu Windows: Wprowadzenie

Być może zastanawiałeś się kiedyś nad tym, czy można i czy warto debugować nie pojedynczy program, ale wszytko to co znajduje się pod kontrolą systemu operacyjnego? Jeżeli odpowiedź brzmi “tak” lub właśnie wzbudziłem Twoją ciekawość, przygotuj sobie kawę lub herbatę i zapoznaj się z artykułem, który przygotowałem dla Ciebie.

1. Wstęp

Celem tego artykułu jest zapoznanie czytelnika z przygotowaniem środowiska do debugowaniem jądra systemu Windows, wyjaśnienie zalet i wad możliwych rozwiązań oraz poprowadzenie zainteresowanej osoby przez proces konfiguracji środowiska debugowania jądra systemu Windows.

2. Dlaczego ktoś by w ogóle chciał debugować jądro systemu operacyjnego?

Debugowanie jądra systemu operacyjnego jest niezbędne do rozwiązania dużej liczby problemów związanych z trybem jądra:

3. Środowisko

Jeśli nadal chcesz przejąć kontrolę nad całym komputerem z systemem Windows lub desperacko pragniesz zmienić sposób myślenia o wewnętrznych elementach systemu Windows, musisz pamiętać o kilku zmianach w stosunku do debugowania w „tradycyjnym” trybie użytkownika. Po pierwsze, uzyskasz dostęp do dowolnego zasobu w systemie: od procesora przez całą pamięć do wątków. Po drugie, każdy ustawiony breakpoint zatrzyma system. Dlatego właśnie potrzebujesz drugiej maszyny. Największe możliwości daje rozwiązanie zbudowane z maszyn fizycznych, jednak podnosi ono koszty zbudowania kompletnego środowiska ze względu na konieczność posiadania drugiego komputera. Alternatywnym rozwiązaniem jest użycie maszyny wirtualnej lub… wirtualizacja całego środowiska.

3.1 Środowisko fizyczne

Aby skonfigurować środowisko fizyczne, potrzebujesz dwóch komputerów: hosta (debugger) i debugowaną maszynę (debugee). Wbrew pozorom nie istnieje z góry narzucony przymus, aby utrzymywać wspólną wersję i architekturę systemu operacyjnego pomiędzy dwoma maszynami. Istotny jest ten sam typ połączenia między tymi maszynami. Obsługiwanymi typami połączeń są Ethernet, port szeregowy, IEEE 1394 (FireWire) oraz USB (w wersji 2.0 lub nowszej). Poniższa tabela prezentuje istotne cechy dopuszczalnych rozwiązań.

PołączenieNiezawodnośćSzybkośćDodatkowe informacje
EthernetStabilneSzybkieKonieczne wsparcie dla karty sieciowej
SerialBardzo stabilneBardzo wolneUmożliwia debugowanie na bardzo niskim poziomie,
np. zarządzanie zasilaniem
może być niedostępne w najnowszych komputerach
IEEE 1394Bardzo stabilneSzybkieMoże być wykorzystane z wykorzystaniem kart rozszerzeń
USBMogą wystąpić problemySzybkieKonieczny specjalny kabel USB

Istnieją pewne uwagi związane z wykorzystaniem niektórych typów połączeń, o których należy pamiętać. Interfejs USB 2.0 jest dopuszczony do użycia tylko w przypadku, jeżeli jest to port nr 1. Konieczne jest również użycie kabla krosowanego. Jeśli jednak zdecydowałeś się na korzystanie z Ethernetu, powinieneś sprawdzić, czy zadeklarowano wsparcie dla posiadanego modelu karty sieciowej.

Jeśli wybrano już typ połączenia, wystarczy połączyć dwa komputery za jego pomocą.

3.2 Środowisko wirtualne

Debugowanie maszyny wirtualnej jest znacznie tańsze niż utrzymanie dodatkowych urządzeń fizycznych. Oczywiście fizyczny host nie musi być obsługiwany przez system Windows. Uniwersalnym rozwiązaniem jest połączenie gości (debuggera oraz maszyny debugowanej) za pomocą wirtualnego połączenia sieciowego.

Istnieją pewne założenia wstępne, którymi posłużono się projektując środowisko debugowania:

Jeśli napotkasz jakiekolwiek problemy z komunikacją pomiędzy maszynami podczas korzystania z tego rozwiązania, upewnij się, że Twoja karta sieciowa jest obsługiwana.

Następna część artykułu prezentuje przygotowanie i konfigurację środowiska wirtualnego.

4. Konfiguracja środowiska wirtualnego

4.1. Przygotowanie maszyny debugowanej (debugee)

Jeżeli skonfigurowano już połączenie sieciowe, nadszedł czas, aby przygotować maszynę debugowaną.

Jako administrator uruchom polecenia używając adres IP debuggera:

bcdedit /debug ON
bcdedit /dbgsettings net hostip:192.168.0.108 port:50000 key:Win.Kernel.Debug.Env

W dowolnej chwili możesz zweryfikować konfigurację debugowanej maszyny uruchamiając polecenie:

bcdedit /dbgsettings

debugee bcdedit config

4.2. Przygotowanie debuggera

  1. Pobierz i zainstaluj Windows 10 SDK .

  2. Po zainstalowaniu wszystkie potrzebne narzędzia powinny być dostępne w katalogu C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\ .

  3. Utwórz katalog do cache’owania symboli, np. C:\Symbols .

  4. Wyeksportuj zmienną środowiskową _NT_SYMBOL_PATH:

setx _NT_SYMBOL_PATH "srv*C:\Symbols*https://msdl.microsoft.com/download/symbols"

4.3. Rozpoczęcie debugowania jądra systemu Windows

Jeżeli nie napisano wyraźnie inaczej, poniższe działania powinny być wykonywane na debuggerze.

  1. Uruchom WinDBG znajdujący się w lokalizacji C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbg.exe.

  2. Z menu File wybierz ‘Kernel Debug’.

windbg file kernel debug

  1. W zakładce ‘NET’ ustaw pole ‘Key’ jako ‘Win.Kernel.Debug.Env’.

windbg config

  1. Wciśnij OK.

windbg waiting

  1. Zrestartuj debugowaną maszynę i poczekaj.

  2. Po kilku sekundach powinieneś zobaczyć:

windbg connected

W tym momencie powinno być możliwe skuteczne przetestowanie możliwości debugowania jądra.

4.4. Test

W WinDBG wybierz Break z menu Debug lub po prostu naciśnij Ctrl + B.

Spróbuj uruchomić dowolne polecenie w sesji windbg, np. wypisanie listy wszystkich procesów:

!process 0 0

Jeśli widzisz listę podobną do poniższej, wszystko jest w porządku.

windbg symbols error

Jeśli będziesz mieć problem z symbolami jak na rysunku poniżej

windbg symbols error

możesz naprawić załadowane symbole, uruchamiając polecenia w sesji windbg:

.symfix
.sympath

5. Podsumowanie

W artykule zapoznano czytelnika z debugowaniem jądra systemu Windows. Ponadto przedstawiono zalety i wady dopuszczalnych konfiguracji zależnych od wybranego typu połączenia pomiędzy maszynami. W ostatniej części artykułu poprowadzono czytelnika krok po kroku przez proces przygotowania środowiska wirtualnego. Zaproponowane rozwiązanie zostało oparte o dwie maszyny wirtualne z systemem Windows 10, które zostały osadzone na fizycznej maszynie z systemem Linux. Połączenie pomiędzy maszynami wirtualnymi wykonano za pośrednictwem sieci wirtualnej.

Następny artykuł na temat debugowania jądra systemu Windows będzie opisywał wybrane polecenia windbg oraz możliwe sposoby ich wykorzystania.