ntOpenFile + (Io)RtlVolumeDeviceToDosName = зависание...

Тема в разделе "WASM.NT.KERNEL", создана пользователем Progr, 26 ноя 2006.

  1. Progr

    Progr New Member

    Публикаций:
    0
    Регистрация:
    8 ноя 2006
    Сообщения:
    48
    Доброго времени суток, господа!
    Подскажите если кто знает:
    Использую связку ObReferenceObjectByHandle-(Io)RtlVolumeDeviceToDosName в перехватчеке ntOpenFile, но в момент выполнения (Io)RtlVolumeDeviceToDosName компьютер зависает...без БСОДа, просто виснет(хотя БСОД, наверное, рано или поздно появится).
    Тот же код в ntCreateFile и ntQueryDirectoryFile работает нормально.
    Вот это место:

    Код (Text):
    1.   PFILE_OBJECT file=0;
    2.   ns=ObReferenceObjectByHandle(*FileHandle,0,0,KernelMode,&file,NULL);
    3.   if (NT_SUCCESS(ns)) {
    4.     ns = RtlVolumeDeviceToDosName(file->DeviceObject, &uniDOSPath);
    5. ....
    Может кто сталкивался....
     
  2. gilg

    gilg New Member

    Публикаций:
    0
    Регистрация:
    19 май 2005
    Сообщения:
    527
    NtOpenFile и NtCreateFile обе просто вызывают IoCreateFile с разными параметрами, особенностей в перехвате быть не может никаких. Запости целиком перехваченную NtOpenFile
     
  3. Boola

    Boola New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2004
    Сообщения:
    24
    Адрес:
    Russia
    Progr
    в нутрях (Io)RtlVolumeDeviceToDosName происходит вызов NtOpenFile(oa->name=\\Device\\MountPointManager) , если это не обрабатывать, твой перехватчик будет зацикливаться.
     
  4. Progr

    Progr New Member

    Публикаций:
    0
    Регистрация:
    8 ноя 2006
    Сообщения:
    48
    Код (Text):
    1. PWCHAR GetFullPathByHandle(IN HANDLE hFile)
    2. {
    3.   char ParentDirectory[1024];
    4.   PWCHAR Name;
    5.   PUNICODE_STRING Parent=NULL;
    6.   ULONG BytesReturned;
    7.   UNICODE_STRING uDOSPath, uTail;
    8.   PFILE_OBJECT file=0;
    9.   wchar_t *uPos;
    10.   NTSTATUS ns;
    11.   SIZE_T neededSize;
    12.  
    13.   ParentDirectory[0]='\0';
    14.   Parent=(PUNICODE_STRING)ParentDirectory;
    15.  
    16.   RtlInitUnicodeString (&uTail, L"\\DEVICE\\HARDDISKVOLUME");
    17.   ns=ObReferenceObjectByHandle(hFile,0,0,KernelMode,&file,NULL);
    18.   if (!NT_SUCCESS(ns)) {
    19.       return NULL;
    20.   } else {
    21.     switch (*NtBuildNumber)
    22.     {
    23.         case 2195:  //win 2k
    24.             ns = RtlVolumeDeviceToDosName(file->DeviceObject, &uDOSPath);
    25.          break;
    26.         case 2600:  //win xp
    27.             ns = IoVolumeDeviceToDosName(file->DeviceObject, &uDOSPath);
    28.          break;
    29.         default:
    30.          return NULL;
    31.          break;
    32.     }
    33.     if (!NT_SUCCESS(ns)) {
    34.       return NULL;
    35.     } else {
    36.         ns=ObQueryNameString(file, (POBJECT_NAME_INFORMATION)ParentDirectory, sizeof(ParentDirectory), &BytesReturned);
    37.         if (!NT_SUCCESS(ns)) {
    38.             return NULL;
    39.         } else {
    40.               RtlUpcaseUnicodeString(Parent, Parent, FALSE);
    41.               uPos = wcsstr(Parent->Buffer, uTail.Buffer);
    42.               if (uPos) {
    43.                 neededSize = (Parent->Length-23 + uDOSPath.Length + 2) * 2;
    44.                 Name = (wchar_t *)ExAllocatePool(PagedPool, neededSize);
    45.                 RtlZeroMemory(Name, neededSize);
    46.                 wcsncpy(Name, uDOSPath.Buffer, uDOSPath.Length);
    47.                 wcsncat(Name, Parent->Buffer+23, Parent->Length-23);
    48.               }
    49.               else
    50.               {
    51.                   return NULL;
    52.               }
    53.         }
    54.         ExFreePool (uDOSPath.Buffer);
    55.     }
    56.     ObDereferenceObject(&file);
    57.   }
    58.   return Name;
    59. }
    60.  
    61. NTSTATUS NewNtOpenFile (
    62.   OUT PHANDLE             FileHandle,
    63.   IN ACCESS_MASK          DesiredAccess,
    64.   IN POBJECT_ATTRIBUTES   ObjectAttributes,
    65.   OUT PIO_STATUS_BLOCK    IoStatusBlock,
    66.   IN ULONG                ShareAccess,
    67.   IN ULONG                OpenOptions )
    68. {
    69.     PWCHAR wcsFileName, pPath;
    70.  
    71.     wchar_t *pdest;
    72.     wchar_t ch = ':';
    73.     UNICODE_STRING uniFileName;
    74.     NTSTATUS status = STATUS_SUCCESS;
    75.  
    76.     status = TrueNtOpenFile (FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock,ShareAccess,OpenOptions);
    77.  
    78.     if (!NT_SUCCESS(status)) return status;
    79.  
    80.     pPath=GetFullPathByHandle1 (*FileHandle);
    81.     if (pPath!=NULL) return status;
    82.  
    83.     pdest = wcsrchr(pPath, ch);
    84.     if (pdest > 0) {
    85.         RtlInitUnicodeString(&uniFileName, pdest-1);
    86.         if (IsHidden(uniFileName)) {
    87.                status = STATUS_OBJECT_NAME_NOT_FOUND;
    88.                goto done;
    89.         }
    90.     } else {
    91.     if (wcslen(wcsFileName) > 0)
    92.         RtlInitUnicodeString(&uniFileName, pPath);
    93.         if (IsHidden(uniFileName)) {
    94.                status = STATUS_OBJECT_NAME_NOT_FOUND;
    95.                goto done;
    96.         }
    97.     }
    98.     if (status==STATUS_OBJECT_NAME_NOT_FOUND) NtClose(FileHandle);
    99.     return status;
    100. }
    Немного многовато, но надеюсь поймете...

    А по-подробнее, не расскажете?
     
  5. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    сорцы win2k по-подробнее расскажут.
    Вроде 2 раза вызывается.
     
  6. Progr

    Progr New Member

    Публикаций:
    0
    Регистрация:
    8 ноя 2006
    Сообщения:
    48
    У меня их нет,
    Я имел ввиду как обработать описаный случай...
     
  7. Progr

    Progr New Member

    Публикаций:
    0
    Регистрация:
    8 ноя 2006
    Сообщения:
    48
    Boola
    Можно пример кода с корректной обработкой, упомянутой Вами ситуации?
     
  8. Boola

    Boola New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2004
    Сообщения:
    24
    Адрес:
    Russia
    Progr
    Можно пример кода с корректной обработкой, упомянутой Вами ситуации?

    Попробуй так

    Код (Text):
    1. NTSTATUS NewNtOpenFile ( )
    2. {
    3.     .....
    4.     if (wcsFileName<>"\\Device\\MountPointManager")
    5.    .....
    6. }
     
  9. Begemot

    Begemot New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2006
    Сообщения:
    79
    Не подскажете, нет ли подобных нюансов с ntCreateFile? Т.к. факт зацикливания имеется, но таже фильтрация не спасает...
    Заранее благодарен.
     
  10. Begemot

    Begemot New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2006
    Сообщения:
    79
    Boola
    Вы не в курсе, на счет ntCreateFile? Как избежать зацикливания в ntCreateFile используя
    ObReferenceObjectByHandle-(Io)RtlVolumeDeviceToDosName?
     
  11. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Begemot
     
  12. Begemot

    Begemot New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2006
    Сообщения:
    79
    n0name
    Это оно у автора работает :)
    Я просто сталкивался с подобной проблемой в CreateFile, но решить не удалось и просто интересно в чем проблема в Creat'e...
    Если кто знает, расскажите, боюсь что и у автора там могут объявиться грабли, о которых он пока не знает ;)
     
  13. Begemot

    Begemot New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2006
    Сообщения:
    79
    Кстати, такая ситуация возникала в CreateFile с OA->FileName=
    \Device\NetBT_Tcpip_{GUID}
    И что-то мне подсказывает, что это не единственный случай.
    Так как же избежать зацикливания при использовании (Io)RtlVolumeDeviceToDosName в Create/OpenFile?

    P.S. Пардон что лезу в чужую тему, просто вопрос близок к теме и данную проблему можно решить "раз и навсегда"...
     
  14. Boola

    Boola New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2004
    Сообщения:
    24
    Адрес:
    Russia
    Begemot
    И что-то мне подсказывает, что это не единственный случай.
    Так как же избежать зацикливания при использовании (Io)RtlVolumeDeviceToDosName в Create/OpenFile?


    Не пробовал выявить среди "не единственных случаев" нечто общее и решить "раз и навсегда"
     
  15. Begemot

    Begemot New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2006
    Сообщения:
    79
    Boola
    Боюсь, что "нечто общее" здесь только "/Device/blah blah blah"...
    Но это не для каждого случая подойдет.
     
  16. Begemot

    Begemot New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2006
    Сообщения:
    79
    Если честно, то вижу только один возможный вариант решения данной проблемы: отслеживать появление рекурсии с одним и тем же именем.
    Возможный путь реализации:
    - создание связанного списка элементов содержащих еще не отработанные имена переданные в CreateFile и идентефикатор данного потока (здесь я не уверен: возможно ли параллельное выполнение "копий" CreateFile; многопоточное?);
    - в начале CreateFile искать переданное в него имя в списке. По результатам поиска: продолжать выполнение обработчика, либо завершиться.
    - при окончательной отработки имени - удаляем это имя из списка.
    Сразу возникает вопрос: как обеспечить безопасный доступ к общим областям памяти(список, адрес первого элемента, возможно что-то еще)? Т.е. пока один поток работает с данными, обеспечить их неизменность и сохранность (и как при этом поведут себя остальные "претенденты"?)...
    Если кто знает решение проще/гибче и т.п. - выскажите, плиз.
     
  17. Begemot

    Begemot New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2006
    Сообщения:
    79
    Продолжая страшную историю ;)
    Немного покапавшись во всем этом деле пришел к выводу, что очевидного зацикливания не происходит и IoVolumeDeviceToDosName вроде бы отрабатывает, но после ее использования, драйвер перестает останавливаться и выгружаться.
    Так что же все-таки там происходит такого нехорошего?
    Кто-нибудь знает?
     
  18. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    если перехват осуществлялся через SDT, а RtlVolumeDeviceToDosName делает вызов напрямую, то какие тогда могут быть проблемы?
     
  19. Begemot

    Begemot New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2006
    Сообщения:
    79
    Nouzui
    Перехват, действительно, делался через SDT.
    Насчет "прямости" RtlVolumeDeviceToDosName ничего не знаю, хотя он вроде бы отрабатывает как положено, но после того, как она отработает, драйвер больше не останавливается...
     
  20. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    Begemot
    да я сам в этом плохо разбираюсь..
    вообще-то, стоит ли привязываться к досовым именам устройств, это тоже вопрос. можно легко назначить диску D: литеру A:, а сам дисковод примонтировать, например, на X: Для этого даже не надо ничего писать - в виндах уже предусмотренна утилитка "mountvol.exe"
    вообще, можно пойти другим путем - перебрать все стрки вида "\??\<буква>:" от A: до Z: и для каждого проверить наличие символической ссылки ZwQuerySymbolicLinkObject(). Тогда для каждой строки вернется либо ошибка, что указывает на то, что такого диска не существует, либо соответсвующая диску строка "DEVICE\HARDISKVOLUME"
    но я не уверен в том, что это полностью корректный способ..