Приветствую всех ! Мне нужно было осуществить перехват системных вызовов. Испробовал многие методы, но все они имеют недостатки: 1. Изменение таблицы экспортов - не все функции вызываются через таблицу. Более того, изменение необходимо производить до загрузки всех модулей. 2. jmp - работает безотказно, но существуют функции, размер которых < 5 байт 3. Посоветовали использовать прерывания - есть функции (из RtlXXX) размер которых 1 байт (XP, SP1) Осталось единственное решение - int1 или int3 4. int3 - довольно часто встречается в ntoskrnl => много ложных срабатываний. Кроме того SoftIce его юзает Остается единственное решение - int1 (Хотя SI его тоже юзает, но с ним проще). Идея заключалась в следующем а) менять вектор прерывания б) ставить 0xF1 в начало функции в) в обработчике проверять - если (адрес - 1) = адрес функции ядра, то взводить флаг трассировки, cli. Если нет, то отдавать управление оригинальному обработчику. Запоминать адрес, восстанавливать байт и iret г) после iret из стека извлекаются флаги - начинается трассировка. При первой же инструкции произойдет вызов обработчика int1 (гаратнировано, т.к. cli). Читается адрес, пишется 0xF1, и iret Надеюсь идея понятная - проблемма: 1. Ловится все нормально, но при снятии обработчика - слетает - BSOD даже не выскакивает (подозрение на разрушенный стек). Стек подчищается нормально, регистры восстанавливаются и т.д. Что может быть ? 2. С cli это все не будет работать на многопроцессорной системе, а использовать в обработчике функций ядра нельзя (т.к. может возникнуть ситуация, что прийдется ловить все NativeAPI => ловить самого себя) З.Ы. А может быть это вообще все бессмысленно )) Ведь обработчик легко снять, или обойти его Что можете посоветовать ? спасибо
Если необходима работа на многопроцессорных системах то можно использовать KeRaiseIRQL - она экспортируется из HAL а не из ntoskrnl если тебе хочется и её перехватить - пиши прямо в параметры процессора
Ну до HAL пока дело не дошло >>пиши прямо в параметры процессора А что этим можно добиться и как это ? Проблемма немного в другом: 1. Во-первых не на все функции удается поставить 0xF1 - некоторые слетают с DSOD = 7F. Некоторые функции ядра вызываются на IRQL > PASSIVE_LEVEL - может ли это быть из-за этого (или просто надо лучще продумать обработчик) 2. Некоторые функции ловятся по отдельности, но вместе слетают - тут я вообще не пойму в чем дело В общем проблемм много. Я спрашиваю только о тех, с которыми столкнулся. Очевидно есть и еще какие-нибудь. Если кто этим занимался - просьба подсказать, чтоб не терять кучу времени
напиши драйвер, йо мае. и перехватывай прерывания. а еще запрети такую фичу как SYSCALL SYSRET через CR4. потому что ХР их юзает вместо int 2fhю ессно придется самому эмулировать. а что ты будешь делать с перехваченым сискаллом - твое дело. можешь в пайп писать например.
>>напиши драйвер, йо мае. и перехватывай прерывания Так это и есть драйвер >>а еще запрети такую фичу как SYSCALL SYSRET через CR4 а чем это чревато, если не запрещать ?
хм... не совсем понял - какая разница как будет вызвана функция - код то у нее один и тот же. А на этот код я и вешаю int1 - как же они миммо пройдут ?
аааа. я не так тебя понял. в теме то прерывания, и я решил что перхват надо вести при переходе в ядро. попробуй перехватывать все таки int3 а чтоб софтайс не потер защити от него обработчик с помощью dr? и установи прерывание на обращение к отадочным регистрам.
с int1 удобнее - т.к. я в обработчике и ловлю и меняю байты опять (используя трассировку) просто другого способа пока не нашел
NT хранит информацию о состоянии процессоров во внутренних стуктурах Посмотри на KeRaiseIRQL\KeGetCurrentIRQL в дизассемблере Их можно изменить и ручками - с тем же эффектом
zss Интересно, хотелось бы увидеть код. А вообще, поищи по сайту. Гдк то была подобная утилитка одного заграничного товарища, там всё работало.
>> Интересно, хотелось бы увидеть код Это обработчик int1 StartAddress и CurrAddress - глобальные dd ModuleImage - глобальная структура OldHandler - старый обработчик смысл - смотрим адрес. Если он является точкой входа какой-либо функции, то это мой int1 и я возвращаю оригинальный байт, ставлю трассировку и cli. Через 1-2 инструкции я опять попадаю в обработчик. Проверяю - если адрес != 0 то опять ставлю int1 Иначе, если есть старый обработчик - то передаю ему управление, если нет, то просто iretd Код (Text): pop [CurrAddress] pushad cmp dword ptr [StartAddress], 0 jz _nonflag // флаг взведен mov ebx, cr0 push ebx and ebx, ~0x10000 mov cr0, ebx mov esi, [StartAddress] mov al, 0xF1 mov byte ptr [esi], al pop ebx mov cr0, ebx mov dword ptr [StartAddress], 0 popad push [CurrAddress] and dword ptr [esp + 8], 0xFFFFFEFF // TF or dword ptr [esp + 8], 0x00000200 // cli iretd _nonflag: mov esi, [CurrAddress] dec esi push esi lea eax, [ModuleImage] push eax call IsFunc test al, al je _error // начало функции mov [StartAddress], esi mov ebx, cr0 push ebx and ebx, ~0x10000 mov cr0, ebx mov byte ptr [esi], al pop ebx mov cr0, ebx push [StartAddress] call WriteHookData popad push [StartAddress] or dword ptr [esp + 8], 0x00000100 // TF and dword ptr [esp + 8], 0xFFFFFDFF //cli iretd _error: mov eax, [OldHandler] test eax, eax je _nonhandler popad push [CurrAddress] jmp [OldHandler] _nonhandler: // нет обработчика popad push [CurrAddress] iretd
Спасибо за исходник у него эпилог и пролог обработчика такой же, а что происходит в самом обработчике - это не важно. Кстати - зачем он меняет сегментные регистры - ведь обработка происходит в контексте перехватываемого процесса ? Никуда дополнительно лесть ненадо Проблемма оказалась в другом. На некоторых функциях слетает на int1. В XP с кодом 8E, а в 2k с кодом 1E (KMODE_EXCEPTION_NOT_HANDLER). 1.Есть подозрение, что все-таки int1 на каких-то уровнях IRQL приводит к BSOD. Больше грешить неначто, т.к. слетает именно на int1 (в частности на функции ExFreePoolWithTag) 2.Есть вторая возможная причина. Установка бряков и собственного обработчика происходит в cli/sti - хотя это мало вероятно... Может кто сможет подсказать в чем дело ? P.S. IRQL ExFreePoolWithTag < DISPATH_LEVEL
zss думаю, что гдето не клеятся какие нить взаимоблокировки. Та хрень, что я тебе послал, работает наура и без проблем кстати, а это здесь зачем ??? or dword ptr [esp + 8], 0x00000100 // TF and dword ptr [esp + 8], 0xFFFFFDFF //cli ты интелловские мануалы хорошо читал ???? Это лишнее, при выходе из обработчика процессор сам всё ставит на сви места а уровень прерывания тут не при чём. #DB , если он корректно написан, может быть вызван на любом уровне irql, главное, чтоб #PF не вызвал. Вот и всё