Проблема: ZwQueryDirectoryFile vs ReturnSingleEntry==TRUE

Тема в разделе "WASM.BEGINNERS", создана пользователем test555, 22 дек 2008.

  1. test555

    test555 New Member

    Публикаций:
    0
    Регистрация:
    7 дек 2007
    Сообщения:
    241
    Кратко: драйвер, перехват этой функции, обработчик FileBothDirectoryInformation

    Я пробегаюсь по всем NextEntryOffset пока они не нулевые, если файл есть, меняю в соотв. с алгоритмом (в зависимости от того где файл находится).
    Так вот вышла бага небольшая, решить не знаю как.

    Суть в том, что если потайной файл лежит в обычной директории, то где бы он ни был (в начале, а фактически не в начале, т.к. первый файл "..", середине или конце, обработчик работает корректно. А если это корень диска, то происходит такая фигня:

    Вначале вызывается ZwQueryDirectoryFile с параметром ReturnSingleEntry==TRUE и функция выдает только первый по списку файл. А потом спрашивает еще раз, и дает все остальные
    Итак, в описании функции про один из параметров сказано:
    ReturnSingleEntry
    Set to TRUE if only a single entry should be returned, FALSE otherwise. If this parameter is TRUE, ZwQueryDirectoryFile returns only the first entry that is found.


    Баг заключается в том, что если наш скрываемый файл в директории диска (допустим флешка) первый, то нам приходится возвращять что файл не найден, таким образом опрос остальных файлов не происходит и получается пустая директория.

    Я не могу придумать пути решения, кроме как очень сложных, что при таком запросе в обработчике сделать запрос на остальные имена файлов, взять первый из этого списка и воткнуть его вместо скрываемого... Но слишком касячно.

    Как вариант забить.. Но интересно было бы узнать пути решения, уверен что не я один на это наткнулся.

    Спасибо.
     
  2. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.317
    смотри такая вещь... ты делаешь "подмену" функции на свой обработчик... почему не делать так:
    Код (Text):
    1. NewZwQueryDirectoryFile(... ReturnSingleEntry ...)
    2. {
    3.  if(!ReturnSingleEntry)
    4.  {
    5.   NTSTATUS ret = OldZwQueryDirectoryFile(... ReturnSingleEntry ...);
    6.   while(...)
    7.   {
    8.     // Обработка результата
    9.     if(flag) // Сдвинуть адрес структуры результата на смещение первого элемента =) (см. ниже)
    10.   }
    11.  }
    12.  else
    13.  {
    14.    NTSTATUS ret = OldZwQueryDirectoryFile(... TRUE ...); // вернется первая запись
    15.    if(...) // Сравнить эту запись с файлом, который нужно спрятать, если не тот, то вернуть окей
    16.    { return ret; }
    17.    else
    18.    {
    19.      NTSTATUS ret1 = OldZwQueryDirectoryFile(... FALSE ...);
    20.      // Взять первую запись отсюда и подменить ею первый в списке файл
    21.      flag = true; // Установить флаг, чтобы при вызове с FALSE не выдавалась два одинаковых вторых файла
    22.    }
    23.  }
    24. }
    извини за херовый код... просто на работе сижу, мало времени делать все красиво... палюсь... ;)
     
  3. test555

    test555 New Member

    Публикаций:
    0
    Регистрация:
    7 дек 2007
    Сообщения:
    241
    Rel? спасибо.. Я нечто похожее хотел сообразить...

    Еще наблюдения:
    Если директория - диск, то при обновлении в проводнике:
    1. Вызывается ZwQueryDirectoryFile(... ReturnSingleEntry == TRUE ...) - перечисляется первый файл
    2. Вызывается ZwQueryDirectoryFile(... ReturnSingleEntry == FALSE ...) (и еще пока не изучил все передаваемые параметры), перечисляются файлы начиная со второго. Возвращяемое значение оригинальной функции ==0
    3. Потом еще раз вызывается пункт 2, опять таки не изучил все параметры, но уже оригинальная функция возвращяет
    0x80000006
    STATUS_NO_MORE_FILES
    (но идет перечисление всех файлов, начиная со второго).

    Касяк в том был, что если нужно скрыть на диске, и файл идет второй (случай если файл первый еще не отлажен), то в пункте 2 я сдвигаю адрес структуры вперед до начала след. записи (т.к. в пункте 2 нужный файл идут уже первым в списке), функция возвращяет сдвинутый указатель.
    Но файл показывается в проводнике.
    Да, забыл про пункт 3, я там тоже сдвигаю указатель, проверяю, сдвиг идет корректно, но файл по-прежднему показывается.

    В обычной папке все работает прекрасно.. Это лишь особенности дисков....

    Вечером проверю, какие параметры передеются в функции, чтобы та поняла, с какого файла нумеровать и почему пункт 3 возвращяет такой статус..

    Вот такие вот проблемки... Проблему решил пока тем, что хранить все буду в папке..
     
  4. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.317
    залогируй входные параметры... всмысле выведи их в файл и посмотри, там наверняка понятнее будет, что он делает и зачем... описание функции можно посмотреть в MSDN:
    http://msdn.microsoft.com/en-us/library/ms801001.aspx
    вообще, если туда последним параметром посылать FALSE, то она начинает перечисление с файла на котором закончила... и еще сама функция может вызываться с параметром ReturnSingleEntry = TRUE, то есть возвращает с каждым вызовом только один файл, что значит что из эксплорера или проводника она может вызываться в цикле пока не вернет STATUS_NO_MORE_FILES... к тому же она может возвращать разные структуры, опять же через входные параметры (там инфу о директориях, о файлах и тд)... там допустим во втором вызове перечисляются все оставшиеся файлы, а затем в третьем вызове ещё что-то, чего в этой директории нет, или просто для контроля, что мол все файлы были перечислены... :) в любом случае нужно бы "лог" входных параметров снять...
     
  5. test555

    test555 New Member

    Публикаций:
    0
    Регистрация:
    7 дек 2007
    Сообщения:
    241
    Rel, спасибо. Как вновь до этого доберусь и разберусь - опишу проблему в подробноостях и ее решение, если таковое будет..