сплайс kssdoit, BSOD 0xCE при выгрузке

Тема в разделе "WASM.BEGINNERS", создана пользователем IceFire, 29 июн 2009.

  1. IceFire

    IceFire New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2006
    Сообщения:
    244
    Отсплайсил kssdoit, все хорошо.

    Но при выгрузке драйвера бывает БСОД DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS.

    Хук оформлен так:

    Код (Text):
    1. __declspec(naked) void MyKSSDOITFunction(void)
    2. {
    3.     __asm
    4.     {
    5.         lock inc dword ptr [inhook]
    6.  
    7.         ................................
    8.  
    9.         push uReturnAddr
    10.  
    11.                 cli
    12.                 lock dec dword ptr [inhook]
    13.                 sti
    14.    
    15.             ret
    16.     }
    17. }
    Процедура выгрузки вот:

    Код (Text):
    1. VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
    2. {  
    3.         __asm{
    4.                 cli
    5.             mov  eax,cr0
    6.             and  eax,not 10000h
    7.             mov  cr0,eax
    8.         }
    9.  
    10.         memcpy((PVOID)uSpliceAddr,JnbOrgCode,sizeof(JnbOrgCode));
    11.  
    12.         __asm{
    13.             mov  eax,cr0
    14.                         or  eax,10000h
    15.             mov  cr0,eax
    16.             sti
    17.         }
    18.  
    19.         FreeMemory();  
    20.  
    21.         while (inhook)
    22.         {
    23.             ZwYieldExecution();
    24.             }
    25. DPRINT("--------------------Driver unloaded--------------------");
    26. return;
    27. }
    Вот если цикл while убрать - БСОД. Если оставить - 98-99 ресурсов системы уходит на процесс System, однако система жива. Но выгрузка драйвера не происходит. Если вместо ZwYieldExecution() поставить DbgPrint("...") - сист. тихо умирает.

    Так как правильно выгружать драйвер в этом случае?
     
  2. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Сделай вывод числа inhook перед циклом while(), сколько покажет?
     
  3. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Нужно снимать перехваты, если обработчики в выгружаемом драйвере. Вроде у меня крах с таким кодом ошибки был спустя десятки секунд, когда не правильно писалось поле Tcb.PreviousMode(изза опечатки записывался дворд, вместо байта, тоесть EnableStackSwap). Предположу что тут тоже чтото подобное.
     
  4. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Дык он снимается. Даже свой кодес узнаю)
     
  5. IceFire

    IceFire New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2006
    Сообщения:
    244
    Clerk

    Ну, обработчик-то естественно в выгружаемом драйвере. Но я его и снимаю - см. выше. БСОД наступает сразу, если не делать цикл с while.

    Great
    Вывод сделал: 248 (dec).
     
  6. IceFire

    IceFire New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2006
    Сообщения:
    244
    Great

    =)
    Ну да, вот это я у тебя подсмотрел:

    Код (Text):
    1.                 cli
    2.                 lock dec dword ptr [inhook]
    3.                 sti
     
  7. TSS

    TSS New Member

    Публикаций:
    0
    Регистрация:
    13 апр 2009
    Сообщения:
    494
    Код (Text):
    1. cli
    2. lock dec dword ptr [inhook]
    3. sti
    Зачем тут cli/sti если изменение переменной делается атомарно?
     
  8. IceFire

    IceFire New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2006
    Сообщения:
    244
    TSS
    Не знаю, подсмотрел в другом коде.

    All
    Нет еще идей? В чем может быть моя ошибка?
     
  9. z0mailbox

    z0mailbox z0

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

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    TSS
    Не нужно запрещать прерывания не потомучто атомарно, а потомучто только одна инструкция исполнятся со сброшенным IF, а для одной инструкции это не имеет значения, поэтому нигде не может понадобится запрещать прерывания для исполнения только одной инструкции.
    В случае можификации регистра управления прерывания запрещать необходимо:
    Код (Text):
    1.     mov eax,Cr0
    2.     and eax,NOT(CR0_WP)
    3.     mov Cr0,eax
    Ибо поток может быть прерван между чтением и записью регистра, а тот может быть изменён после возврата процессора на прерванный код.
     
  11. IceFire

    IceFire New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2006
    Сообщения:
    244
    А вообще, корректно я выгружаю драйвер при таком перехвате? Или нужно еще что-то учитывать?
     
  12. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Код атомарно сбрасывающий флажёк должен находится в невыгружаемой памяти, либо какието дополнительные манипуляции выполнять, например тред может быть прерван на инструкции, слудующей за сбросом флажка(тут Ret), тогда тред может уже и не вернуться. Можно запрещать прерывания до сброса флажка, взводить флажёк IF в регистре флагов сохранённом в стеке и выполнять возврат инструкцией Iret, хотя это ничего не даст, следует выделить пул и в нём уже декремент счётчика входов выполнять.
     
  13. IceFire

    IceFire New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2006
    Сообщения:
    244
    Clerk

    Как этого добиться? Сейчас этот код в простой процедуре внутри драйвера.

    All
    Сделал вывод значения inhook в цикле while, перед ZwYieldExecution(). Счетчик достигает больших значений (пара-тройка тысяч) и очень медленно падает - в три минуты на единицу, примерно.

    Неужели так подолгу не возвращается управление из сервиса?
     
  14. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    IceFire
    Это изза рекурсивных вызовов теневых сервисов. Например вызывается какойто сервис, он юзает KeUserModeCallback(), переходит в юзермод, там снова вызовы сервисов.
    Выделить пул, записать туда код и в дальнейшем не освобождать эту память.
     
  15. IceFire

    IceFire New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2006
    Сообщения:
    244
    Clerk

    1. Счетчик до нуля-то досчитает когда-нибудь, если мы уже не ходим в сплайс-процедуру? (запустили процедуру выгрузки, которая сняла хук)

    2.
    Код (Text):
    1. ExAllocatePoolWithTag(NonPagedPool,...)
    Так?

    3. Справедливо ли считать временем работы сервиса разницу между EDX:EAX после rdtsc ДО и ПОСЛЕ kssdoit? С условием использования сервисом KeUserModeCallback() и проч.

    4.
    . Т.е. не теневые сервисы рекурсивные вызовы не используют? Правильно я понимаю?
     
  16. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    IceFire
    Наверно всё проще, я запутался %), шадов сервисы тут не причём, возврат на сервис ведь после отработки вашего кода, который не известно что делает, предположу что в юзермод не прыгает. Вобщем у меня такие проблемы никогда не возникали, ибо я не чистил за собой(несколько килобайт памяти не критично), а код весь перемещаемый.
    Выделяйте пул как в 2 и пусть обработчик в нём будет, либо его чать(всего несколько инструкций). Можно гдето в уже выделенной памяти место использовать это не важно.