TdiBuildReceive

Тема в разделе "WASM.NT.KERNEL", создана пользователем at0s, 22 мар 2010.

  1. at0s

    at0s New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2009
    Сообщения:
    91
    Если я правильно понял 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):
    1.     pRBuffer   = ExAllocatePoolWithTag(NonPagedPool, Size,'1stA');  
    2.     pRBuffer2 = ExAllocatePoolWithTag(NonPagedPool, Size,'2stA');          
    3.  
    4.     Mdl   = IoAllocateMdl(pRBuffer, Size, FALSE, FALSE, NULL);
    5. ...
    6.     Mdl2 = IoAllocateMdl(pRBuffer2, Size, FALSE, FALSE, NULL);
    7. ...
    8.    Mdl->Next   = NULL;
    9.    Mdl2->Next = NULL;  
    10.     __try
    11.     {
    12.         MmProbeAndLockPages(Mdl,  KernelMode, IoModifyAccess);
    13.         MmProbeAndLockPages(Mdl2, KernelMode, IoModifyAccess);        
    14.     }
    15.  
    16.     KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE);  
    17.     Irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE);
    18.     if (!Irp)         return STATUS_INSUFFICIENT_RESOURCES;
    19.  
    20.     while (k < 0x50000)
    21.     {
    22.  
    23.         TdiBuildReceive (Irp, DeviceObject, Connection, KSocketComplete,
    24.                                                                       &Ctx, Mdl, Flags, Size);
    25.     ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL );    <<<<<<<<<<<<<<<<<
    26.      Status = IoCallDriver(DeviceObject, Irp);                  <<<<<<<<<<<<<<<<<
    27.     if (Status == STATUS_PENDING)
    28.     {.....    }
    29.      BytesReceived = Ctx.Iosb.Information;
    30.      RtlCopyMemory(pAAA,pRBuffer,BytesReceived);
    31.      pAAA += BytesReceived;    <<<  (PCHAR pAAA = pRBuffer2;)
    32.      k += BytesReceived;
    33.     if (!NT_SUCCESS(Status))
    34.     {.....    }
    35.      if ( !(Ctx.Iosb.Status || Ctx.Iosb.Information)) break;
    36.        
    37.      KeResetEvent(&Ctx.Event);
    38.      IoReuseIrp(Irp, STATUS_UNSUCCESSFUL);
    39.   }// while
     
  2. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Ты пытаешься залочить non-paged страницы. Это как бы не совсем нормально. Либо поменяй NonPagedPool на PagedPool, либо вместо MmProbeAndLockPages() используй MmBuildMdlForNonPagedPool(). Это раз. Во-вторых, I/O-менеджер будет выполнять разблокировку страниц и освобождение MDL при завершении каждого запроса. Другими словами, он будет делать это при каждом вызове IoCallDriver(). У тебя же блокировка страниц (вызов MmProbeAndLockPages) выполняется только единожды, а это неправильно, число блокировок/разблокировок должно совпадать. Короче говоря, попробуй для начала переместить вызовы IoAllocateMdl() и MmProbeAndLockPages() внутрь цикла.
     
  3. at0s

    at0s New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2009
    Сообщения:
    91
    x64 спасибо
    добавил IoAllocateIrp, IoAllocateMdl, MmProbeAndLockPages в конец цикла - заработало :)
    с первой частью что-то, наверное, перемудрил
    немного глючит, но глобально работает (частенько :)), буду шлифовать
    спасибо
     
  4. at0s

    at0s New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2009
    Сообщения:
    91
    Код (Text):
    1.     TdiBuildReceive (Irp, DeviceObject, Connection, KSocketComplete, &Ctx, Mdl, Flags, Size);
    2.     Status = IoCallDriver(DeviceObject, Irp);
    3.     if (Status == STATUS_PENDING)
    4. .............
    5.     if ( !(Ctx.Iosb.Status || Ctx.Iosb.Information))    break;
    6. .............
    7. RtlCopyMemory(pBBB,pAAA,Ctx.Iosb.Information);
    8. .....
    Я думал что сошел с ума, но значение в Ctx.Iosb.Information (кол-во полученных байтов),
    иногда, пишется с опозданием , те после проверок и "попытки" скопировать ( команд через 10 ).

    С чем это может быть вызванно
     
  5. at0s

    at0s New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2009
    Сообщения:
    91
    С чем == чем :)
     
  6. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Такого не бывает, ищи у себя ошибку.
     
  7. at0s

    at0s New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2009
    Сообщения:
    91
    x64
    Код (Text):
    1. Такого не бывает, ищи у себя ошибку.
    сам уже неделю ломаю голову, как это возможно, ( хоть я и только осваиваю win кернел, и задаю простые вопросы, опыт системного програмирования 20 лет, просто платформы другие )
    вот прога и вывод дебагера, судите сами
    Код (Text):
    1.  while (1)
    2.  {
    3.     TdiBuildReceive (Irp, DeviceObject, Connection, KSocketComplete, &Ctx, Mdl, Flags, Size);
    4.     IoCallDriver(DeviceObject, Irp);
    5.      RtlCopyMemory(pBBB,pAAA,Ctx.Iosb.Information);
    6.     // check received bytes
    7. DbgPrint(" * * * * *   KSReceive returned status %08x.  BytesReceived:%i \n", Ctx.Iosb.Status, Ctx.Iosb.Information);
    8.     if ( !(Ctx.Iosb.Status || Ctx.Iosb.Information)) break;  <-- оставил единственное условие выхода из цикла, 0 0
    9. .........
    10.   }// while
    11.   Status =ZwClose(FileHandle );
    12. __int 3;     
    13.   DbgPrint(" * * * * * ZwClose********StAtus: 0x%x\n ",Status);
    14.   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
    голова уже в дверной проем не пролазит
     
  8. at0s

    at0s New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2009
    Сообщения:
    91
    Заметил странную закономерность:
    Ctx.Iosb.Information "обновляется" не по истечении какого-то промежутка времени, а при int 3, чуть изменил прогу предыдушего поста для проверки "теории"
    Код (Text):
    1. if ( !(Ctx.Iosb.Status || Ctx.Iosb.Information))  __asm int 3;
    2.         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 "работать", может есть какой-то нюанс при работе с ввод/выводом ?
     
  9. at0s

    at0s New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2009
    Сообщения:
    91
    После долгих раздумий на тему " Что за чертовщина ? ", интуиция подкинула мысль - " А что если виртуалка что-то не то, не так как надо ........... "

    На реальной машине заработало без проблем :)

    ...... Урок был долгий, интересный, дошел до того , что начал сомневаться в принципах фон Неймана :)
     
  10. C2H5OH

    C2H5OH New Member

    Публикаций:
    0
    Регистрация:
    21 мар 2008
    Сообщения:
    42
    Хороший был монолог :)))
     
  11. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    at0s
    >опыт системного програмирования 20 лет, просто платформы другие
    Случайно не приходилось сталкиваться с системами, построенными по принципу полного перебора?

    Последний отрывок:
    Код (Text):
    1.     TdiBuildReceive (Irp, DeviceObject, Connection, KSocketComplete, &Ctx, Mdl, Flags, Size);
    2.     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, и вообще имеем очень мало представления о том, что здесь происходит; если применяется какая-то необычная модель взаимодействия, то, полагаем, нас исправят.
     
  12. TSS

    TSS New Member

    Публикаций:
    0
    Регистрация:
    13 апр 2009
    Сообщения:
    494
    Sol_Ksacap
    >Случайно не приходилось сталкиваться с системами, построенными по принципу полного перебора?
    =)))
    Истоки перебора видимо лежат тут: http://www.rootkit.com/newsread.php?newsid=416
     
  13. at0s

    at0s New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2009
    Сообщения:
    91
    Спасибо за коменты.

    Sol_Ksacap
    "с системами полного перебора".....надеюсь это не сарказм по поводу 20...
    а так .... только когда нет других вариантов, это сейчас можно вольно обращаться с процессорным временем и
    памятью, (кто-бы мне сказал несколько лет назад, что есть ОС, которой для себя 1 ГИГА
    мало..... ), ну я еще не изучил windows, мне рано судить, здесь я начинаюший :)

    STATUS_PENDING. я приводил только те куски кода, которые существенны в данный момент, чтоб не захламлять
    пост. В проге все это есть. Спасибо.

    TSS
    ты прав, первоначальный вариант взят оттуда

    p.s. Только неграмотный человек на вопрос "Как найти площадь Ленина?" отвечает: "длину Ленина умножить на
    ширину Ленина..." А грамотный знает, что надо взять интеграл по поверхности !