Ring0 - потоки.

Тема в разделе "WASM.NT.KERNEL", создана пользователем gevara, 21 май 2007.

  1. gevara

    gevara максим

    Публикаций:
    0
    Регистрация:
    10 ноя 2006
    Сообщения:
    112
    Адрес:
    г. Пермь
    может ли DriverEntry функция создавать поток? причём поток должен продолжать работать, а функция DriverEntry должна завершиться.
    Код (Text):
    1. void __cdecl Test(PVOID a)
    2. {
    3. LARGE_INTEGER delay;
    4. delay.QuadPart = SEC(1000);
    5. while(1) KeDelayExecutionThread(KernelMode,0,&delay);  
    6. }
    7. DriverEntry(..)
    8. {
    9. PsCreateSystemThread(&hThread,THREAD_ALL_ACCESS,0,0,0,Test,0);
    10. return 0;
    11. }
    проблемма в том, что при загрузке дрова лоадер виснет, хотя, (смотрел в сайсе) функция DriverEntry завершается и возвращает 0, PsCreateSystemThread срабатывает удачно, поток запускается.
     
  2. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Да.

    Так оно и будет. Точнее поток начинает жить своей жизнью безотносительно к тому, что делает и как завершается DriverEntry. Проблема только в том, что код потоковой функции находится в теле драйвера. Т.е. драйвер должен оставаться загружен всё время пока живёт поток. Но если DriverEntry не создаст device object (если это legacy драйвер) и у драйвера нет функции AddDevice (если это legacy драйвер), то по выходу из DriverEntry загрузчик проверит, создал ли драйвер девайс. Если нет, то вызовет его DriverUnload и попытается выгрузить его из памяти. Тут у тебя косяк и происходит. Ещё м.б. завязка на хендл потока... т.е. в объекте драйвера увеличивается счетчик ссылок и пока он не обнулится драйвер не может быть выгружен, но на 100% не скажу... уже не помню всех деталей. В любом случае, legacy драйвер обязан создать девайс в DriverEntry, иначе система считает, что такой драйвер без девайса нафиг ей не нужен и стремиться от него избавиться.
     
  3. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Ну дык он и не пытается его выгрузить, всего лишь загрузить. Ну хотя для эксперимента можно попробовать закрыть хендл потока в DriverEntry, только не вызовет ли это его завершения? Счетчик хендов ведь упадет до нуля.. хотя, наверное, при старте счетчик ссылок увеличивается.. я хз )

    Хм.. а почему тогда принудительно не килляются дрова, не создающие девайсов, но имеющие DriverUnload ?
    У меня они выгружаются только явно, по ZwUnloadDriver и никак иначе
     
  4. gevara

    gevara максим

    Публикаций:
    0
    Регистрация:
    10 ноя 2006
    Сообщения:
    112
    Адрес:
    г. Пермь
    Ну... вобщем немного понятно.. попробую помудить с созданием потока.

    Есть ещё вопрос. Если я вызову ZwUnloadDriver - система прибъёт этот поток или же мне необходимо самому его прибить?
    Немного странно: есть функция ZwTerminateThread.ntdll - она есть и в СДТ, но в экспорте ntoskrnl такой функции нет. отсюда вопрос - можно ли убивать ей системные потоки?
     
  5. gevara

    gevara максим

    Публикаций:
    0
    Регистрация:
    10 ноя 2006
    Сообщения:
    112
    Адрес:
    г. Пермь
    Всем спасибо за ответы.

    Вобщем проблемма была в том, что:
    Код (Text):
    1. PsCreateSystemThread(&hThread,THREAD_ALL_ACCESS,0,0,0,Test,0);
    четвёртым параметром необходимо указывать не 0, а -1 т.е. NtCurrentThread(). я подумал что 0, т.к. в ДДК написано optional:
    Код (Text):
    1.  IN HANDLE  ProcessHandle  OPTIONAL,
    Далее - система сама потоки не убивает, а при попытке выгрузить дров, не убив поток вылазит сайс и говорит fault! т.е. образ выгружается, а поток продолжает работать.
     
  6. k3internal

    k3internal New Member

    Публикаций:
    0
    Регистрация:
    11 янв 2007
    Сообщения:
    607
    gevara


    <В любом случае, legacy драйвер обязан создать девайс в DriverEntry, иначе система считает, что такой драйвер без девайса нафиг ей не нужен и стремиться от него избавиться.>

    Абсолютно не стремится. Даже если драйвер не создал устройства, но, DriverEntry вернуло Success, драйвер остаётся в памяти. Другое дело, если DriverEntry располагается в удаляемой секции, и процедура потока тоже в ней. В таком случае, на ядре со страницами по 4к произойдёт освобождение заданной странички и тогда само собой либо поток зависает либо бсод. Если страничка 4м, то как правило код DriverEntry остаётся, но может быть забит нулями, видел и такое, а это значит, что данный кусок памяти перестаёт быть виден как занятый. Соответственно с ним может случиться всё что угодно. Если драйвер компилён майкросовтовским компилером, то он почти всегда в 99,99% случаев создаёт секцию INIT, что собственно и подтверждает всё вышесказанное.
    Да, и кроме того, ты в DriverEntry не пишешь ничего в Pe - заголовок? это тоже одна из причин взвисов. В общем, смотри внимательно. Создавать девайс необязательно, иначе нелогичность выходит, если драйвер удаляет свой девайс оно что, должно быть автоматом должно быть выгружено? так и руктиты бы их большая часть по крайней мере не смогли бы работать)))
     
  7. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Нет. Только сам системный поток может самого себя завершить вызовом PsTerminateSystemThread.

    Я уже не помню всех деталей, но...

    Код (Text):
    1. NTSTATUS
    2. IopLoadDriver(
    3.    ...
    4.     )
    5. {
    6.  ...
    7.     //
    8.     // If we load the driver because we think it is a legacy driver and
    9.     // it does not create any device object in its DriverEntry.  We will
    10.     // unload this driver.
    11.     //
    12.  
    13.     if (NT_SUCCESS(status) && !IopIsLegacyDriver(driverObject)) {
    14.  
    15.         if (driverObject->DeviceObject == NULL && ... ) {
    16.  
    17.             IopDriverLoadingFailed(KeyHandle, NULL);
    18.             status = STATUS_PLUGPLAY_NO_DEVICE;
    19.             ...
    20.         }
    21.         if (!NT_SUCCESS(status)) {
    22.             if (driverObject->DriverUnload) {
    23.                 driverObject->Flags |= DRVO_UNLOAD_INVOKED;
    24.                 driverObject->DriverUnload(driverObject);
    25.                 IopBootLog(&baseName, FALSE);
    26.             }
    27.         }
    28.     }
    29. ...
    30. }
     
  8. gevara

    gevara максим

    Публикаций:
    0
    Регистрация:
    10 ноя 2006
    Сообщения:
    112
    Адрес:
    г. Пермь
    > Нет. Только сам системный поток может самого себя завершить вызовом PsTerminateSystemThread.
    мдя.. :dntknw: это плохо. То есть придётся создавать механизм, чтобы при запуске DriverUnload поток выходил из бесконечного цикла...
     
  9. Guest

    Guest Guest

    Публикаций:
    0
    Этот механизм - глобальная переменная типа fTerminate, и в DriverUnload вызов WaitForSingleObject.
     
  10. gevara

    gevara максим

    Публикаций:
    0
    Регистрация:
    10 ноя 2006
    Сообщения:
    112
    Адрес:
    г. Пермь
    угу. это я уже понял. кроме того придётся еще и слип ставить...
     
  11. k3internal

    k3internal New Member

    Публикаций:
    0
    Регистрация:
    11 янв 2007
    Сообщения:
    607
    <Я уже не помню всех деталей, но...>

    Хм, ну чессслово, сколько дров делал без устройства, никогда ничего не выгружалось.
     
  12. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    k3internal
    +1
    Four-F
    Ну так оно возвращает только STATUS_PLUGPLAY_NO_DEVICE, я не помню, а может это и не статус ошибки вовсе, поэтому и незачем выгружать драйвер.
     
  13. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Вполне возможно что я ошибаюсь или путаю что-то. Раз говорите, что не выгружаются, значит так оно и есть.
     
  14. z0mailbox

    z0mailbox z0

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    635
    Адрес:
    Russia СПБ
    та же фигня. сколько дров было просто патчивших что-то или хукающих что-то