Пишу программу по Ms-Rem'ой статье про Ring-0.Возникла проблема с функцией NtQueryDirectoryFile.Ставлю на неё перехват при малом количестве файлов,отображаемых Explorer'ом всё OK, но стоит зайти в папку где много файлов комп уходит в reboot.Вот код функции перехвата: NTSTATUS NewNtQueryDirectoryFile ( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG FileInformationLength, IN FILE_INFORMATION_CLASS FileInformationClass, IN BOOLEAN ReturnSingleEntry, IN PUNICODE_STRING FileName OPTIONAL, IN BOOLEAN RestartScan) { ULONG NextOff=0; KIRQL irql = KeGetCurrentIrql(); LPSTR fileInf=FileInformation; Result=TrueNtQueryDirectoryFile(FileHandle,Event,ApcRoutine,ApcContex t,IoStatusBlock,FileInformation,FileInformationLength,FileInformationC lass,ReturnSingleEntry,FileName,RestartScan); KeAcquireSpinLock(&MySpinLock,&irql); switch(FileInformationClass) { case 0x0003: while((((PFILE_BOTH_DIRECTORY_INFORMATION)fileInf)->NextEntryOffset)!= 0) { NextOff=((PFILE_BOTH_DIRECTORY_INFORMATION)fileInf)->NextEntryOffset; fileInf+=((PFILE_BOTH_DIRECTORY_INFORMATION)fileInf)->NextEntryOffset; } break; default: break; } KeReleaseSpinLock(&MySpinLock,irql); return Result; } Если закомментировать while то всё OK.Спасибо.
обьяви PFILE_BOTH_DIRECTORY_INFORMATION fileInf,NextOff; вместо LPSTR может тогда легче станет Код (Text): PFILE_BOTH_DIRECTORY_INFORMATION fileInf; while(!fileInf->NextEntryOffset) { ((char*)fileInf)+=fileInf->NextEntryOffset; } и смотри в отладчике , что там и как
""и смотри в отладчике , что там и как "" Можно ли SoftIce'ом приаттачится к драйверу.Если это так то plz черканите пару строк как это можно сделать. "обьяви PFILE_BOTH_DIRECTORY_INFORMATION fileInf,NextOff; " Могу ошибаться,но как мне кажется,в твоём случае придётся инициализировать два объекта,размером со структуру PFILE_BOTH_DIRECTORY_INFORMATION,которые займут 2xsizeof(PFILE_BOTH_DIRECTORY_INFORMATION)в памяти.В моём же случае 2xsizeof(ULONG),что меньше.
Почему мы всё равно в конце концов работаем с указателями... А если делать парсинг не только FileBothDirectoryInformation, а ещё FileDirectoryInformation, FileFullDirectoryInformation, FileNamesInformation ?? В таком случае 2 двордами можно спокойно обойтись. Хотя для лучшей читабельности кода можна и все структуры обьявить. sizeof(PFILE_BOTH_DIRECTORY_INFORMATION) == sizeof(ULONG)
Да, ну и сморозил же я,только сейчас дошло. Но можно сохранить дворд если не объявлять fileInf,а сделать так: FileInformation+=((PFILE_BOTH_DIRECTORY_INFORMATION)FileInformation)-> NextEntryOffset;
Удивительно как этот код вообще где-то работает. В нем нет ни проверок на успешность вызова NtQueryDirectoryFile ни обработки других классов информации ни даже корректной обработки всех ситуаций возникающих при скрытии. Держи пример обработчика который скрывает все файлы имена которых начинаются с "_" Код (Text): NTSTATUS NewZwQueryDirectoryFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG FileInformationLength, IN FILE_INFORMATION_CLASS FileInformationClass, IN BOOLEAN ReturnSingleEntry, IN PUNICODE_STRING FileName OPTIONAL, IN BOOLEAN RestartScan) { NTSTATUS status = TrueZwQueryDirectoryFile(FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, FileInformation, FileInformationLength, FileInformationClass, ReturnSingleEntry, FileName, RestartScan); if (NT_SUCCESS(status)) { PFILE_FULL_DIRECTORY_INFORMATION FileDirectoryInfo, LastFileDirectoryInfo; PFILE_FULL_DIRECTORY_INFORMATION LastFileFullDirectoryInfo, FileFullDirectoryInfo; PFILE_BOTH_DIRECTORY_INFORMATION LastFileBothDirectoryInfo, FileBothDirectoryInfo; PFILE_NAMES_INFORMATION LastFileNamesInfo, FileNamesInfo; ULONG Offset = 0; switch (FileInformationClass) { case FileDirectoryInformation : FileDirectoryInfo = NULL; do { FileDirectoryInfo = (PVOID)((ULONG)FileInformation + Offset); LastFileDirectoryInfo = FileDirectoryInfo; if (FileDirectoryInfo->FileName[0] == 0x5F00) { if (!FileDirectoryInfo->NextEntryOffset) { if (LastFileDirectoryInfo) LastFileDirectoryInfo->NextEntryOffset = 0; else status = STATUS_NO_SUCH_FILE; return status; } else if (LastFileDirectoryInfo) LastFileDirectoryInfo->NextEntryOffset += FileDirectoryInfo->NextEntryOffset; } Offset += FileDirectoryInfo->NextEntryOffset; } while (FileDirectoryInfo->NextEntryOffset); break; case FileFullDirectoryInformation : FileFullDirectoryInfo = NULL; do { LastFileFullDirectoryInfo = FileFullDirectoryInfo; FileFullDirectoryInfo = (PVOID)((ULONG)FileInformation + Offset); if (FileFullDirectoryInfo->FileName[0] == 0x5F00) { if (!FileFullDirectoryInfo->NextEntryOffset) { if (LastFileFullDirectoryInfo) LastFileFullDirectoryInfo->NextEntryOffset = 0; else status = STATUS_NO_SUCH_FILE; return status; } else if (LastFileFullDirectoryInfo) LastFileFullDirectoryInfo->NextEntryOffset += FileFullDirectoryInfo->NextEntryOffset; } Offset += FileFullDirectoryInfo->NextEntryOffset; } while (FileFullDirectoryInfo->NextEntryOffset); break; case FileBothDirectoryInformation : FileBothDirectoryInfo = NULL; do { LastFileBothDirectoryInfo = FileBothDirectoryInfo; FileBothDirectoryInfo = (PVOID)((ULONG)FileInformation + Offset); if (FileBothDirectoryInfo->FileNameLength > 1 && FileBothDirectoryInfo->FileName[0] == 0x5F00) { if (!FileBothDirectoryInfo->NextEntryOffset) { if (LastFileBothDirectoryInfo) LastFileBothDirectoryInfo->NextEntryOffset = 0; else status = STATUS_NO_SUCH_FILE; return status; } else if (LastFileBothDirectoryInfo) LastFileBothDirectoryInfo->NextEntryOffset += FileBothDirectoryInfo->NextEntryOffset; } Offset += FileBothDirectoryInfo->NextEntryOffset; } while (FileBothDirectoryInfo->NextEntryOffset); break; case FileNamesInformation : FileNamesInfo = NULL; do { LastFileNamesInfo = FileNamesInfo; FileNamesInfo = (PVOID)((ULONG)FileInformation + Offset); if (FileNamesInfo->FileName[0] == 0x5F00) { if (!FileNamesInfo->NextEntryOffset) { if(LastFileNamesInfo) LastFileNamesInfo->NextEntryOffset = 0; else status = STATUS_NO_SUCH_FILE; return status; } else if (LastFileNamesInfo) LastFileNamesInfo->NextEntryOffset += FileNamesInfo->NextEntryOffset; } Offset += FileNamesInfo->NextEntryOffset; } while (FileNamesInfo->NextEntryOffset); break; } } return status; }
И кстати, зачем ты в своем коде использовал спинлоки? От них в данном случае все только тормозить будет. Синхронизация тут не нужна, так как никто другой не будет обращаться к модифицируемой информации.
можна и так Код (Text): ULONG Offset = 0; ULONG PrevItem; while(((PFILE_BOTH_DIRECTORY_INFORMATION)FileInformation)->NextEntryOf fset != 0) { Offset = (ULONG)FileInformation; (ULONG)FileInformation = Offset + ((PFILE_BOTH_DIRECTORY_INFORMATION)FileInformation)->NextEntryOffset; }
Предпологал,что другой код обращается в NewZwQueryDirectoryFile и что-то меняет в ней.Ещё раз спасибо.
Наверное должно быть так ?) Offset += FileDirectoryInfo->NextEntryOffset; А то сейчас скажет что там еррор =)
Да, но зачем нам Offset: //ULONG Offset = 0; ULONG PrevItem; while(((PFILE_BOTH_DIRECTORY_INFORMATION)FileInformation)->NextEntryOf fset != 0) { //Offset = (ULONG)FileInformation; (ULONG)FileInformation +=((PFILE_BOTH_DIRECTORY_INFORMATION)FileInformation)->NextEntryOffset ; }
Тогда так(экономим один дворд ): //ULONG Offset = 0; ULONG PrevItem; while(((PFILE_BOTH_DIRECTORY_INFORMATION)FileInformation)->NextEntryOf fset != 0) { //Offset = (ULONG)FileInformation; PrevItem=((PFILE_BOTH_DIRECTORY_INFORMATION)FileInformation)->NextEntr yOffset; (ULONG)FileInformation +=((PFILE_BOTH_DIRECTORY_INFORMATION)FileInformation)->NextEntryOffset ; }
От уменьшения размеров переменных в стеке ничего лучше не станет, а вот читабельность кода весьма важный фактор. Раньше я тоже писал подобным стилем, но сейчас взглянул на свои исходники годовой давности и понял что нифига в них не понимаю. Вот теперь стараюсь читабельный код писать.
Кстати, варианты с while(((PFILE_BOTH_DIRECTORY_INFORMATION)FileInformation)->NextEntryOf fset != 0) неправильны. Так как может быть ситуация, когда в папке только один файл который и нужно скрывать, в этом случае его NextEntryOffset == 0 и он не будет скрыт.