Как обмануть на NTFS ZwQueryDirectoryFile?

Тема в разделе "WASM.WIN32", создана пользователем cresta, 14 апр 2006.

  1. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Ситуация такая:

    В отличие от fat32, в ntfs explorer запрашивает ZwQueryDirectoryFile с флагом ReturnSingleEntry при перечислении объектов в корне диска.

    Запрос с ReturnSingleEntry==TRUE происходит только один раз, для первого по алфавиту объекта в корне диска. Возможно, для него это способ определиться, есть что-либо в разделе или нет.

    Если пытаться скрыть первый по алфавиту объект, то explorer считает (imho), что там вообще ничего нет, и последующих вызовов для этого диска не присылает, т.е. перестает видеть вообще весь диск:dntknw: Если скрывать любой другой, кроме первого - все нормально скрывается.

    Как обмануть? Вообще, возможно скрыть первый объект, чтобы остальные оставались видимыми?

    Спасибо.
     
  2. Ms Rem

    Ms Rem New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2005
    Сообщения:
    1.057
    Адрес:
    С планеты "Земля"
    Код (Text):
    1. NTSTATUS __stdcall
    2.   NewZwQueryDirectoryFile(
    3.         IN HANDLE FileHandle,
    4.         IN HANDLE Event OPTIONAL,
    5.         IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
    6.         IN PVOID ApcContext OPTIONAL,
    7.         OUT PIO_STATUS_BLOCK IoStatusBlock,
    8.         OUT PVOID FileInformation,
    9.         IN ULONG FileInformationLength,
    10.         IN FILE_INFORMATION_CLASS FileInformationClass,
    11.         IN BOOLEAN ReturnSingleEntry,
    12.         IN PUNICODE_STRING FileName OPTIONAL,
    13.         IN BOOLEAN RestartScan)
    14. {
    15.     NTSTATUS status = TrueZwQueryDirectoryFile(FileHandle,
    16.                                                Event,
    17.                                                ApcRoutine,
    18.                                                ApcContext,
    19.                                                IoStatusBlock,
    20.                                                FileInformation,
    21.                                                FileInformationLength,
    22.                                                FileInformationClass,
    23.                                                ReturnSingleEntry,
    24.                                                FileName,
    25.                                                RestartScan);
    26.  
    27.     if (NT_SUCCESS(status))
    28.     {
    29.         PFILE_DIRECTORY_INFORMATION FileDirectoryInfo, LastFileDirectoryInfo;
    30.         ULONG  Offset = 0;
    31.         ULONG  NameLength;
    32.         PWCHAR FileName;
    33.  
    34.         if (ReturnSingleEntry)
    35.         {              
    36.             while (NT_SUCCESS(status))
    37.             {
    38.                 GetFileName(FileInformation, FileInformationClass, &FileName, &NameLength);
    39.  
    40.                 if (!RkIsFileHidden(FileName, NameLength)) break;
    41.  
    42.                 if (RestartScan) return STATUS_NO_MORE_FILES;
    43.                
    44.                 status = TrueZwQueryDirectoryFile(FileHandle,
    45.                                                   NULL,
    46.                                                   NULL,
    47.                                                   NULL,
    48.                                                   IoStatusBlock,
    49.                                                   FileInformation,
    50.                                                   FileInformationLength,
    51.                                                   FileInformationClass,
    52.                                                   TRUE,
    53.                                                   NULL,
    54.                                                   FALSE);              
    55.             }
    56.         } else     
    57.  
     
  3. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Значит, вместо эксплорера самому вызвать wQueryDirectoryFile для следующего за скрываемым?

    Понял, спасибо :)



    P.S.

    Кстати, насколько обязательно модифицировать возвращаемый IoStatusBlock? Его кто-нибудь проверяет?
     
  4. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    cresta

    Напишешь код, если не жалко можешь прислать сорец на мыло?
     
  5. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Если напишу...

    Что-то повторный вызов ZwQueryDirectoryFile с ReturnSingleEntry постоянно возвращает C0000003 для любых передаваемых параметров, в т.ч. и с RestartScan==TRUE :dntknw:
     
  6. Ms Rem

    Ms Rem New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2005
    Сообщения:
    1.057
    Адрес:
    С планеты "Земля"
    хз, у меня все работает. неправильно вызываешь значит.
     
  7. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Повторный вызов делаю так:


    Код (Text):
    1.                 if  (pInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY){
    2.                     uStr.Length = (USHORT)pInfo->FileNameLength;
    3.                     uStr.MaximumLength = uStr.Length + 2;
    4.                     uStr.Buffer = &pInfo->FileName[0];
    5.                     if ( ToHide(FileHandle, &uStr, IsParentProcess) ){
    6.                         if (ReturnSingleEntry) {
    7.                             if (RestartScan) {
    8.                                 IoStatusBlock->Status = STATUS_NO_MORE_FILES;
    9.                                 IoStatusBlock->Information = 0;
    10.                                 Status = STATUS_NO_MORE_FILES;
    11.                                 goto _ret;
    12.                             }
    13.                             _asm {
    14.                                 push    0
    15.                                 push    0
    16.                                 push    1
    17.                                 push    dword ptr [ebp+36]
    18.                                 push    dword ptr [ebp+32]
    19.                                 push    dword ptr [ebp+28]
    20.                                 push    dword ptr [ebp+24]
    21.                                 push    0
    22.                                 push    0
    23.                                 push    0
    24.                                 push    dword ptr [ebp+8]
    25.                                 call    dword ptr [TrueZwQueryDirectoryFile]
    26.                                 mov    [Status],eax
    27.                             }
    28.                             DbgPrint("Status = %08X", Status);
    29.                             goto _ret;
    30.                         }




    Пока сделал половинчатое решение: если ReturnSingleEntry был TRUE, сбрасываю его в FALSE, делаю первый вызов TrueZwQueryDirectoryFile, и затем вручную затираю выходной массив, так что в нем остается только один (следующий за скрываемым) объект.

    Папка видна, но недоступна ни для каких действий с ней (удаление, переименование, копирование, открытие)
     
  8. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Ms Rem



    Все верно, это я тут нахимичил :)

    Спасибо.