Przygotowanie środowiska pracy
Zacznijmy od przygotowania środowiska. Będzie nam potrzebne WDK (Windows Driver Kit), w wersji 7.1, która umożliwia tworzenie sterowników pod systemy Windows XP, Vista oraz 7. Gwoli ścisłości należy wspomnieć, że najnowszą obecnie wersją jest WDK 8, która obsługuje Windows 8, ale nie zadziała już na XP.
Jest ono dostępne do pobrania stąd:
WDK 7.1. Plik ISO po pobraniu należy nagrać na płytę, lub zamontować jako wirtualny napęd w systemie. Następną wymaganą czynnością jest odpalenie instalatora z tego napędu. Podczas instalacji najlepiej jest zaznaczyć wszystkie możliwe komponenty, chyba że jesteśmy pewni, że któryś z nich się nam nie przyda.
Kompilacja przykładowego sterownika
Po zainstalowaniu WDK utwórzmy folder, gdzie będą się znajdować źródła naszego sterownika, nazwijmy go
MyDriver. Niech będzie to C:\MyDriver. Należy w nim umieścić pliki:
Po czym możemy już skompilować sterownik. W tym celu otwieramy Menu Start, wskazujemy kolejno Windows Driver Kits -> WDK 7600.16385.1 -> Build Environments -> Windows 7 -> x64 Free Build Environment. W oknie konsoli przechodzimy do katalogu C:\MyDriver i wpisujemy
build. Powinniśmy otrzymać output o mniej więcej takiej postaci:
BUILD: Compile and Link for AMD64
BUILD: Loading c:\winddk\7600.16385.1\build.dat...
BUILD: Computing Include file dependencies:
BUILD: Start time:
BUILD: Examining c:\mydriver directory for files to compile.
c:\mydriver Invalidating OACR warning log for 'root:amd64fre'
BUILD: Saving c:\winddk\7600.16385.1\build.dat...
BUILD: Compiling and Linking c:\mydriver directory
Configuring OACR for 'root:amd64fre' - <OACR on>
Compiling - mydriver.c
Linking Executable - objfre_win7_amd64\amd64\mydriver.sys
BUILD: Finish time:
BUILD: Done
3 files compiled - 4 Warnings
1 executable built
Nasz sterownik pojawił się teraz w lokalizacji C:\MyDriver\objfre_win7_amd64\amd64\mydriver.sys.
Podpisanie cyfrowe sterownika
Mamy sterownik, ale próba uruchomienia go w tej chwili zakończy się najprawdopodobniej otrzymaniem kodu błędu 577 (
Systemowe kody błędów (500-999)). Dlaczego tak się dzieje? Otóż, od czasów Visty wszystkie sterowniki działające przy systemach x64
muszą być podpisane, aby można było je uruchomić. Taka mała niewygoda dla twórców rootkitów ;) Wiadomo jednak, że deweloper nie szejk katarski, pieniędzy łatwo wydawać nie chce. W związku z tym, stworzono coś, co nazywa się
TESTSIGNING. Polega to na tym, że system zgodzi się na załadowanie wszystkich sterowników, które są podpisane
jakimkolwiek certyfikatem, ale podpisane być muszą. Jak to włączyć? Potrzebne będą niestety uprawnienia administratora. Uruchamiamy cmd.exe, właśnie jako administrator, i wpisujemy następujące polecenie:
Bcdedit.exe -set TESTSIGNING ON
Wykonajmy teraz jeszcze jedną czynność. Teoretycznie powinna być opisana na końcu, ale żeby nie restartować komputera kilka razy, wspomniana będzie tutaj, a omówiona na końcu.
Uruchamiamy edytor rejestru i przechodzimy do klucza
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Debug Print Filter. Jeśli nie mamy go w rejestrze, należy go stworzyć. Następnie tworzymy nową wartość typu DWORD o nazwie
DEFAULT i ustawiamy jej dane na 0xffffffff lub, w dziesiątkowym, na 4294967295. Następnie restartujemy komputer.
Nasz system powinien teraz obsługiwać testowe podpisywanie. Aby sprawdzić, czy to faktycznie działa, wystarczy popatrzyć na któryś z rogów pulpitu, czy znajduje się tam informacja o systemie i kompilacji. Wg MSDN'u jest to lewy dolny róg, ale w moim systemie prawy. Wygląda na to, że ktoś był nietrzeźwy ;)
Niemniej jednak, czas na wygenerowanie naszego testowego certyfikatu. Z poziomu cmd przechodzimy do katalogu C:\WinDDK\7600.16385.1\bin\amd64 i wpisujemy polecenie:
makecert -r -pe -ss PrivateCertStore -n CN=NazwaCertyfikatu MyDriver.cer
Aby sprawdzić, czy certyfikat został prawidłowo utworzony, można odpalić certmgr.msc i po lewej stronie przejść do Certyfikaty - bieżący użytkownik -> PrivateCertStore -> Certyfikaty.
Teraz pozostaje nam podpisać sterownik. Używamy w tym celu następującego polecenia:
signtool sign /v /s PrivateCertStore /n NazwaCertyfikatu /t http://timestamp.verisign.com/scripts/timestamp.dll C:\MyDriver\objfre_win7_amd64\amd64\mydriver.sys
Możemy jeszcze zweryfikować podpisanie, poprzez wykonanie następujących poleceń (z prawami administratora):
certmgr.exe /add MyDriver.cer /s /r localMachine root
signtool verify /pa /v C:\MyDriver\objfre_win7_amd64\amd64\MyDriver.sys
Jeśli nie wystąpiły żadne błędy, sterownik został prawidłowo podpisany i jest gotowy do użycia. No właśnie, jak go uruchomić? Generalnie, istnieje kilka metod. Jedna z nich, polega na wykorzystaniu nieudokumentowanych funkcji WinAPI (np.
ZwSystemSetInformation z ntdll.dll). Pojawia się tu jednak pewien problem - pamięć sterownika może zostać poddana stronicowaniu. Próba dostępu do takiej pamięci może z kolei spowodować BSoD'a. Drugą (bezpieczną, bo sterowniki nie zostaną poddane stronicowaniu) metodą, jest użycie SCM (Service Control Manager), i właśnie tej metody użyjemy. Będziemy potrzebować dodatkowego programu. Możemy napisać go sami (przykładowy kod poniżej) lub ściągnąć z internetu (np.
OSRLOADER).
#include <cstdio>
#include <windows.h>
#include <shlwapi.h>
int main( int argc, char ** argv )
{
if( argc != 2 )
{
printf( "Usage: %s path_to_driver\n", argv[ 0 ] );
return 1;
}
SC_HANDLE hSCManager;
SC_HANDLE hService;
SERVICE_STATUS sStatus;
hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CREATE_SERVICE );
if( hSCManager )
{
hService = CreateService( hSCManager, PathFindFileName( argv[ 1 ] ), PathFindFileName( argv[ 1 ] ),
SERVICE_START | DELETE | SERVICE_STOP, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
SERVICE_ERROR_IGNORE, argv[ 1 ], NULL, NULL, NULL, NULL, NULL );
if( !hService )
hService = OpenService( hSCManager, PathFindFileName( argv[ 1 ] ),
SERVICE_START | DELETE | SERVICE_STOP );
if( hService )
{
if( !StartService( hService, 0, NULL ) )
printf( "Some error has occured while starting service: %d\n",( int ) GetLastError() );
else
printf( "Service started successfully\n" );
printf( "Press Enter to stop service\n" );
getchar();
ControlService( hService, SERVICE_CONTROL_STOP, & sStatus );
DeleteService( hService );
CloseServiceHandle( hService );
}
else
printf( "Some error has occured while creating service: %d\n",( int ) GetLastError() );
CloseServiceHandle( hSCManager );
}
else
printf( "Some error has occured while opening SCM: %d\n",( int ) GetLastError() );
return 0;
}
Program należy skompilować z
-lshlwapi
, a następnie uruchomić jako administrator.
Prawdopodobnie podczas uruchamiania nie otrzymaliśmy żadnych błędów, więc sterownik powinien działać. Można się o tym przekonać na własne oczy. Tutaj dochodzimy do miejsca, gdzie trzeba wytłumaczyć cel stworzenia odpowiednich wartości w rejestrze. Otóż, poczynając od Windows Visty i Windows Server 2008, output funkcji
DbgPrint jest wyłączony. Jako że w naszym przykładowym sterowniku ta funkcja jest jedyną widoczną oznaką, że wszystko działa, należy ten output włączyć. Robimy to właśnie poprzez zmodyfikowanie rejestru.
Aby podglądnąć wynik działania tej funkcji, należy pobrać program
DebugView i uruchomić go (oczywiście z prawami administratora), oraz wcisnąć Ctrl+K. Następnie uruchomić sterownik za pomocą naszego programu. W okienku DebugView powinnien się pojawić napis "Hello world!", a po zakończeniu usługi "Invoked OnUnload".
Podsumowanie
Artykuł ten ma na celu przedstawić sposób uruchomienia własnych sterowników jedynie jako ciekawostkę. Wszelkie błędy, jak również różnice w instalacji na innych systemach, można zgłaszać na
forum.
Źródła