Отсплайсил kssdoit, все хорошо. Но при выгрузке драйвера бывает БСОД DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS. Хук оформлен так: Код (Text): __declspec(naked) void MyKSSDOITFunction(void) { __asm { lock inc dword ptr [inhook] ................................ push uReturnAddr cli lock dec dword ptr [inhook] sti ret } } Процедура выгрузки вот: Код (Text): VOID DriverUnload(IN PDRIVER_OBJECT DriverObject) { __asm{ cli mov eax,cr0 and eax,not 10000h mov cr0,eax } memcpy((PVOID)uSpliceAddr,JnbOrgCode,sizeof(JnbOrgCode)); __asm{ mov eax,cr0 or eax,10000h mov cr0,eax sti } FreeMemory(); while (inhook) { ZwYieldExecution(); } DPRINT("--------------------Driver unloaded--------------------"); return; } Вот если цикл while убрать - БСОД. Если оставить - 98-99 ресурсов системы уходит на процесс System, однако система жива. Но выгрузка драйвера не происходит. Если вместо ZwYieldExecution() поставить DbgPrint("...") - сист. тихо умирает. Так как правильно выгружать драйвер в этом случае?
Нужно снимать перехваты, если обработчики в выгружаемом драйвере. Вроде у меня крах с таким кодом ошибки был спустя десятки секунд, когда не правильно писалось поле Tcb.PreviousMode(изза опечатки записывался дворд, вместо байта, тоесть EnableStackSwap). Предположу что тут тоже чтото подобное.
Clerk Ну, обработчик-то естественно в выгружаемом драйвере. Но я его и снимаю - см. выше. БСОД наступает сразу, если не делать цикл с while. Great Вывод сделал: 248 (dec).
Код (Text): cli lock dec dword ptr [inhook] sti Зачем тут cli/sti если изменение переменной делается атомарно?
если бы перехват не снялся - код был бы другой у меня такой код был последний раз из-за QueueWorkItem под большой нагрузкой
TSS Не нужно запрещать прерывания не потомучто атомарно, а потомучто только одна инструкция исполнятся со сброшенным IF, а для одной инструкции это не имеет значения, поэтому нигде не может понадобится запрещать прерывания для исполнения только одной инструкции. В случае можификации регистра управления прерывания запрещать необходимо: Код (Text): mov eax,Cr0 and eax,NOT(CR0_WP) mov Cr0,eax Ибо поток может быть прерван между чтением и записью регистра, а тот может быть изменён после возврата процессора на прерванный код.
Код атомарно сбрасывающий флажёк должен находится в невыгружаемой памяти, либо какието дополнительные манипуляции выполнять, например тред может быть прерван на инструкции, слудующей за сбросом флажка(тут Ret), тогда тред может уже и не вернуться. Можно запрещать прерывания до сброса флажка, взводить флажёк IF в регистре флагов сохранённом в стеке и выполнять возврат инструкцией Iret, хотя это ничего не даст, следует выделить пул и в нём уже декремент счётчика входов выполнять.
Clerk Как этого добиться? Сейчас этот код в простой процедуре внутри драйвера. All Сделал вывод значения inhook в цикле while, перед ZwYieldExecution(). Счетчик достигает больших значений (пара-тройка тысяч) и очень медленно падает - в три минуты на единицу, примерно. Неужели так подолгу не возвращается управление из сервиса?
IceFire Это изза рекурсивных вызовов теневых сервисов. Например вызывается какойто сервис, он юзает KeUserModeCallback(), переходит в юзермод, там снова вызовы сервисов. Выделить пул, записать туда код и в дальнейшем не освобождать эту память.
Clerk 1. Счетчик до нуля-то досчитает когда-нибудь, если мы уже не ходим в сплайс-процедуру? (запустили процедуру выгрузки, которая сняла хук) 2. Код (Text): ExAllocatePoolWithTag(NonPagedPool,...) Так? 3. Справедливо ли считать временем работы сервиса разницу между EDX:EAX после rdtsc ДО и ПОСЛЕ kssdoit? С условием использования сервисом KeUserModeCallback() и проч. 4. . Т.е. не теневые сервисы рекурсивные вызовы не используют? Правильно я понимаю?
IceFire Наверно всё проще, я запутался %), шадов сервисы тут не причём, возврат на сервис ведь после отработки вашего кода, который не известно что делает, предположу что в юзермод не прыгает. Вобщем у меня такие проблемы никогда не возникали, ибо я не чистил за собой(несколько килобайт памяти не критично), а код весь перемещаемый. Выделяйте пул как в 2 и пусть обработчик в нём будет, либо его чать(всего несколько инструкций). Можно гдето в уже выделенной памяти место использовать это не важно.