В статье про HASP3 был очень интересный момент, до которого я никак не докопаюсь Тут несколько сложновато написано, но смысл такой: всякий раз при выполнении такого исключения все биты в DR7 скидываются, и мы получаем в исключении #1 его "чистым". Попытка проинициализировать его внутри обработчика приведет к краху системы... Это - выдержка из статьи. Так вот, уважаемый Chingachguk, почему dr7 нельзя инициализировать внутри оработчика????? В моей ХР SP2 регистр dr7 постоянно (почему-то при изменении размера любого окна) сбрасывает winlogon.exe, попытка восстановить его в драйвере ведет к заквисанию.
Ну так там же далее пояснения - как это обойти. Необходимо "вернуться" из обработчика на свой код, затем восстановить DRx, затем уже вернуться в точку исключения: Код (Text): ; подпрограмма - ловушка #1 - debug BD equ 0010000000000000b B0 equ 0001b B1 equ 0010b B2 equ 0100b B3 equ 1000b CMD_IN_AL_DX equ 0ECh TrapPort proc push ebp mov ebp,esp ... @@AfterDebugRegs: ; Запоминаем адрес возврата и возвращаемся в наш код mov dword ptr RetAddr_UD01_EIP,ecx mov word ptr RetAddr_UD01_CS,es mov [ebp+4],offset32 After_DebugRegisterUsed mov word ptr [ebp+8],cs popfd pop es pop ds popad pop eax pop ebp iretd TrapPort endp ; Я знаю, что исключение (обращение к портам или сброс DR7) ; вызвано в драйвере защиты (VXD), поэтому я не забочусь о селекторе точки исключения (cs), а только о EIP: After_DebugRegisterUsed proc pushad pushfd ; Восстанавливаем cr4 & DR7 ; Enable DE flag mov eax,cr4 or eax,01000b mov cr4,eax ; FEDCBA9876543210FEDCBA9876543210 mov eax,TrapMask ; 01100110011001100010011111111111b mov dr7,eax popfd popad ; Возвращаемся [b]near[/b] jmp'ом: jmp dword ptr RetAddr_UD01_EIP ; Хотя на самом деле корректно писать jmp far (fword ptr)[Сохраненные cs:eip адреса возврата] After_DebugRegisterUsed endp
Возможно, дело в том, что когда возникает исключение попытки сброса DRx, то при входе в обработчик исключения установлен бит DE в cr4. Если ты пытаешься его (DRx)восстановить внутри обработчика, то возникает повторное исключение или сразу GPF. Но, насколько я помню, мне не удалось найти другого решения.
Так ведь бит DE в cr4 запрещает только отладочные прерывания при обращении к портам, а я к портам пока и не обращаюсь, только пытаюсь перехватить модификацию DRx :-(
Ну да, немного не так. Ты получаешь исключение по попытке сброса DRx, затем внутри исключения пытаешься его исправить. Видимо, в этом и проблема. Возможно, надо сначала какой-то битик скинуть/поставить, но я решил это через iretd (что разрешает видимо повторную инициализацию DRx) и уже затем инициализация DRx.
Шаманство какое-то... Специально нарыл интелловские доки, читал очень вниательно и выяснил, что GD в DR7 в обработчике первого прерывания сбрасывается, то есть доступ к отладочным регистрам разрешен и это так, ибо к DR6 доступаюсь спокойно без зацикливания. Кроме того, выяснил, что iretd не сбрасывает разрешающих битов, так что дело в чем-то еще... Попробовал делать так, как у тебя, то есть подменять реальный адрес возврата по iretd на адрес своей функи... так вот, выставление этого бита в DR7 уже в ней дает тот же эффект - зависает намертво. Очень бы хотелось разобраться, как с этим быть. Возможно, что где-то в системе есть код типа: Код (Text): @1: xor ebx, ebx mov dr7, ebx ... mov ebx, dr7 test ebx, GD jnz @1 но вряд ли... посоветуй, плиз, в какую сторону копать на эту тему?
Попробовал делать так, как у тебя, то есть подменять реальный адрес возврата по iretd на адрес своей функи... Туда точно ты попадаешь ? > так вот, выставление этого бита в DR7 уже в ней дает > тот же эффект - зависает намертво. Ну у меня не совсем так, попробуй все же в точности как у меня.