Selezionare il template Empty WDM Driver (è sempre un po' nascosto ma alla fine salta fuori) e impostare nome e percorso desiderati.
Se nella cartella Driver Files del progetto è presente un file con estensione .inf eliminatelo (la sua presenza potrebbe compromettere la compilazione per il tipo di driver che andremo a scrivere).
Aggiungere un file con estensione .c alla cartella Source Files
Impostare la modalità a 64-bit (se non già impostata di default).
Scrivere il seguente codice nel file con estensione .c aggiunto al progetto e cercare di capirne il contenuto: sono stati aggiunti abbondanti commenti a supporto.
Compilare e copiare il file con estensione .sys nel Guest. A questo punto, sempre nel Guest, possiamo usare una console dei comandi aperta come amministratore ed il tool sc.exe per installare, il driver attraverso il comando (stando attenti agli spazi):
sc create nome_driver type= kernel binPath= percorso_file_sys
Si può, sempre attraverso sc.exe, avviare, stoppare e rimuovere il driver attraverso i comandi:
sc start nome_driver
sc stop nome_driver
sc delete nome_driver
Se durante queste operazioni DebugView è aperto (come amministratore) si possono leggere le varie stringhe passate a KdPrint (controllare che l'opzione Capture -> Capture Kernel sia selezionata in DebugView). Notare che la funzione DriverUnload è chiamata allo stop del driver, non alla rimozione completa dalla memoria e dal registro.
Usare sc.exe non è il massimo della comodità. Per rendere le cose un po' più sbrigative si può scrivere un proprio tool sfruttando l'API relativa (si veda [3]) oppure si possono usare tool sviluppati da terzi come OSR Driver Loader o KdManager (si veda [2]; in questo corso userò KdManager). Avviare KdManager come amministratore, selezionare il file con estensione .sys, premere Register per installare il driver, Run per avviarlo, Stop per fermarlo e Unregister per rimuoverlo
Codice Sorgente:
HelloKernel.zip
Riferimenti:
[1] https://github.com/zodiacon/windowskernelprogrammingbook
[2] https://github.com/wanttobeno/Win64DriverStudy_Src/blob/master/%5B1-2%5DKrnlHW64/sys/objfre_win7_amd64/amd64/KmdManager.exe
[3] https://docs.microsoft.com/en-us/windows/win32/services/the-complete-service-sample
Impostare la modalità a 64-bit (se non già impostata di default).
Scrivere il seguente codice nel file con estensione .c aggiunto al progetto e cercare di capirne il contenuto: sono stati aggiunti abbondanti commenti a supporto.
#include <ntddk.h> #define DRIVER_TAG 'dcba' /* typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWCH Buffer; } UNICODE_STRING; */ UNICODE_STRING g_RegistryPath; // Funzione invocata alla rimozione del driver void DriverUnload(_In_ PDRIVER_OBJECT DriverObject) { // macro che sopprime avvisi trattati come errori UNREFERENCED_PARAMETER(DriverObject); // libera memoria allocata ExFreePool(g_RegistryPath.Buffer); KdPrint(("Hello driver Unload called\n")); } // DriverEntry è l'entrypoint del driver chiamato da un thread di sistema quando il driver viene caricato e avviato. // DriverObject è l'oggetto che rappresenta questo stesso driver e che viene passato a DriverEntry per // essere inizializzato con vari puntatori a funzioni. // RegistryPath punta ad una stringa che rappresenta la chiave nel registro di sistema che il driver può // usare per salvare/leggere dati. NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) { // Memory pool evita frammentazione ed inefficienze allocando solo blocchi di dimensione multipla // di una pagina (in realtà è più complesso di così ma poco importa a livello pratico; la memoria // ritornata da ExAllocatePoolWithTag verrà gestita in modo simile alla normale memoria allocata su heap). // Tag usato per facilitare compito di debugger e altri strumenti di diagnostica (max 4 caratteri tra // apici singoli; spesso scritti al contrario per il fatto che su macchine little-endian il loro ordine è rovesciato). g_RegistryPath.Buffer = (WCHAR*)ExAllocatePoolWithTag(PagedPool, RegistryPath->Length, DRIVER_TAG); // KdPrint macro simile a funzione printf in quanto permette di usare stringhe di formato e specificatori. // Compilando in modalità Debug è uguale a DbgPrint mentre in modalità Release non ha alcun effetto, al contrario // di DbgPrint che ha sempre effetto a prescindere dalla modalità di compilazione. if (g_RegistryPath.Buffer == NULL) { KdPrint(("Failed to allocate memory\n")); return STATUS_INSUFFICIENT_RESOURCES; } // RtlCopyUnicodeString(Destination, Source) copia il minor numero di caratteri tra // Source.Length e Destination.MaximumLength da Source a Destination. // RtlCopyUnicodeString modifica solo il campo Length di Destination, // MaximumLength deve quindi essere impostato esplicitamente. g_RegistryPath.MaximumLength = RegistryPath->Length; RtlCopyUnicodeString(&g_RegistryPath, (PCUNICODE_STRING)RegistryPath); // Specificatore %wZ indica UNICODE_STRING KdPrint(("Copied registry path: %wZ\n", &g_RegistryPath)); // Imposta metodo da invocare quando driver viene rimosso DriverObject->DriverUnload = DriverUnload; // Raccoglie info su OS RTL_OSVERSIONINFOW info = { sizeof(info) }; RtlGetVersion(&info); KdPrint(("Windows Version: %d.%d.%d\n", info.dwMajorVersion, info.dwMinorVersion, info.dwBuildNumber)); KdPrint(("Hello driver initialized successfully\n")); return STATUS_SUCCESS; }
Compilare e copiare il file con estensione .sys nel Guest. A questo punto, sempre nel Guest, possiamo usare una console dei comandi aperta come amministratore ed il tool sc.exe per installare, il driver attraverso il comando (stando attenti agli spazi):
sc create nome_driver type= kernel binPath= percorso_file_sys
Si può, sempre attraverso sc.exe, avviare, stoppare e rimuovere il driver attraverso i comandi:
sc start nome_driver
sc stop nome_driver
sc delete nome_driver
Se durante queste operazioni DebugView è aperto (come amministratore) si possono leggere le varie stringhe passate a KdPrint (controllare che l'opzione Capture -> Capture Kernel sia selezionata in DebugView). Notare che la funzione DriverUnload è chiamata allo stop del driver, non alla rimozione completa dalla memoria e dal registro.
Usare sc.exe non è il massimo della comodità. Per rendere le cose un po' più sbrigative si può scrivere un proprio tool sfruttando l'API relativa (si veda [3]) oppure si possono usare tool sviluppati da terzi come OSR Driver Loader o KdManager (si veda [2]; in questo corso userò KdManager). Avviare KdManager come amministratore, selezionare il file con estensione .sys, premere Register per installare il driver, Run per avviarlo, Stop per fermarlo e Unregister per rimuoverlo
Codice Sorgente:
HelloKernel.zip
Riferimenti:
[1] https://github.com/zodiacon/windowskernelprogrammingbook
[2] https://github.com/wanttobeno/Win64DriverStudy_Src/blob/master/%5B1-2%5DKrnlHW64/sys/objfre_win7_amd64/amd64/KmdManager.exe
[3] https://docs.microsoft.com/en-us/windows/win32/services/the-complete-service-sample
Nessun commento:
Posta un commento