Фильтр логического диска

Тема в разделе "WASM.NT.KERNEL", создана пользователем DeeoniS, 13 янв 2007.

  1. DeeoniS

    DeeoniS New Member

    Публикаций:
    0
    Регистрация:
    6 авг 2004
    Сообщения:
    132
    Есть драйвер который становится в стек логического диска C:\. Становится то он хорошо, а вот IRP плохо обрабытавает - после нескоторого времени работы WinDbg говорит следующие:
    Код (Text):
    1. Access violation - code c0000005 (!!! second chance !!!)
    2. nt!NtWriteFile+0x321:
    3. 8057a29f ff530c           call    dword ptr [ebx+0xc]
    Функция обработки IRP такая:
    Код (Text):
    1. NTSTATUS
    2. DtdHookRoutine(
    3.     PDEVICE_OBJECT HookDevice,
    4.     IN PIRP Irp
    5.     )
    6. {
    7.     PIO_STACK_LOCATION  currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
    8.     PHOOK_EXTENSION     hookExt;
    9.  
    10.     //
    11.     // Point at the device extension, which contains information on which
    12.     // file system this IRP is headed for
    13.     //
    14.     hookExt = HookDevice->DeviceExtension;
    15.  
    16.     switch (currentIrpStack->MajorFunction)
    17.     {
    18.     case IRP_MJ_CREATE:
    19.    
    20.         DbgPrint("dtd!DtdHookRoutine: currentIrpStack->MajorFunction = IRP_MJ_CREATE\n");
    21.     break;
    22.  
    23.     case IRP_MJ_SET_INFORMATION:
    24.  
    25.         DbgPrint("dtd!DtdHookRoutine: currentIrpStack->MajorFunction = IRP_MJ_SET_INFORMATION\n");
    26.     break;
    27.  
    28.     default:
    29.    
    30.         DbgPrint("dtd!DtdHookRoutine: currentIrpStack->MajorFunction = other\n");
    31.     break;
    32.     }
    33.  
    34.     IoCopyCurrentIrpStackLocationToNext(Irp);
    35.  
    36.     return IoCallDriver( hookExt->FileSystem, Irp );
    37. }
    В чем может быть проблема проблема???
     
  2. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Возможно прямого отношения к багу это и не имеет, но IoCopyCurrentIrpStackLocationToNext без последующего IoSetCompletionRoutine - это баг по-любому.

    Когда IRP будет завершаться, то будет вызвана IO_STACK_LOCATION.CompletionRoutine, но у тебя там мусор.

    В общем случае, либо так:

    IoCopyCurrentIrpStackLocationToNext
    IoSetCompletionRoutine
    IoCallDriver

    либо так

    IoSkipCurrentIrpStackLocation
    IoCallDriver
     
  3. DeeoniS

    DeeoniS New Member

    Публикаций:
    0
    Регистрация:
    6 авг 2004
    Сообщения:
    132
    Пробовал и IoSkipCurrentIrpStackLocation, тот же баг. Только когда используешь эту функцию что-то странное происходит с IRP.
    Код (Text):
    1.     // Сейчас Irp->StackCount == 9
    2.     //    Irp->CurrentLocation == 9
    3.     IoSkipCurrentIrpStackLocation(Irp);
    4.     // После вызова IoSkipCurrentIrpStackLocation
    5.     //  Irp->CurrentLocation == 10
    6.  
    7.     return IoCallDriver( hookExt->FileSystem, Irp );
    8.     // А после IoCallDriver()
    9.     //  Irp->CurrentLocation == 11
    Мне кажется это както неправильно, или я ошибаюсь?
     
  4. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Ну значит баг не в этом, но это тоже баг ;) А с IRP всё нормально. Если мы делаем скип, то не ставим CompletionRoutine и таким образом после вызова IoCallDriver полностью теряем IRP... "мы его теряем" (с) :)))

    Т.е. после того как IoCallDriver вернётся, IRP уже может быть завершён, а может ещё нет. Если нет, то в Irp->CurrentLocation может быть все что угодно от 0 до Irp->StackCount+1, если да, то память под IRP уже могла быть передана кому-то другому и там вообще мусор.

    А приращение на единицу после IoSkipCurrentIrpStackLocation нормальное.

    Подробности можно глянуть тут: http://www.wasm.ru/article.php?article=drvw2k15
     
  5. DeeoniS

    DeeoniS New Member

    Публикаций:
    0
    Регистрация:
    6 авг 2004
    Сообщения:
    132
    да, я читал твою статью... очень хорошо написанно, хотя и очень много сразу потому еще не все стало на свои места :)

    А в чем может быть баг... может есть какие мысли?

    вот кстати стек вызовов при виалюшене:
    Код (Text):
    1. STACK_TEXT:  
    2. f7d93d38 804df06b 00000890 00000000 00000000 nt!NtWriteFile+0x321
    3. f7d93d38 7c90eb94 00000890 00000000 00000000 nt!KiFastCallEntry+0xf8
    4. 0184f6c8 7c90e9ff 7c81100e 00000890 00000000 ntdll!KiFastSystemCallRet
    5. 0184f6cc 7c81100e 00000890 00000000 00000000 ntdll!ZwWriteFile+0xc
    6. 0184f72c 50042018 00000890 0184f768 0000004d kernel32!WriteFile+0xf7
    7. 0184fb6c 50041e81 0184fba0 0000004d 01a41238 wuaueng!Trace::CTraceCategory::WriteToFile+0xf8
    8. 0184fda4 500418f0 00000003 00000000 5004c2e8 wuaueng!Trace::CTraceCategory::Trace+0x131
    9. 0184fdc8 5004c2d2 0184fdf0 00000004 00000003 wuaueng!Trace::CDebugTrace::Trace+0x4b
    10. 0184fdf8 5004417a 00000010 01a40e98 01a40e98 wuaueng!CSusAgent::DispatchEvent+0x1a4
    11. 0184fe10 500440f7 00000001 00000010 01a40f6c wuaueng!CSusEventSystem::DispatchEvent+0x47
    12. 0184fe3c 5004461d 00000001 01a40e98 00000000 wuaueng!CSusEventSystem::ProcessRewaitHandle+0x68
    13. 0184fe5c 50044596 00000000 00000000 00000003 wuaueng!CSusEventSystem::ProcessTimeout+0x7d
    14. 0184fe80 50066898 50002000 7c80ac28 00000000 wuaueng!CSusEventSystem::Run+0x6d
    15. 0184ff18 500013f0 00000001 000e4ce0 500012a7 wuaueng!ServiceMain+0x20c
    16. 0184ff6c 010011cc 00000001 000e4ce0 00000000 wuauserv!ServiceMain+0xaf
    17. 0184ffa0 77deb48b 00000001 000e4ce0 0007e898 svchost!ServiceStarter+0x9e
    18. 0184ffb4 7c80b50b 000e4cd8 00000000 0007e898 ADVAPI32!ScSvcctrlThreadA+0x12
    19. 0184ffec 00000000 77deb479 000e4cd8 00000000 kernel32!BaseThreadStart+0x37
    Как видно ошибку провацирует wuauserv, т.е автоапдейт виндовс. В стеке нет моего фильтра.
     
  6. DeeoniS

    DeeoniS New Member

    Публикаций:
    0
    Регистрация:
    6 авг 2004
    Сообщения:
    132
    отключил службу автоапдейта... все равно падает. Но заметил особенность, что в стеке перед вызовом есть следующие функции: ntdll!KiFastSystemCallRet и nt!KiFastCallEntry. Как я понимаю это функции быстрого ввода/вывода. Я их никак не обрабатываю, но в FileMon'е Руссиновича они перехватываются. Может и мне надо перехватывать. Или это не то???
     
  7. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Нет. Это шлюзы в ядро. Если камень поддерживает инструкции sysenter/sysexit (или как их там), то, видимо, испльзуются эти функции при переходе ring3->ring0 и обратно. У меня камень без sysenter, поэтому точно сказать не могу, но судя по именам ничего другого они делать и не могут. Т.е. они исползуются при вызове любой функции переходящей в ядро и прямого отношения к багу тоже не имеют.

    Падает фдерная NtWriteFile при попытке обращения к какому-то параметру/полю структуры. Дизасмни свой ntoskrnl.exe. Разберись что происходит в районе NtWriteFile+0x321 и посмотри в отладчике.
     
  8. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Насчет SYSENTER вот топик: http://www.wasm.ru/forum/viewtopic.php?id=10962
     
  9. DeeoniS

    DeeoniS New Member

    Публикаций:
    0
    Регистрация:
    6 авг 2004
    Сообщения:
    132
    вообще поидее то что мой драйвер становиться в стек никак не должно влиять на NtWriteFile, т.к. насколько я понимаю NtWriteFile шлет запрос к девайсу логического диска, и как раз там начинает работать мой фильтр.

    Единственное что может падать (если придерживаться этой схемы), так это код который обрабатывает ответ от драйвера.
     
  10. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    DeeoniS
    а у тебя hookExt->FileSystem точно правильный?
    вообще, если в твоем драйвере что-то происходит, то это наверняка не в том куске кода, который ты запостил
     
  11. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    По одной строчке call dword ptr [ebx+0xc] сложно ориентироваться, но я таки попробую. Почти 100% падает при попытке вызвать Fast I/O Dispatch Routine. Вот очень сильно (на 99% ;)) упрощённый код NtWriteFile:

    Код (Text):
    1. NTSTATUS
    2. NtWriteFile(
    3.     IN HANDLE FileHandle,
    4.     ...
    5.     )
    6. {
    7.     ...
    8.     status = ObReferenceObjectByHandle( FileHandle,
    9.                                         0L,
    10.                                         IoFileObjectType,
    11.                                         requestorMode,
    12.                                         (PVOID *) &fileObject,
    13.                                         &handleInformation);
    14.     ...
    15.     deviceObject = IoGetRelatedDeviceObject( fileObject );
    16.     ...
    17.     fastIoDispatch = deviceObject->DriverObject->FastIoDispatch;
    18.     ...
    19.     if (...) {
    20.         ...
    21.         if (...) {
    22.             ...
    23.             if ( fastIoDispatch->FastIoWrite( ... ) ) {         <<<<-----!!!!!!!!
    24.                 ...
    25.             }
    26.             ...
    27.         }
    28.         ...
    29.     }
    30.     ...
    31.     return status;
    32. }
     
  12. DeeoniS

    DeeoniS New Member

    Публикаций:
    0
    Регистрация:
    6 авг 2004
    Сообщения:
    132
    Four-F
    т.е. получается что всетаки надо перехватывать функции быстрого ввода/вывода. Просто я писал драйвер ориентируясь на FileMon Руссиновича. Там он в DriverEntry перехватывает быстрый в/в:
    Код (Text):
    1. //
    2. // This Filemon's Fast I/O dispatch table. Note that NT assumes that
    3. // file system drivers support some Fast I/O calls, so this table must
    4. // be present for an file system filter driver
    5. //
    6. FAST_IO_DISPATCH    FastIOHook = {
    7.     sizeof(FAST_IO_DISPATCH),
    8.     FilemonFastIoCheckifPossible,
    9.     FilemonFastIoRead,
    10.     FilemonFastIoWrite,
    11.     FilemonFastIoQueryBasicInfo,
    12.     //....
    13. };
    14.  
    15. NTSTATUS
    16. DriverEntry(
    17.     IN PDRIVER_OBJECT DriverObject,
    18.     IN PUNICODE_STRING RegistryPath
    19.     )
    20. {
    21.         //....
    22.  
    23.         DriverObject->FastIoDispatch = &FastIOHook;
    24.  
    25.         //....
    26. }
    а я этого не делаю, т.к. хотел для начала все максимально упростить.
     
  13. DeeoniS

    DeeoniS New Member

    Публикаций:
    0
    Регистрация:
    6 авг 2004
    Сообщения:
    132
    Nouzui
    hookExt->FileSystem точно правильный, если конечно где-то не затирается чем-нибудь, но это маловероятно
     
  14. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Да. Вот тут список того, что может влетать в драйверы томов:
    http://msdn2.microsoft.com/en-us/library/ms790755.aspx

    Но перехватывать нужно всё и просто редиректить в оригинальный драйвер. Это стандартный подход, как для "честных" фильтров, так и для хукающих.
     
  15. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    весело.. всегда думал, что fast io опционально, типа, SizeOfFastIoDispatch=0, и никаких проблем
    мда..
     
  16. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    О fast io нужно думать только, если с файловой системой дело имеешь.
     
  17. DeeoniS

    DeeoniS New Member

    Публикаций:
    0
    Регистрация:
    6 авг 2004
    Сообщения:
    132
    Four-F спасибо... Я так и думал что дело в этом. Завтра проверю, точно скажу.
     
  18. DeeoniS

    DeeoniS New Member

    Публикаций:
    0
    Регистрация:
    6 авг 2004
    Сообщения:
    132
    Дело было действительно в fast io, теперь не падает... вроде
     
  19. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    а как вообще определяется, можно ли использовать fast io
    по флагу FO_FILE_FAST_IO_READ в объекте файла?

    и в чем вообще смысл этих функций? почему они используются только для синхронных операций и при наличии кеширования?
     
  20. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Потому, что это и есть чтение/запись кешированного файла, т.е. просто копируются данные из кеша, который суть буфер в памяти. Смысл в том, что это гораздо быстрее чем создавать IRP, прогонять его через цепочку драйверов, заставляя их дергать данные с диска.

    Можно ли использовать fast io, определяет диспетчер ввода/вывода. И так как я сам про это мало что знаю ;), подробнее можно глянуть в IFS Kit в разделах "Introduction to File System Filter Drivers" и "OSR Technical Articles", а также в журнале "The NT Insider" на osronline.com.