Если я правильно понял MSDN, TdiBuildReceive, для получения большого количества информации, надо вызывать повторно (the client must make as many receive requests as necessary to receive the expedited TSDU.) но при втором вызове IoCallDriver имею: IRQL_NOT_LESS_OR_EQUAL (a) CURRENT_IRQL: 2 FAULTING_IP: nt!MmMapLockedPagesSpecifyCache+211 я что-то некорректно делаю с MDL ? Код (Text): pRBuffer = ExAllocatePoolWithTag(NonPagedPool, Size,'1stA'); pRBuffer2 = ExAllocatePoolWithTag(NonPagedPool, Size,'2stA'); Mdl = IoAllocateMdl(pRBuffer, Size, FALSE, FALSE, NULL); ... Mdl2 = IoAllocateMdl(pRBuffer2, Size, FALSE, FALSE, NULL); ... Mdl->Next = NULL; Mdl2->Next = NULL; __try { MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess); MmProbeAndLockPages(Mdl2, KernelMode, IoModifyAccess); } KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE); Irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE); if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; while (k < 0x50000) { TdiBuildReceive (Irp, DeviceObject, Connection, KSocketComplete, &Ctx, Mdl, Flags, Size); ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL ); <<<<<<<<<<<<<<<<< Status = IoCallDriver(DeviceObject, Irp); <<<<<<<<<<<<<<<<< if (Status == STATUS_PENDING) {..... } BytesReceived = Ctx.Iosb.Information; RtlCopyMemory(pAAA,pRBuffer,BytesReceived); pAAA += BytesReceived; <<< (PCHAR pAAA = pRBuffer2;) k += BytesReceived; if (!NT_SUCCESS(Status)) {..... } if ( !(Ctx.Iosb.Status || Ctx.Iosb.Information)) break; KeResetEvent(&Ctx.Event); IoReuseIrp(Irp, STATUS_UNSUCCESSFUL); }// while
Ты пытаешься залочить non-paged страницы. Это как бы не совсем нормально. Либо поменяй NonPagedPool на PagedPool, либо вместо MmProbeAndLockPages() используй MmBuildMdlForNonPagedPool(). Это раз. Во-вторых, I/O-менеджер будет выполнять разблокировку страниц и освобождение MDL при завершении каждого запроса. Другими словами, он будет делать это при каждом вызове IoCallDriver(). У тебя же блокировка страниц (вызов MmProbeAndLockPages) выполняется только единожды, а это неправильно, число блокировок/разблокировок должно совпадать. Короче говоря, попробуй для начала переместить вызовы IoAllocateMdl() и MmProbeAndLockPages() внутрь цикла.
x64 спасибо добавил IoAllocateIrp, IoAllocateMdl, MmProbeAndLockPages в конец цикла - заработало с первой частью что-то, наверное, перемудрил немного глючит, но глобально работает (частенько ), буду шлифовать спасибо
Код (Text): TdiBuildReceive (Irp, DeviceObject, Connection, KSocketComplete, &Ctx, Mdl, Flags, Size); Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) ............. if ( !(Ctx.Iosb.Status || Ctx.Iosb.Information)) break; ............. RtlCopyMemory(pBBB,pAAA,Ctx.Iosb.Information); ..... Я думал что сошел с ума, но значение в Ctx.Iosb.Information (кол-во полученных байтов), иногда, пишется с опозданием , те после проверок и "попытки" скопировать ( команд через 10 ). С чем это может быть вызванно
x64 Код (Text): Такого не бывает, ищи у себя ошибку. сам уже неделю ломаю голову, как это возможно, ( хоть я и только осваиваю win кернел, и задаю простые вопросы, опыт системного програмирования 20 лет, просто платформы другие ) вот прога и вывод дебагера, судите сами Код (Text): while (1) { TdiBuildReceive (Irp, DeviceObject, Connection, KSocketComplete, &Ctx, Mdl, Flags, Size); IoCallDriver(DeviceObject, Irp); RtlCopyMemory(pBBB,pAAA,Ctx.Iosb.Information); // check received bytes DbgPrint(" * * * * * KSReceive returned status %08x. BytesReceived:%i \n", Ctx.Iosb.Status, Ctx.Iosb.Information); if ( !(Ctx.Iosb.Status || Ctx.Iosb.Information)) break; <-- оставил единственное условие выхода из цикла, 0 0 ......... }// while Status =ZwClose(FileHandle ); __int 3; DbgPrint(" * * * * * ZwClose********StAtus: 0x%x\n ",Status); DbgPrint(" * * * * * KSReceive returned status %08x. BytesReceived:%i \n", Ctx.Iosb.Status, Ctx.Iosb.Information); kd> g * * * * * KSOpenAddress returned 00000000 * * * * * KSOpenConnection returned 00000000 * * * * * KSAssociateAddress returned 00000000 * * * * * KSocketConnect returned 00000000 * * * * * KSocketSend returned 00000000 * * * * * KSReceive returned status 00000000. BytesReceived:4140 * * * * * KSReceive returned status 00000000. BytesReceived:0 Break instruction exception - code 80000003 (first chance) * * * * * ZwClose********StAtus: 0x0 * * * * * KSReceive returned status 00000000. BytesReceived:18020 голова уже в дверной проем не пролазит
Заметил странную закономерность: Ctx.Iosb.Information "обновляется" не по истечении какого-то промежутка времени, а при int 3, чуть изменил прогу предыдушего поста для проверки "теории" Код (Text): if ( !(Ctx.Iosb.Status || Ctx.Iosb.Information)) __asm int 3; if (!( Ctx.Iosb.Information)) break; оказалось - ВЕРНО !!! вот вывод дебагера * * * * * KSSend returned 00000000 * * * * * KSReceive returned status 00000000. BytesReceived:3760 * * * * * KSReceive returned status 00000000. BytesReceived:380 * * * * * KSReceive returned status 00000000. BytesReceived:0 Break instruction exception - code 80000003 (first chance) b866a8b8 cc int 3 kd> g * * * * * KSReceive returned status 00000000. BytesReceived:64240 * * * * * KSReceive returned status 00000000. BytesReceived:0 Break instruction exception - code 80000003 (first chance) b866a8b8 cc int 3 kd> g * * * * * KSReceive returned status 00000000. BytesReceived:64239 * * * * * KSReceive returned status 00000000. BytesReceived:5241 как видите, после int 3 условие, if (!( Ctx.Iosb.Information)) break, не срабатывает ( иначе выйдет из цикла, обратите внимание на адрес int 3 b866a8b8 ), значит Ctx.Iosb.Information уже!!! != 0 Вопрос: как, без int 3, заставить windows "работать", может есть какой-то нюанс при работе с ввод/выводом ?
После долгих раздумий на тему " Что за чертовщина ? ", интуиция подкинула мысль - " А что если виртуалка что-то не то, не так как надо ........... " На реальной машине заработало без проблем ...... Урок был долгий, интересный, дошел до того , что начал сомневаться в принципах фон Неймана
at0s >опыт системного програмирования 20 лет, просто платформы другие Случайно не приходилось сталкиваться с системами, построенными по принципу полного перебора? Последний отрывок: Код (Text): TdiBuildReceive (Irp, DeviceObject, Connection, KSocketComplete, &Ctx, Mdl, Flags, Size); IoCallDriver(DeviceObject, Irp); После вызова IoCallDriver() не проверяется, если status == STATUS_PENDING. Из этого следует, что запрос гарантированно синхронный – т.е. KSocketComplete уже отработала. Однако в предыдущих кусках ты проверял статус. Так что же – запрос может быть асинхронным? Если так, то в случае получения STATUS_PENDING после вызова IoCallDriver ты ожидаешь на событии, сигнализируемом из KSocketComplete? Событие сигнализируется после заполнения Ctx.Iosb? Далее, вернёмся к первому отрывку. Вместо залочки страниц из неподкачиваемого пула x64 уже предложил пользовать MmBuildMdlForNonPagedPool() для постройки массива pfn в mdl. А вот насчёт разблокировки страниц и освобождения mdl IoManager'ом – разве в данном случае позволительно разрешать поднимание Irp'а, аллоцированного в текущей процедуре, до такого этапа? (Doron Holan так не считает – click). Что выглядит логичным для данного случая: сигнализация события внутри KSocketComplete для случая Irp->PendingReturned, с последующим безусловным возвращением STATUS_MORE_PROCESSING_REQUIRED оттуда (без дотрагивания до буферов или Irp'а после сигнализации события!) – таким образом вызывающая процедура получит контроль синхронно (конечно, при условии её ожидания на событии в случае получения STATUS_PENDING от IoCallDriver), и никто не будет разлочивать\освобождать аллоцированный mdl (вызывающая процедура сможет сделать это самостоятельно когда будет необходимо). Дисклеймер: мы не работали с сетевыми девайсами и протоколами в r0, и вообще имеем очень мало представления о том, что здесь происходит; если применяется какая-то необычная модель взаимодействия, то, полагаем, нас исправят.
Sol_Ksacap >Случайно не приходилось сталкиваться с системами, построенными по принципу полного перебора? =))) Истоки перебора видимо лежат тут: http://www.rootkit.com/newsread.php?newsid=416
Спасибо за коменты. Sol_Ksacap "с системами полного перебора".....надеюсь это не сарказм по поводу 20... а так .... только когда нет других вариантов, это сейчас можно вольно обращаться с процессорным временем и памятью, (кто-бы мне сказал несколько лет назад, что есть ОС, которой для себя 1 ГИГА мало..... ), ну я еще не изучил windows, мне рано судить, здесь я начинаюший STATUS_PENDING. я приводил только те куски кода, которые существенны в данный момент, чтоб не захламлять пост. В проге все это есть. Спасибо. TSS ты прав, первоначальный вариант взят оттуда p.s. Только неграмотный человек на вопрос "Как найти площадь Ленина?" отвечает: "длину Ленина умножить на ширину Ленина..." А грамотный знает, что надо взять интеграл по поверхности !