Фильтр файловой системы

Тема в разделе "LANGS.C", создана пользователем Just_Neko, 12 фев 2009.

  1. Just_Neko

    Just_Neko New Member

    Публикаций:
    0
    Регистрация:
    12 фев 2009
    Сообщения:
    22
    Всем доброго дня!
    Пишу свой собственный файловый фильтр
    Общая задача на будущее - на лету шифровать данные при записи и расшифровывать при чтении
    Написал каркас, стал отлаживать в Soft-Ice'e - падает с кодом 0x0000008E

    Убрал практически всё, оставил лишь процедуру, пропускающую IRP-пакеты дальше, все равно падает. Подскажите, где здесь кроется злосчастный баг? =)
    Код (Text):
    1. // 0x0000008E (0xC0000005, 0x8058DD6A, 0xF7791C14, 0x00000000)
    2.  
    3. #include "ntddk.h"
    4.  
    5. #define NT_DEVICE_NAME L"\\Device\\HarddiskVolume1"
    6. #define WIN32_DEVICE_NAME L"\\DosDevices\\HarddiskVolume1"
    7.  
    8. #define MAXPATHLEN      1024
    9.  // GLOBALS
    10.  PDEVICE_OBJECT DriveHookDevices[26];
    11.  ULONG DrivesToHook = 0;
    12.  //
    13.  typedef struct _FILE_FS_ATTRIBUTE_INFORMATION {
    14.     ULONG FileSystemAttributes;
    15.     LONG MaximumComponentNameLength;
    16.     ULONG FileSystemNameLength;
    17.     WCHAR FileSystemName[1];
    18. } FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION;
    19.  
    20. typedef struct {
    21.     PDEVICE_OBJECT   FileSystem;
    22.     unsigned         LogicalDrive;
    23.     BOOLEAN          Hooked;
    24.     PFILE_FS_ATTRIBUTE_INFORMATION FsAttributes;
    25.     IO_REMOVE_LOCK RemoveLock;
    26. } HOOK_EXTENSION, *PHOOK_EXTENSION;
    27.  
    28. NTKERNELAPI
    29. NTSTATUS ZwQueryVolumeInformationFile(  
    30.     IN HANDLE FileHandle,  
    31.     OUT PIO_STATUS_BLOCK IoStatusBlock,  
    32.     OUT PVOID FsInformation,  
    33.     IN ULONG Length,  
    34.     IN FS_INFORMATION_CLASS FsInformationClass  
    35.     );
    36.    
    37. BOOLEAN HookDrive(IN ULONG Drive, IN PDRIVER_OBJECT DriverObject);
    38. NTSTATUS DispatchAny(PDEVICE_OBJECT, PIRP);
    39. NTSTATUS CompleteRequest(PIRP, NTSTATUS, ULONG_PTR);
    40. VOID UnloadOperation(IN PDRIVER_OBJECT);
    41. VOID UnhookDrive(IN ULONG);
    42. ULONG HookDeviceSet(IN ULONG,IN PDRIVER_OBJECT);
    43.    
    44. NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath)  
    45. {
    46.     NTSTATUS status;
    47.     int i;
    48.     for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
    49.     {
    50.         pDriverObject->MajorFunction[i] = DispatchAny;
    51.     }
    52.     HookDrive(2, pDriverObject);
    53.     pDriverObject->DriverUnload = UnloadOperation;
    54.     return STATUS_SUCCESS;
    55. }
    56.  
    57.  
    58. BOOLEAN HookDrive(IN ULONG Drive, IN PDRIVER_OBJECT DriverObject)
    59. {
    60.     IO_STATUS_BLOCK ioStatus;
    61.     HANDLE ntFileHandle;
    62.     OBJECT_ATTRIBUTES objectAttributes;
    63.     PDEVICE_OBJECT fileSysDevice;
    64.     PDEVICE_OBJECT hookDevice;
    65.     UNICODE_STRING fileNameUnicodeString;
    66.     ULONG fileFsAttributesSize;
    67.     PFILE_FS_ATTRIBUTE_INFORMATION fileFsAttributes;
    68.     NTSTATUS status;
    69.     ULONG i;
    70.     PFILE_OBJECT fileObject;
    71.     WCHAR filename[]=L"\\DosDevices\\A:\\";
    72.     PHOOK_EXTENSION hookExtension;
    73.     ULONG LockTag;
    74.     LockTag='Neko';
    75.     if (Drive >=26)
    76.         return FALSE;
    77.     if (DriveHookDevices[Drive] == NULL) // если диск ещё не захвачен
    78.     {
    79.         filename[12]=(CHAR)('A'+Drive); // настраиваем имя диска
    80.         RtlInitUnicodeString(&fileNameUnicodeString,filename);
    81.         InitializeObjectAttributes(&objectAttributes,
    82.                                     &fileNameUnicodeString,
    83.                                     OBJ_CASE_INSENSITIVE,
    84.                                     NULL,
    85.                                     NULL);
    86.         status=ZwCreateFile(&ntFileHandle,
    87.                             SYNCHRONIZE|FILE_ANY_ACCESS,
    88.                             &objectAttributes,
    89.                             &ioStatus,
    90.                             NULL,
    91.                             0,
    92.                             FILE_SHARE_READ|FILE_SHARE_WRITE,
    93.                             FILE_OPEN,
    94.                             FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE,
    95.                             NULL,
    96.                             0);
    97.         if(!NT_SUCCESS(status))
    98.         {  
    99.             return FALSE;
    100.         }
    101.         status=ObReferenceObjectByHandle(ntFileHandle,
    102.                                         FILE_READ_DATA,
    103.                                         NULL,
    104.                                         KernelMode,
    105.                                         &fileObject,
    106.                                         NULL);
    107.         if(!NT_SUCCESS(status))
    108.         {
    109.             ZwClose(ntFileHandle);
    110.             return FALSE;
    111.         }
    112.         fileSysDevice=IoGetRelatedDeviceObject(fileObject);
    113.         if(!fileSysDevice)
    114.         {
    115.             ObDereferenceObject(fileObject);
    116.             ZwClose(ntFileHandle);
    117.             return FALSE;
    118.         }
    119.         // проверяем, не захвачен ли
    120.         for(i=0;i<26;i++)
    121.         {
    122.             if(DriveHookDevices[i]==fileSysDevice)
    123.             {
    124.                 // Если уже захватили, ассоциируем с другими дисками, указывающими на тот же драйвер
    125.                 ObDereferenceObject(fileObject);
    126.                 ZwClose(ntFileHandle);
    127.                 DriveHookDevices[Drive]=fileSysDevice;
    128.                 return TRUE;
    129.             }
    130.         }
    131.         status=IoCreateDevice(DriverObject,
    132.                             sizeof(HOOK_EXTENSION),
    133.                             NULL,
    134.                             fileSysDevice->DeviceType,
    135.                             fileSysDevice->Characteristics,
    136.                             FALSE,
    137.                             &hookDevice);
    138.         if(!NT_SUCCESS(status))
    139.         {
    140.             ObDereferenceObject(fileObject);
    141.             ZwClose(ntFileHandle);
    142.             return FALSE;
    143.         }
    144.         hookDevice->Flags &= ~DO_DEVICE_INITIALIZING;
    145.         hookDevice->Flags |= (fileSysDevice->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO));
    146.         hookExtension=hookDevice->DeviceExtension;
    147.         hookExtension->LogicalDrive='A'+Drive;
    148.         hookExtension->FileSystem=fileSysDevice;
    149.         hookExtension->Hooked=TRUE;
    150.         status=IoAttachDeviceByPointer(hookDevice,fileSysDevice);
    151.         if(!NT_SUCCESS(status))
    152.         {
    153.             ObDereferenceObject(fileObject);
    154.             ZwClose(ntFileHandle);
    155.             return FALSE;
    156.         }
    157.         // проверяем, не NTFS ли это
    158.         fileFsAttributesSize=sizeof(FILE_FS_ATTRIBUTE_INFORMATION)+MAXPATHLEN;
    159.         hookExtension->FsAttributes=(PFILE_FS_ATTRIBUTE_INFORMATION)ExAllocatePool(NonPagedPool,fileFsAttributesSize);
    160.  
    161.     if(KeGetCurrentIrql()==PASSIVE_LEVEL)
    162.     {
    163.         IoInitializeRemoveLock(&hookExtension->RemoveLock,LockTag,0,0);
    164.     }                          
    165.         if(hookExtension->FsAttributes && !NT_SUCCESS( ZwQueryVolumeInformationFile(ntFileHandle,
    166.                                     &ioStatus,
    167.                                     hookExtension->FsAttributes,
    168.                                     fileFsAttributesSize,
    169.                                     FileFsAttributeInformation)))
    170.         {
    171.             // В случае провала мы не получаем аттрибуты
    172.             ExFreePool(hookExtension->FsAttributes);
    173.             hookExtension->FsAttributes=NULL;
    174.         }
    175.         // обновляем список захваченных устройств, добавляя этот
    176.         ObDereferenceObject(fileObject);
    177.         ZwClose(ntFileHandle);
    178.         DriveHookDevices[Drive]=hookDevice;
    179.     }
    180.     else // если диск уже захвачен
    181.     {
    182.         hookExtension = DriveHookDevices[Drive]->DeviceExtension;
    183.         hookExtension->Hooked=TRUE;
    184.     }
    185.     return TRUE;
    186. }
    187.  
    188.  
    189. NTSTATUS DispatchAny(PDEVICE_OBJECT fido, PIRP pIrp)
    190. {
    191. NTSTATUS status;
    192. PHOOK_EXTENSION pdx = (PHOOK_EXTENSION) fido->DeviceExtension;
    193. //status = IoAcquireRemoveLock(&pdx->RemoveLock, pIrp);
    194. //if (!NT_SUCCESS(status))
    195. //return CompleteRequest(pIrp, status, 0);
    196. IoSkipCurrentIrpStackLocation(pIrp);
    197. status = IoCallDriver(pdx->FileSystem, pIrp);
    198. //IoReleaseRemoveLock(&pdx->RemoveLock, pIrp);
    199. return status;
    200. }
    201.  
    202. NTSTATUS CompleteRequest(PIRP Irp, NTSTATUS status, ULONG_PTR info)
    203. {
    204.     Irp->IoStatus.Status = status;
    205.     Irp->IoStatus.Information = info;
    206.     IoCompleteRequest(Irp, IO_NO_INCREMENT);
    207.     return status;
    208. }
    209.  
    210.  
    211. VOID UnloadOperation(IN PDRIVER_OBJECT pDriverObject)
    212. {
    213.     PDEVICE_OBJECT  deviceObject = pDriverObject->DeviceObject;
    214.     PHOOK_EXTENSION pDiskDeviceExtension=(PHOOK_EXTENSION)pDriverObject->DeviceObject->DeviceExtension;
    215.     IoDetachDevice(pDiskDeviceExtension->FileSystem);
    216.     IoDeleteDevice( deviceObject );
    217.     return;
    218. }
    Заранее огромное спасибо всем откликнувшимся
     
  2. Just_Neko

    Just_Neko New Member

    Публикаций:
    0
    Регистрация:
    12 фев 2009
    Сообщения:
    22
    Сразу ещё один вопрос - перед аттачем к диску я активирую флаг DO_BUFFERED_IO, поскольку в дальнейшем буду использовать данный метод работы с диском

    hookDevice->Flags |= (fileSysDevice->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO));

    Но в утилите DeviceTree показано, что мои локальные имеют параметры Interpreted Device Flag:

    BUS_ENUMERATE_NAME
    DEVICE_HAS_NAME
    DIRECT_IO
    (на системном ещё SYSTEM_BOOT_PARTITION)

    Если я правильно понял, флаги на создаваемом устройстве и к которому подключаешься должны быть одинаковые.
    Где ошибка?
     
  3. Just_Neko

    Just_Neko New Member

    Публикаций:
    0
    Регистрация:
    12 фев 2009
    Сообщения:
    22
    Первый вопрос уже разрешил - надо было использовать \\Device\\HarddiskVolume1
    Второй до сих пор актуален
     
  4. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Ты пишешь, что хочешь себе флаги как у того устройства либо buffered i/o либо direct i/o. у того устройства direct очевидно. чтоты хочешь еще?
    юзай директ.
     
  5. Just_Neko

    Just_Neko New Member

    Публикаций:
    0
    Регистрация:
    12 фев 2009
    Сообщения:
    22
    Спасибо.
    Скажите, правильно ли я всё понял:
    при перехвате IRP_MJ_READ:
    a) при BUFFERED_IO мы получаем указатель на данные через Buf = (PUCHAR)(pIrp->AssociatedIrp.SystemBuffer);
    b) при DIRECT_IO - через Buf = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);

    при этом в обоих случаях смещение в файле, в который осуществляется запись, хранится в p_IO_STK->Parameters.Read.ByteOffset.QuadPart?
    Таким образом, если драйвер перехватывает и чтение и запись с целью дописывания в начало каждого файла сигнатуры, скажем, из 4-х байт, достаточно увеличивать в процедурах перехвата данный параметр на 4, что при BUFFERED_IO, что при DIRECT_IO? (Разумеется, только для новых или уже обработанных файлов)
     
  6. Just_Neko

    Just_Neko New Member

    Публикаций:
    0
    Регистрация:
    12 фев 2009
    Сообщения:
    22
    Небольшой вопрос по азам программирования драйверов:

    я правильно понял, что если вызываешь IoCompleteRequest, то Irp передается вышестоящим драйверам, и вниз уже не попадает?
    Также интересует, обязательно ли должен быть вызов данной функции в конце своей IoCompletion routine, если ты не самый высокий драйвер (для тех обязательно, как написано в DDK)?
     
  7. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    в конце IoCompletion - зачем? IoCompleteRequest как раз сама дергает completion routines.
    если ты возвращаешь саксесс, тогда пакет и так завершится. есил ты возвращаешь море процессинг реквайред - тогда потом уже завершай.

    Вниз уже не попадает, но драйверв вышестоящие при чем тут?
    IoCompleteRequest в двух словах дергает IoCompletion Routines, копирует буффера там какие надо и освобождет память. Это если очень грубо.

    То есть если есть цепочка драйверов, то все фильтры должны вызывать IoCallDriver и передавать ниже, либо IoCompleteRequest и сами завершить пакет, а нижестоящий только complete может.
     
  8. Just_Neko

    Just_Neko New Member

    Публикаций:
    0
    Регистрация:
    12 фев 2009
    Сообщения:
    22
    IoCompleteRequest indicates the caller has completed all processing for a given I/O request and is returning the given IRP to the I/O Manager.When a driver has finished all processing for a given IRP, it calls IoCompleteRequest. The I/O Manager checks the IRP to determine whether any higher-level drivers have set up an IoCompletion routine for the IRP. If so, each IoCompletion routine is called, in turn, until every layered driver in the chain has completed the IRP. (с) DDK

    Если судить по этому копипасту из DDK, IoCompleteRequest говорит, что данный пакет обработан, передавай его обратно наверх, проходя все completion routines других драйверов, которые там расставлены (c STATUS_SUCCESS естественно)

    STATUS_MORE_PROCESSING_REQUIRED возвращается, если с пакетом больше ничего не надо делать, т.е. вышестоящие и нижестоящие его не получат. Если вернуть STATUS_SUCCESS, пакет irp пойдёт дальше

    при том, что вызов процедуры IoCompleteRequest и возврат STATUS_SUCCESS передадут пакет вышестоящим. Единственное, что я не понял, STATUS_MORE_PROCESSING_REQUIRED надо возвращать процедуре, вызывающей IoCompleteRequest, или устанавливать его в Irp->IoStatus.Status перед вызовом IoCompleteRequest?
     
  9. Just_Neko

    Just_Neko New Member

    Публикаций:
    0
    Регистрация:
    12 фев 2009
    Сообщения:
    22
    В нескольких примерах по написанию драйверов-фильтров видел, например, при перехвате IRP_MJ_CREATE завершение процедуры обработки с помощью

    return CompleteRequest(Irp, STATUS_SUCCESS, 0);
    ,где
    NTSTATUS CompleteRequest(PIRP Irp, NTSTATUS status, ULONG_PTR info)
    {
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = info;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
    }

    Разве в этом случае пакет не остановит свое движение вниз по стеку драйверов и не начнет двигаться обратно вверх, проходя через все IoCompletion'ы, установленные ранее?
    Я думал, более логично использовать

    IoSkipCurrentIrpStackLocation(Irp);
    return IoCallDriver(((PHOOK_EXTENSION)DeviceObject->DeviceExtension)->FileSystem,Irp);

    чтобы пакет достиг самого нижнего драйвера носителя (в моём случае диска)
     
  10. Just_Neko

    Just_Neko New Member

    Публикаций:
    0
    Регистрация:
    12 фев 2009
    Сообщения:
    22
    Огромная просьба ответить, последний вопрос до сих пор актуален
     
  11. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
  12. Just_Neko

    Just_Neko New Member

    Публикаций:
    0
    Регистрация:
    12 фев 2009
    Сообщения:
    22
    Прочитал

    И всё-таки можно узнать, почему в драйверах-фильтрах для обработки не своих пакетов повсеместно используют return CompleteRequest(pIrp, STATUS_SUCCESS, 0);
    где NTSTATUS CompleteRequest(PIRP Irp, NTSTATUS status, ULONG_PTR info)
    {
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = info;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
    }
    Ведь это не позволит пройти пакету дальше, он вернётся по стеку драйверов обратно отправителю, пройдя все установленные ранее IoCompletion, и не достигнет устройства?
     
  13. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    Как драйверы эти в народе кличутся? Правильно - фильтры, а что фильтры делают?;)
     
  14. Just_Neko

    Just_Neko New Member

    Публикаций:
    0
    Регистрация:
    12 фев 2009
    Сообщения:
    22
    Фильтры могут обрабатывать данные, идущие как до устройства, так и от него
    Так я всё-таки прав или нет, в данном случае данные устройства не достигнут? IRP к нему ведь придёт до того, как дойдёт до устройства, а ему он дальше пакет получается не передаст? Кстати, как вообще регулировать, каким по счету в стеке драйверов идёт твой фильтр?
     
  15. Just_Neko

    Just_Neko New Member

    Публикаций:
    0
    Регистрация:
    12 фев 2009
    Сообщения:
    22
    Вопрос актуален, прошу всех знающих помочь