Приветствую всех. Пробую перехватывать прерывания(IDT), хук работает, но вот с обработкой проблемы. Вот такой код работает отменно: Код (Text): ULONG i = 0; __declspec( naked ) void int3New() { __asm inc [i]; __asm jmp int3_old; } Счетчик считает, с этим проблем нет. Но вот хочется, чтобы при каждом INT3 выводилось сообщение в лог DbgView Делаю так: Код (Text): __declspec( naked ) void int3New() { __asm pushad __asm pushfd DbgPrint("INT3"); __asm popfd __asm popad __asm jmp int3_old; } Тут уже начинаются проблемы. Если выполнить INT3 единожды, то все ок, сообщение есть, система "живёт". Но если поставить сразу два(и больше) прерывания подряд и пустить по ним прогу появляется бсод. Как я уже только не пробывал. Вот один из последних вариантов: Код (Text): __declspec( naked ) void int3New() { __asm { cli pushad pushfd mov eax, cr0 mov CR0Reg, eax and eax, 0xFFFEFFFF mov cr0, eax } __asm inc [i]; DbgPrint("INT3"); __asm { mov eax, CR0Reg mov cr0, eax popfd popad sti } __asm jmp int3_old; } Смотрел краш-дампы. Крах из-за доступа в память, куда не было доступа. Один из анализов краш-дампа(их много тк было много разных вариантов, взял один из последних): Код (Text): MODULE_NAME: TEST1 FAULTING_MODULE: 804d7000 nt DEBUG_FLR_IMAGE_TIMESTAMP: 4d662055 EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - <Unable to get error code text> FAULTING_IP: nt+79a4 804de9a4 e9c7a03677 jmp f7848a70 TRAP_FRAME: b2c83cf0 -- (.trap 0xffffffffb2c83cf0) ErrCode = 00000000 eax=b2c83da8 ebx=7ffde000 ecx=00000000 edx=00000001 esi=00291f18 edi=00291ea4 eip=804de9a4 esp=b2c83d64 ebp=b2c83d64 iopl=0 nv up ei pl nz na po nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000202 nt+0x79a4: 804de9a4 e9c7a03677 jmp f7848a70 Resetting default scope CUSTOMER_CRASH_COUNT: 26 DEFAULT_BUCKET_ID: COMMON_SYSTEM_FAULT BUGCHECK_STR: 0x8E LAST_CONTROL_TRANSFER: from 804e2440 to 804de9a4 STACK_TEXT: WARNING: Stack unwind information not available. Following frames may be wrong. b2c83d64 804e2440 badb0d00 00000001 804e2490 nt+0x79a4 b2c83d9c f8bc64e2 f8bc6690 b2c83da8 00291e01 nt+0xb440 b2c83da0 f8bc6690 b2c83da8 00291e01 00291f18 TEST1+0x4e2 b2c83da4 b2c83da8 00291e01 00291f18 0012fc94 TEST1+0x690 b2c83da8 00291e01 00291f18 0012fc94 b2c83dcc 0xb2c83da8 b2c83dac 00291f18 0012fc94 b2c83dcc 7ffde000 0x291e01 b2c83db0 0012fc94 b2c83dcc 7ffde000 00000001 0x291f18 b2c83db4 b2c83dcc 7ffde000 00000001 00000000 0x12fc94 b2c83db8 7ffde000 00000001 00000000 00291ea4 0xb2c83dcc b2c83dcc 00000000 00000302 0012fb20 00000023 0x7ffde000 STACK_COMMAND: kb FOLLOWUP_IP: TEST1+4e2 f8bc64e2 ?? ??? SYMBOL_STACK_INDEX: 2 SYMBOL_NAME: TEST1+4e2 FOLLOWUP_NAME: MachineOwner IMAGE_NAME: TEST1.sys BUCKET_ID: WRONG_SYMBOLS Followup: MachineOwner 0x0000008E = KERNEL_MODE_EXCEPTION_NOT_HANDLED 0xC0000005 = STATUS_ACCESS_VIOLATION Собственно проблема понятна, за раз обращение к одному адресу несколькими потоками. Пробовал создавать строку с фразой INT3 динамически(вызывая другую функцию естественно). (char text[4];test[0] = 'I';...;.. Но ничего не изменилось. Буду рад советам или если предложите почитать что-то про мою проблему. Я только пробую все это дело, сильно не пинайте, если упустил или не сообщил что-то. Все чисто на энтузиазме и только для себя. Тестирую под ВМ(VirtualBox последний) с системой WinXP SP3. Система "чистая". На хосте 2 проца, в ВМ используется 1.
срочно уберите этот лютый пипец) pushfd не требуется. а вот сохранять сегменты не помешало бы + перегружать fs. залей минидамп, я ничего не понял из твоего поста
Краш-дамп от этого кода: Код (Text): __declspec( naked ) void int3New() { __asm { cli pushad } __asm inc [i]; DbgPrint("INT3"); __asm { popad sti } __asm jmp int3_old; } Расскажите пожалуйста поподробней про За ужастный код мне очень стыдно, пробую все что попадается Но на ошибках учатся)
UnameR Манипуляции с cr0 не нужны. В fs должен лежать селектор 0x30, его следует установить в прологе. Там же сохранить сегментные регистры. Т.е. что-то вроде: Код (Text): push ds push es push fs push gs mov ax, 0x30 mov fs, ax Ну а в эпилоге это все надо восстановить.
А если попрбовать выводить дебаг инфу в спец системном потоке через глобальный буфер не забывая о синхранизации. Вместо DbgPrint("INT3") записывать данные в память. В другом спец потоке считывать эти данные и выводить. Такой путь хоть и более сложный но видется более надежным.
Да, это именно то, что было нужно. Благодарю. Задача не требует надёжности, это для себя. Все в подконтрольной среде, поэтому даже если и будет иногда вызывать крахи, это не страшно. Мне чисто для наблюдений Тема исчерпана. Всем спасибо.
Вообще, в Windows специально предусмотрены особые стабы, в которые оборачиваются обработчики прерываний, чтобы при передачах управления user->kernel корректно создавались бы трап фреймы, иначе вот велики шансы получить самые разнообразные бсоды из-за кучи различных особенностей и подводных камней. Чтобы корректно создавался трап фрейм, обработчик должен быть установлен не вручную, а через IoConnectInterrupt() (возможно, придется установить его на свободный рандомный вектор, а потом вручную переставить на третий). Только такая установка может гарантировать, что управление попадет в ваш обработчик только после корректного входа в ядро, а после окончания будет произведен корректный возврат через Kei386EoiHelper. И что в любой момент управление сможет быть корректно прервано по таймеру, контекст сохранён, а поток переключен на любой другой. Тогда и прерывания можно будет включить.