Tutorial de desarrollo de controladores de sistemas de archivos de Windows …

publicado en: tutoriales | 0

Este tutorial le ofrece pasos fáciles de entender para el desarrollo de un sencillo controlador de filtro de sistema de archivos. El controlador de demostración que le mostramos cómo crear imprime los nombres de los archivos abiertos para depurar la salida.

Este artículo está escrito para ingenieros con experiencia básica en el desarrollo de controladores de dispositivos Windows, así como conocimientos de C/C++. Además, también podría ser útil para personas sin un conocimiento profundo del desarrollo de controladores de Windows.

¿Qué es el controlador de filtro del sistema de archivos de Windows?

Un controlador de filtro del sistema de archivos de Windows es llamado durante cada operación de E/S del sistema de archivos (crear, leer, escribir, renombrar, etc.). Por lo tanto, es capaz de modificar el comportamiento del sistema de archivos. Los controladores de filtro del sistema de archivos son comparables a los controladores heredados, aunque requieren varios pasos de desarrollo especiales. El software de seguridad, copia de seguridad, instantánea y anti-virus utiliza estos controladores.

Desarrollo de un controlador de filtro de sistema de archivos simple

Antes de comenzar el desarrollo

Primero, para desarrollar un controlador de filtro de sistema de archivos, necesitas el kit IFS o WDK del sitio web de Microsoft. También tienes que establecer la variable de entorno %WINDDK% en la ruta, donde has instalado el kit WDK/IFS.

Atención: Incluso el más pequeño error en un controlador de sistema de archivos puede causar BSOD o inestabilidad del sistema.

Main.c

Entrada del controlador del filtro del sistema de archivos

Es un punto de acceso para cualquier controlador, incluso para el controlador del filtro del sistema de archivos. Lo primero que debemos hacer es almacenarDriverObject como una variable global (lo usaremos más tarde):

                //// Global dataPDRIVER_OBJECT g_fsFilterDriverObject = NULL;//// DriverEntry - Punto de entrada del conductorNTSTATUS DriverEntry(__inout PDRIVER_OBJECT DriverObject,__in PUNICODE_STRING RegistryPath){ NTSTATUS status = STATUS_SUCCESS;ULONG i = 0;//ASSERT(FALSE); // Esto se romperá para depurar///// Almacenar nuestro objeto conductor.//g_fsFiltroObjeto Conductor = Objeto Conductor;...}

Establecimiento de la tabla de despacho del IRP

El siguiente paso en el desarrollo de un controlador de filtro del sistema de archivos es llenar la tabla de despacho de IRP con punteros de función a los manejadores de IRP. Tendremos un manejador genérico de IRP en nuestro controlador de archivos que envía solicitudes más adelante. También necesitaremos un manejador para IRP_MJ_CREATE para recuperar los nombres de los archivos abiertos. Consideraremos la implementación de los manejadores IRP más adelante.

                //// DriverEntry - Punto de entrada del conductorNTSTATUS DriverEntry(__inout PDRIVER_OBJECT DriverObject,__in PUNICODE_STRING RegistryPath){ ...//// Inicializar la tabla de despacho del objeto conductor.// para (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; ++i) {DriverObject-{ i] = FsFilterDispatchPassThrough;}DriverObject-{ IRP_MJ_CREATE] = FsFilterDispatchCreate;...}

Establecer una tabla de despacho de E/S rápida

El controlador de filtro del sistema de archivos requiere una mesa de despacho de E/S rápida. No configurar esta tabla llevaría a un fallo del sistema. La E/S rápida es una forma diferente de iniciar operaciones de E/S que es más rápida que la IRP. Las operaciones de E/S rápidas siempre son sincrónicas. Si el manejador de E/S rápida devuelve FALSO, entonces no podemos usar E/S rápida. En este caso, se creará IRP.

                //// Datos globalesFAST_IO_DISPATCH g_fastIoDispatch ={size of(FAST_IO_DISPATCH),FsFilterFastIoCheckIfPossible,...};//// DriverEntry - Punto de entrada del conductorNTSTATUS DriverEntry(__inout PDRIVER_OBJECT DriverObject,__in PUNICODE_STRING RegistryPath){ ...//// Establecer la tabla de envío fast-io.//DriverObject-{N-]FastIoDispatch = &g_fastIoDispatch;...}

Registro de notificaciones sobre cambios en el sistema de archivos

Mientras se desarrolla un controlador de filtro del sistema de archivos, deberíamos registrar una notificación sobre los cambios en el sistema de archivos. Es crucial rastrear si el sistema de archivos se está activando o desactivando para realizar la conexión/desconexión de nuestro controlador de filtro del sistema de archivos. A continuación puede ver cómo realizar un seguimiento de los cambios en el sistema de archivos.

                //// DriverEntry - Punto de entrada del conductorNTSTATUS DriverEntry(__inout PDRIVER_OBJECT DriverObject,__in PUNICODE_STRING RegistryPath){ ...//// Rutina de devolución de llamada registrada para cambios en el sistema de archivos.//status = IoRegisterFsRegistrationChange(DriverObject, FsFilterNotificationCallback); if (!NT_SUCCESS(status)) {return status;}...}

Estableciendo la rutina de descarga del conductor

La última parte de la inicialización del controlador del sistema de archivos es establecer una rutina de descarga. Esta rutina le ayudará a cargar y descargar el controlador de filtro del sistema de archivos sin necesidad de reiniciar. No obstante, este controlador sólo se puede descargar realmente para fines de depuración, ya que es imposible descargar los filtros del sistema de archivos de manera segura. No se recomienda realizar la descarga en código de producción.

                //// DriverEntry - Punto de entrada del conductorNTSTATUS DriverEntry(__inout PDRIVER_OBJECT DriverObject,__in PUNICODE_STRING RegistryPath){ ...//// Configurar la rutina de descarga del conductor (sólo con fines de depuración).//DriverObject-{[DriverUnload = FsFilterUnload;}

Implementación de descarga del controlador del sistema de archivos

El conductor descarga la rutina, limpia los recursos y los distribuye. El siguiente paso en el desarrollo del controlador del sistema de archivos es desregistrar la notificación de los cambios en el sistema de archivos.

                //// Rutina de descargaVOID FsFilterUnload(__en PDRIVER_OBJECT DriverObject){...//// Rutina de devolución de llamada no registrada para cambios en el sistema de archivos.//IoUnregisterFsRegistrationChange(DriverObject, FsFilterNotificationCallback);...}

Después de anular el registro de la notificación, debe hacer un bucle a través de los dispositivos creados y separarlos y eliminarlos. Entonces espera cinco segundos hasta que todos los IRP pendientes se hayan completado. Tengan en cuenta que esta es una solución sólo de depuración. Funciona en el mayor número de casos, pero no hay garantía de que funcione en todos ellos.

                //// Descargue la rutinaVOID FsFilterUnload(__en PDRIVER_OBJECT DriverObject){...para (;;){IoEnumerateDeviceObjectList(DriverObject,devList,sizof(devList),&numDevices);if (0 == numDevices){break;}numDevices = min(numDevices, RTL_NUMBER_OF(devList));for (i = 0; i < numDevices; ++i) {FsFilterDetachFromDevice(devList[i]);ObDereferenceObject(devList[i]);}KeDelayExecutionThread(KernelMode, FALSE, &interval);}}

IrpDispatch.c

Despacho de paso

La única responsabilidad de este manejador de IRP es pasar las solicitudes al siguiente conductor. El objeto del siguiente conductor se almacena en la extensión de nuestro dispositivo.

                //// PassThrough IRP HandlerNTSTATUS FsFilterDispatchPassThrough(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp){PFSFILTER_DEVICE_EXTENSION pDevExt = (PFSFILTER_DEVICE_EXTENSION)DeviceObjectDeviceExtension;IoSkipCurrentIrpStackLocation(Irp);return IoCallDriver(pDevExt->AttachedToDeviceObject, Irp);}

Despacho crear

Cada operación de creación de archivos invoca a este controlador IRP. Después de tomar un nombre de archivo de PFILE_OBJECT, lo imprimimos en la salida de depuración. Después de eso, llamamos al handler pass-through que hemos descrito anteriormente. Noten que un nombre de archivo válido existe en PFILE_OBJECT sólo hasta que la operación de creación del archivo haya terminado! También existen las aperturas relativas así como las aperturas por id. En recursos de terceros, puedes encontrar más detalles sobre la recuperación de nombres de archivo en esos casos.

                //// IRP_MJ_CREATE IRP HandlerNTSTATUS FsFilterDispatchCreate(__in PDEVICE_OBJECT DeviceObject,__in PIRP Irp){PFILE_OBJECT pFileObject = IoGetCurrentIrpStackLocation(Irp)-;FileObject;DbgPrint("%wZ
", &pFiltroObjeto->NombreDeArchivo);return FsFiltroDispatchPassThrough(DeviceObject, Irp);}

FastIo.c

Dado que no todas las rutinas de E/S rápidas deben ser implementadas por el sistema de archivos subyacente, tenemos que probar la validez de la tabla de despacho de E/S rápidas para el siguiente controlador usando la siguiente macro:

                // Macro para comprobar si la rutina de manejo de FAST_IO_DISPATCH es válida

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *