Ситуация осложняется еще и там что опыта программирования в ядре не много. Драйвер ведет перехват NtClose вызова. Проверяет, является ли закрываемый объект файлом, если да, то получает имя файла, копирует его в буфер, сигнализирует юзермодному приложению, то в свою очередь забирает этот буфер. Драйвер+приложение довольно неплохо работали, отлавливая все закрываемые файлы. Однако нашлась бага. Если воткнуть флешку, то в скором времени получаем BSOD (IRQL_LESS_OR_NOT_EQUAL). Итак, подробнее код перехватчика, ключевой момент: Код (Text): NTSTATUS NewNtClose( IN HANDLE Handle) {NTSTATUS D, status; PFILE_OBJECT pFileObject=NULL; UNICODE_STRING unic_str; POBJECT_NAME_INFORMATION Obj_name=NULL; ANSI_STRING ansiStr; LARGE_INTEGER Wait; ULONG RES1, returned; KIRQL IRQLold, IRQLnew; RES1=0; if (ExTryToAcquireFastMutex(&g_fMutex)) { if ((g_fbNotifyRoutineSet == TRUE )) { //глобальный флаг -ведется ли мониторинг status = ObReferenceObjectByHandle(Handle, FILE_READ_ATTRIBUTES, *IoFileObjectType, KernelMode, &pFileObject, NULL ); //узнали, является ли файлом закрываемый хендл if (status ==0 ) { if ( pFileObject->WriteAccess ){//проверяем режим открытия status = ObQueryNameString(pFileObject->DeviceObject, NULL , 0 , &RES1); if ((RES1>0)&& (status ==0xc0000004 )) {// получаем имя устройства (узнаем размер и выделяем память под него Obj_name= (POBJECT_NAME_INFORMATION) ExAllocatePool(NonPagedPool, RES1); status = ObQueryNameString(pFileObject->DeviceObject, Obj_name , RES1 , &returned); IRQLold=KeGetCurrentIrql( ); DPRINT("%S %S, prior = %ld", Obj_name->Name.Buffer,pFileObject->FileName.Buffer, IRQLold); //выводим тукущий IRQL и имена закрываемых файлов и устройств // если исправить на (1==2) то BSOD нет if ((status==0)/*&&(IRQLold<2)*/&&(1==1) ) { Wait.LowPart = SEMAPHORE_TIMEOUT; Wait.HighPart = -1; //ожидание пока юзермодное приложение не скажет что забрало предыдущую порцию данных KeWaitForSingleObject(&g_pksemaphore,Executive, KernelMode, FALSE, &Wait); //копирует в глобальный буфер имя устройства RtlUnicodeStringToAnsiString( &ansiStr, &Obj_name->Name, TRUE ); RES1= (ansiStr.Length > 99? 99: ansiStr.Length); memset(g_buffer, 0 ,MAX_PATH_2); strncpy(g_buffer, ansiStr.Buffer, RES1); RtlFreeAnsiString(&ansiStr); // добавляем к строке путь файла RtlUnicodeStringToAnsiString( &ansiStr, &pFileObject->FileName, TRUE ); strcat(g_buffer,ansiStr.Buffer); RtlFreeAnsiString(&ansiStr); DPRINT("%s, LEN = %ld", g_buffer, RES1); // сигнализируем юзермоду что данные можно брать KeSetEvent(g_pkEventObject, 0, FALSE); } ExFreePool(Obj_name); } } } if (pFileObject!=NULL) ObDereferenceObject(&pFileObject); } ExReleaseFastMutex (&g_fMutex); } D = TrueNtClose(Handle); return D; } Глобальный буфер выделяю при загрузке дрова: Код (Text): g_buffer= ExAllocatePool(NonPagedPool, MAX_PATH_2); Данные забираются IOCTRL запросом Код (Text): NTSTATUS DriverDispatcher( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION irpStack; ULONG ioControlCode; NTSTATUS status ; HANDLE h_Event; LARGE_INTEGER Wait; irpStack = IoGetCurrentIrpStackLocation (Irp); switch( irpStack->Parameters.DeviceIoControl.IoControlCode ) { ... case IOCTL_GET_PROCESS_DATA: DPRINT("IOCTL_GET_PROCESS_DATA IRQL = %ld", KeGetCurrentIrql()); if (irpStack->Parameters.DeviceIoControl.OutputBufferLength >=strlen(g_buffer) ) { memcpy(Irp->AssociatedIrp.SystemBuffer, g_buffer,strlen(g_buffer)); Irp->IoStatus.Status =STATUS_SUCCESS; Irp->IoStatus.Information = strlen(g_buffer); if ( KeReadStateSemaphore(&g_pksemaphore) < SEMAPHORE_LIMIT) KeReleaseSemaphore(&g_pksemaphore,0 ,1, FALSE); }else {Irp->IoStatus.Status =STATUS_BUFFER_TOO_SMALL; DPRINT("STATUS_BUFFER_TOO_SMALL"); } break; ... Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; Итак. Так работает хорошо. DebugView выводит строки с названием закрываемый файлов. (при создании или модификации). 1. Если вставить флешку, то после того как она определиться и перед тем как должен начаться "автозапуск" или проще говоря перед тем как появится новый том в системе, выдается IRQL_LESS_OR_NOT_EQUAL STOP 0x0000000A (0x74fc4588, 0x00000002, 0x0,0x804f9c5b) ПРо него пишут: 1.1. Если изменить условие на заведому ложь (1==2), то падения не происходит. Теперь самое забавное: Если условие ложно заведомо, то при втыкании флешки у меня никакой реакции в виде DPRINT("%S %S, prior = %ld", Obj_name->Name.Buffer,pFileObject->FileName.Buffer, IRQLold); не имеем, то есть до этого участка кода при выткании флешки не доходит, а хотя она определяется и начнается автозапуск. (а при копировании файлов их имена ловятся) Если же исправить условие на ПРАВДУ, то падения происходят. 1.?. Спрашивается, ЧТО за НЕЧТО вызывает падения? Я думал может с каким файлом совладать не может, но никаких файлов не закрывается. И что вызвает падение, причем параметр при падении говорит что 0x00000002 это IRQL. Но у меня при условии (1==2) все IRQL =1. Было подозрение, что падение происходит после того как совершается KeSetEvent(g_pkEventObject, 0, FALSE); и следом данные забирает юзермодное приложение. Но оно вообще с 0 IRQL работает (проверял н обычных файлах).. Так что же такое происходит с этим дьявольским участком кода? Ведь до этого кода не доходит.. или...? 2. Если раскомментировать проверку IRQL if ((status==0)&&(IRQLold<2)&&(1==2) ) то падения не происходит, однако если if ((status==0)&&(IRQLold<2)&&(1==1) ) то получаем падение STOP 0x3 (0xbf8089c0, 0x000000FF, 0x0, 0x805327ae) и там сигнаизируется win32k.sys Причем упало не сразу, успел появится автозапуск, но закрытие никакх файлов зафиксировано не было Мне просто интересно, как так? Если же закомментировать строки между KeWaitForSingleObject(&g_pksemaphore,Executive, KernelMode, FALSE, &Wait); и KeSetEvent(g_pkEventObject, 0, FALSE); То я на экране получаю БСОД PAGE_FAULT_IN_NONPAGED_AREA STOP 0x50 (0xED142A7c, 0x0, 0xF65EDB68, 0x02) и упоминание о моем драйвере. Ну там в любом случае БСОД вылазит. Даже если закомментировать в инверсии. Пробовал использовать verifier.exe майкрософт, но пока не разобрался что с ним делать. Поставил свой драйвер в автозагрузку и указал ее в утилите, дак я при загрузке каждый раз получал БСОД, хотя пока к драйверу не подключиться юзермодной прогой и не оптравить спец. запрос, который установил флаг g_fbNotifyRoutineSet, то тот код вообще выполняться не будет. Могу дампы сделать, но не знаю что с ними делать.. Пока хотелось бы понять магию под пунктом 1 и как от нее избавиться. ПС: что значит строка: Код (Text): RES1= (ansiStr.Length > 99? 99: ansiStr.Length); Я ее влял в ниге Солдатова, они определяет длину строки. Но что значит > 99? 99: я так понять и не смог, моих знаний не хватает, просмотрел справочники, не попалось, и искать не знаю как эта вещь называется.. ??
Partner что то вы путаете. Если ansiStr.Length > 99, то RES1=99 иначе RES1= ansiStr.Length test555 поставь Debugging Tools for windows. Открой там креш-дамп и посмотри хотя бы по какому смещению произошел креш, тогда узнаешь команду где крешнулось...
test555 1. Отступы в коде магическим обраом пропали или же их и не было никогда? 2. Ставите Debugging tools, открываете крешдамп и даете нам !analyze -v Или же предлагаете нам заняться гаданием на кофейной гуше и выкладыванием пасьянсов?
Код (Text): kd> !analyze -v ******************************************************************************* * * * Bugcheck Analysis * * * ******************************************************************************* IRQL_NOT_LESS_OR_EQUAL (a) An attempt was made to access a pageable (or completely invalid) address at an interrupt request level (IRQL) that is too high. This is usually caused by drivers using improper addresses. If a kernel debugger is available get the stack backtrace. Arguments: Arg1: 74fc4588, memory referenced Arg2: 00000002, IRQL Arg3: 00000000, bitfield : bit 0 : value 0 = read operation, 1 = write operation bit 3 : value 0 = not an execute operation, 1 = execute operation (only on chips which support this level of status) Arg4: 804f9c5b, address which referenced memory Debugging Details: ------------------ READ_ADDRESS: 74fc4588 CURRENT_IRQL: 2 FAULTING_IP: nt!KeWaitForSingleObject+bb 804f9c5b 803b02 cmp byte ptr [ebx],2 DEFAULT_BUCKET_ID: DRIVER_FAULT BUGCHECK_STR: 0xA PROCESS_NAME: System LAST_CONTROL_TRANSFER: from 00000000 to 80540683 STACK_TEXT: f8acac64 00000000 00000000 00000000 00000000 nt!KiTrap0E+0x233 STACK_COMMAND: .bugcheck ; kb FOLLOWUP_IP: nt!KeWaitForSingleObject+bb 804f9c5b 803b02 cmp byte ptr [ebx],2 SYMBOL_NAME: nt!KeWaitForSingleObject+bb FOLLOWUP_NAME: MachineOwner MODULE_NAME: nt IMAGE_NAME: ntkrnlpa.exe DEBUG_FLR_IMAGE_TIMESTAMP: 4802516a FAILURE_BUCKET_ID: 0xA_nt!KeWaitForSingleObject+bb BUCKET_ID: 0xA_nt!KeWaitForSingleObject+bb Followup: MachineOwner --------- Вот. Что может быть не так с KeWaitForSingleObject? (если в нем дело)
У меня на висте эта ф-ция видать отличается от твоей. Нашел такие строки mov ecx, [ebp+Object] cmp byte ptr [ecx], 2 Наверно твой ebx указывает в никуда, т.е. ты передаешь не то в первый параметр ф-ции KeWaitForSingleObject. Но я могу ошибатся, посмотрим что скажут профи )
Код (Text): FOLLOWUP_IP: nt!KeWaitForSingleObject+bb 804f9c5b 803b02 cmp byte ptr [ebx],2 В Ebx загружается первый параметр функции, соответственно это указатель на обьект. В сурцах это строка: Код (Text): Objectx->Header.Type == MutantObject Так как указатель не валидный поэтому и падает. Не удивлюсь если переменную g_pksemaphore ты определил в секции .init
Clerk Да ты глянь он вообще юзермодный. А точнее, неизвестно, который это вызов KeWaitForSingleObject. Который автор вставил или где-то в глубине. Так что нужен колл стек
Great Что юзермодный, не понял ?? Мне кажется у него переменные в выгружаемой памяти, либо вобще хз где.. В принципе да, нужен дамп стека. [Аа.. указатель, ну да вижу.]
Т.к. тот дамп удалился, делаю по новой.. Есть небольшое отличие. Итого: Код (Text): kd> !analyze -v IRQL_NOT_LESS_OR_EQUAL (a) An attempt was made to access a pageable (or completely invalid) address at an interrupt request level (IRQL) that is too high. This is usually caused by drivers using improper addresses. If a kernel debugger is available get the stack backtrace. Arguments: Arg1: 74fc4588, memory referenced Arg2: 00000002, IRQL Arg3: 00000000, bitfield : bit 0 : value 0 = read operation, 1 = write operation bit 3 : value 0 = not an execute operation, 1 = execute operation (only on chips which support this level of status) Arg4: 804f9c5b, address which referenced memory Debugging Details: ------------------ READ_ADDRESS: 74fc4588 CURRENT_IRQL: 2 FAULTING_IP: nt!KeWaitForSingleObject+bb 804f9c5b 803b02 cmp byte ptr [ebx],2 DEFAULT_BUCKET_ID: DRIVER_FAULT BUGCHECK_STR: 0xA PROCESS_NAME: System TRAP_FRAME: f8ad6c64 -- (.trap 0xfffffffff8ad6c64) ErrCode = 00000000 eax=00000bb7 ebx=74fc4588 ecx=00000000 edx=f8ad6d1c esi=821c6640 edi=821c66b0 eip=804f9c5b esp=f8ad6cd8 ebp=f8ad6cf8 iopl=0 nv up ei pl zr na pe nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010246 nt!KeWaitForSingleObject+0xbb: 804f9c5b 803b02 cmp byte ptr [ebx],2 ds:0023:74fc4588=?? Resetting default scope LAST_CONTROL_TRANSFER: from 804f9c5b to 80540683 STACK_TEXT: f8ad6c64 804f9c5b badb0d00 f8ad6d1c e1da4758 nt!KiTrap0E+0x233 f8ad6cf8 805322e5 00000000 00000000 00000000 nt!KeWaitForSingleObject+0xbb f8ad6d30 805327e7 f67f7d28 f67f7d38 f8ad6d60 nt!ExpWaitForResource+0x2f f8ad6d40 805b09fd 8063bc78 00000001 00000000 nt!ExAcquireResourceExclusiveLite+0x6f f8ad6d60 805b0f44 f67f7d50 00000001 805597c0 nt!ObpRemoveObjectRoutine+0x53 f8ad6d74 80534c02 00000000 00000000 821c6640 nt!ObpProcessRemoveObjectQueue+0x38 f8ad6dac 805c6160 00000000 00000000 00000000 nt!ExpWorkerThread+0x100 f8ad6ddc 80541dd2 80534b02 00000000 00000000 nt!PspSystemThreadStartup+0x34 00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16 STACK_COMMAND: kb FOLLOWUP_IP: nt!KeWaitForSingleObject+bb 804f9c5b 803b02 cmp byte ptr [ebx],2 SYMBOL_STACK_INDEX: 1 SYMBOL_NAME: nt!KeWaitForSingleObject+bb FOLLOWUP_NAME: MachineOwner MODULE_NAME: nt IMAGE_NAME: ntkrnlpa.exe DEBUG_FLR_IMAGE_TIMESTAMP: 4802516a FAILURE_BUCKET_ID: 0xA_nt!KeWaitForSingleObject+bb BUCKET_ID: 0xA_nt!KeWaitForSingleObject+bb Followup: MachineOwner --------- !pte 74fc4588 Код (Text): kd> !pte 74fc4588 VA 74fc4588 PDE at 00000000C0601D38 PTE at 00000000C03A7E20 contains 0000000000000000 !vad 74fc4588 Код (Text): kd> !vad 74fc4588 VAD level start end commit No VAD describing VA FFFFFFFF821EC078 in the current process !thread Код (Text): kd> !thread THREAD 821c6640 Cid 0004.001c Teb: 00000000 Win32Thread: 00000000 RUNNING on processor 0 Not impersonating DeviceMap e1004460 Owning Process 821c77c0 Image: System Attached Process N/A Image: N/A Wait Start TickCount 2999 Ticks: 0 Context Switch Count 861 UserTime 00:00:00.000 KernelTime 00:00:00.109 Start Address nt!ExpWorkerThread (0x80534b02) Stack Init f8ad7000 Current f8ad6d1c Base f8ad7000 Limit f8ad4000 Call 0 Priority 13 BasePriority 13 PriorityDecrement 0 DecrementCount 16 ChildEBP RetAddr Args to Child f8ad6c64 804f9c5b badb0d00 f8ad6d1c e1da4758 nt!KiTrap0E+0x233 (FPO: [0,0] TrapFrame @ f8ad6c64) f8ad6cf8 805322e5 00000000 00000000 00000000 nt!KeWaitForSingleObject+0xbb (FPO: [5,5,4]) f8ad6d30 805327e7 f67f7d28 f67f7d38 f8ad6d60 nt!ExpWaitForResource+0x2f (FPO: [0,5,0]) f8ad6d40 805b09fd 8063bc78 00000001 00000000 nt!ExAcquireResourceExclusiveLite+0x6f (FPO: [2,0,0]) f8ad6d60 805b0f44 f67f7d50 00000001 805597c0 nt!ObpRemoveObjectRoutine+0x53 (FPO: [2,1,4]) f8ad6d74 80534c02 00000000 00000000 821c6640 nt!ObpProcessRemoveObjectQueue+0x38 (FPO: [1,0,0]) f8ad6dac 805c6160 00000000 00000000 00000000 nt!ExpWorkerThread+0x100 (FPO: [1,8,0]) f8ad6ddc 80541dd2 80534b02 00000000 00000000 nt!PspSystemThreadStartup+0x34 (FPO: [Non-Fpo]) 00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16 Семафор у меня описан так (не знаю где в С++ находится секция .init) : Код (Text): KSEMAPHORE g_pksemaphore; В драйверЭнтри Код (Text): KeInitializeSemaphore(&g_pksemaphore, SEMAPHORE_LIMIT, SEMAPHORE_LIMIT); ВОт еще, но вроде это уже было: Код (Text): kd> kb ChildEBP RetAddr Args to Child f8ad6c64 804f9c5b badb0d00 f8ad6d1c e1da4758 nt!KiTrap0E+0x233 f8ad6cf8 805322e5 00000000 00000000 00000000 nt!KeWaitForSingleObject+0xbb f8ad6d30 805327e7 f67f7d28 f67f7d38 f8ad6d60 nt!ExpWaitForResource+0x2f f8ad6d40 805b09fd 8063bc78 00000001 00000000 nt!ExAcquireResourceExclusiveLite+0x6f f8ad6d60 805b0f44 f67f7d50 00000001 805597c0 nt!ObpRemoveObjectRoutine+0x53 f8ad6d74 80534c02 00000000 00000000 821c6640 nt!ObpProcessRemoveObjectQueue+0x38 f8ad6dac 805c6160 00000000 00000000 00000000 nt!ExpWorkerThread+0x100 f8ad6ddc 80541dd2 80534b02 00000000 00000000 nt!PspSystemThreadStartup+0x34 00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16
Мне интересно, почему именно при вставлении флешки падает, ведь при обычном копировании все работает и семафор выполняет свою функцию..
Может я неправильно понимаю, но разве там не должно произойти ошибки доступа к памяти(или как там это называется) , после которой диспетчер памяти подгрузит эту секцию из свопа ?
onSide, не совсем понимаю вашу терминологию, Я уж не знаю как правильно было объявлять переменную семафора, решил сделать так: Код (Text): PKSEMAPHORE pg_pksemaphore Код (Text): pg_pksemaphore= ExAllocatePool(NonPagedPool, sizeof(KSEMAPHORE)); KeInitializeSemaphore(pg_pksemaphore, SEMAPHORE_LIMIT, SEMAPHORE_LIMIT); ну и потом грохаю. но до того момента не доходило.. Кстати, не знаю в чем фишка, но после выделения памяти для объекта семафора мне строка Код (Text): DPRINT("SEMAPHORE = %x", pg_pksemaphore); Дает значение (запомнил на бумажке 81ee6c20) Потом этого адреса в креш-дампе не нашел, по идее он же в стеке должен быть? Собственно после такой манипуляции ничего не изменилось.
Я ерунду написал насчёт переменной даже не подумав, еслибы изза неё, то упало бы до входа в функцию при обращении к ней. Падение не связано с приведённым кодом видимо, копипаст вобще дурной тон.. как вариант дебажить. Крэшдамп кривой.
поместить в нестраничную память всё что нужно. А в остальном чёт уж больно криво всё. адреса юзермодные при irql=2. а вы какой антивирус пишите?
asmfan, дак я в 15 сообщении поместил уже в неподкачиваемую память... Самое забавное, что если поставить невыполнимое условие, то при втыкании флешки до этого места не доходит (т.е. ничего не ловится) а если поставить корректрный IF то БСОД.. Магия.