Привет фсем! Что-то я, наверное, туплю.... Заменяю настоящую функцию NtOpenFile: Код (Text): NTSTATUS NewNtOpenFile (OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG ShareAccess, IN ULONG OpenOptions ) { LPWSTR OpenedFileName; __try { OpenedFileName = ObjectAttributes->ObjectName->Buffer; if (IsAdded (ObjectsList, OpenedFileName)) { DPRINT ("%S: Access denided", OpenedFileName); return STATUS_ACCESS_DENIED; } else { DPRINT ("%S: Access OK", OpenedFileName); return TrueNtOpenFile (FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock,ShareAccess,OpenOptions); } } __except(EXCEPTION_EXECUTE_HANDLER) { DPRINT("Exception on NewNtOpenFile"); return STATUS_INVALID_PARAMETER; } } В DbgView выдаются сообщения типа "D:\Games: Access OK" и "C:\BP: Access denided". Но директория все равно видна и не блокируется!!! В чем дело?
Задача: есть некий список директорий и файлов (ObjectsList), реализация неважна. Есть перехват функции NtOpenFile. В ней нужно проверить наличие в списке открываемой директории или файла функцией IsAdded (реализация опять же неважна, т.к. она точно работает правильно). В случае, если в этом списке открываемый файл/директория есть, заблокировать к ней/ему доступ.
Возможно, директория видна потому, что список файлов и вложенных директорий возвращается функциями FindFirstFileEx, FindNextFile, которые обращаются к NtQueryDirectoryFile. Причем для этого нужен Handle папки, в которой находится скрываемая папка или файл. А если директория открывается не функцией NtOpenFile, а функцией NtCreateFile?
Дело еще в том, что абсолютно тот же самый код (просто с другой реализацией IsAdded, что несущественно) месяц назад работал отлично! А вот про это я забыл. Спасибо, попробую.
IsAdded (ObjectsList, OpenedFileName)) функцию выкладывай и еще давай , как хук ставишь А то дал код типа int somefunc(int somepar1, int somepar2) и спрашиваешь почему функция не работает? Телепатов нет
В общем дело действительно в функциях, которые отвечают за работу односвязного списка. Вот исходный текст, что в нем неправильно? Общий смысл такой: драйверу приходит структура из ринг3, где одно из полей - путь к директории, которую надо заблокировать. Типы: Код (Text): typedef struct _blockedObjectData { LPWSTR DirPath; .... }blockedObjectData, *PblockedObjectData; typedef struct _ObjectList { PVOID NextItem; LPWSTR FileName; } TObjectList, *PObjectList; PObjectList ObjectsList = NULL; typedef struct _DRIVERDATA { int driverAction; blockedObjectData bObjectData; } DRIVERDATA, *PDRIVERDATA; Сам код: Код (Text): NTSTATUS DriverDispatcher( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) ... pisl = IoGetCurrentIrpStackLocation(Irp); if ( pisl->MajorFunction == IRP_MJ_WRITE) { ... LPWSTR AddingString = NULL; Data = Irp->UserBuffer; __try { switch(Data->driverAction) { case 1: AddingString = Data->bObjectData.DirPath; DPRINT ("AddingString = %S", AddingString); if (!IsAdded (ObjectsList, AddingString)) { DPRINT ("Item %S is not added\n",AddingString); AddItem (&ObjectsList, AddingString); //AddItem(&ObjectsList, L"\\??\\C:\\BP\\"); //ВОТ ТАК РАБОТАЕТ! } else DPRINT ("Item %S is already added\n",Data->bObjectData.DirPath); break; Функции для работы с односвязным списком: Код (Text): BOOLEAN IsAdded(PObjectList List, LPWSTR CheckedFileName) { PObjectList Item = List; while (Item) { DPRINT ("In List: %S", Item->FileName); if (wcsncmp (Item->FileName,CheckedFileName, wcslen(CheckedFileName)) == 0) return TRUE; Item = Item->NextItem; } return FALSE; } void AddItem(PObjectList *List, LPWSTR AddingFileName) { PObjectList wNewItem; wNewItem = ExAllocatePool(NonPagedPool, sizeof(TObjectList)); wNewItem->NextItem = *List; *List = wNewItem; wNewItem->FileName = AddingFileName; DPRINT ("Adding %S", wNewItem->FileName); return; } В итоге валятся одни исключения((
думаю, вот тут ошибка:wNewItem->FileName = AddingFileName; Когда ты непосредственно пишешь L"\\??\\C:\\BP\\" - выделяется память, доступная для чтения из драйвера при проверке списка. А когда сохраняешь адрес строки (AddingString) и потом пытаешься прочитать эту строку, адрес AddingString оказывается недоступен для чтения и приводит к исключению. Выделяй память под строку wNewItem = ExAllocatePool(NonPagedPool, 4 + 512); где 512 - место под строку, и в это место копируй имя директории. Эта память не будет приводить к исключениям. Код (Text): typedef struct _ObjectList { PVOID NextItem; WCHAR FileName[256]; } TObjectList, *PObjectList; Естественно, надо будет wNewItem->FileName = AddingFileName; заменить на wcscpy (wNewItem->FileName, AddingFileName);
Спасибо большое, все работает! Я и раньше делал wcscpy (wNewItem->FileName, AddingFileName);, но забывал выделить память! Только, наверное, wNewItem->FileName = ExAllocatePool(NonPagedPool, 4 + wcslen(AddingFileName)); ?
Можно и так выделять. Просто код будет дольше работать (лишний вызов wcslen). И в функции IsAdded можно заменить wcsncmp на wcscmp, опять же это избавляет от необходимости вызова wcslen при проверке списка. P.S. Хотя если количество элементов списка велико, то выделение памяти ровно под длину строки позволит сэкономить некоторое количество nonpaged-памяти. Есть ли в этом смысл - не знаю... P.P.S. А чего это ты не проверяешь, какое значение вернула ExAllocatePool? Количество памяти в кернеле не так велико, как в юзере, тем более памяти nonPaged. Вполне можешь и получить ноль (ошибку выделения) в результате вызова ExAllocatePool, что неизбежно приведет к исключению.
Так я же выделил уже память под структуру: Код (Text): PObjectList wNewItem; wNewItem = ExAllocatePool(NonPagedPool, sizeof(TObjectList)); Код (Text): А чего это ты не проверяешь, какое значение вернула ExAllocatePool? Надо будет добавить... Привык, что под ринг3 память под структуры выделяется 100%
Если ее не выделять, то при выполнении строчки wcscpy (wNewItem->FileName, AddingFileName); валится синий экран