Обработчик прерываний

Тема в разделе "WASM.WIN32", создана пользователем zss, 10 ноя 2004.

  1. zss

    zss New Member

    Публикаций:
    0
    Регистрация:
    11 июл 2004
    Сообщения:
    40
    Адрес:
    Чехов-2
    Приветствую всех !



    Мне нужно было осуществить перехват системных вызовов.

    Испробовал многие методы, но все они имеют недостатки:



    1. Изменение таблицы экспортов - не все функции вызываются через таблицу. Более того, изменение необходимо производить до загрузки всех модулей.

    2. jmp - работает безотказно, но существуют функции,

    размер которых < 5 байт :dntknw:

    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 => ловить самого себя)



    З.Ы. А может быть это вообще все бессмысленно :))) Ведь обработчик легко снять, или обойти его



    Что можете посоветовать ?



    спасибо
     
  2. nobody

    nobody New Member

    Публикаций:
    0
    Регистрация:
    8 сен 2004
    Сообщения:
    32
    Адрес:
    Afghanistan
    Если необходима работа на многопроцессорных системах то можно использовать KeRaiseIRQL - она экспортируется из HAL а не из ntoskrnl

    если тебе хочется и её перехватить - пиши прямо в параметры процессора
     
  3. zss

    zss New Member

    Публикаций:
    0
    Регистрация:
    11 июл 2004
    Сообщения:
    40
    Адрес:
    Чехов-2
    Ну до HAL пока дело не дошло :)

    >>пиши прямо в параметры процессора

    А что этим можно добиться и как это ?



    Проблемма немного в другом:

    1. Во-первых не на все функции удается поставить 0xF1 - некоторые слетают с DSOD = 7F. Некоторые функции ядра вызываются на IRQL > PASSIVE_LEVEL - может ли это быть из-за этого (или просто надо лучще продумать обработчик)

    2. Некоторые функции ловятся по отдельности, но вместе слетают - тут я вообще не пойму в чем дело



    В общем проблемм много. Я спрашиваю только о тех, с которыми столкнулся. Очевидно есть и еще какие-нибудь. Если кто этим занимался - просьба подсказать, чтоб не терять кучу времени :)
     
  4. Narkomanius

    Narkomanius New Member

    Публикаций:
    0
    Регистрация:
    14 апр 2003
    Сообщения:
    144
    напиши драйвер, йо мае. и перехватывай прерывания. а еще запрети такую фичу как SYSCALL SYSRET через CR4. потому что ХР их юзает вместо int 2fhю ессно придется самому эмулировать. а что ты будешь делать с перехваченым сискаллом - твое дело. можешь в пайп писать например.
     
  5. zss

    zss New Member

    Публикаций:
    0
    Регистрация:
    11 июл 2004
    Сообщения:
    40
    Адрес:
    Чехов-2
    >>напиши драйвер, йо мае. и перехватывай прерывания



    Так это и есть драйвер :)



    >>а еще запрети такую фичу как SYSCALL SYSRET через CR4



    а чем это чревато, если не запрещать ?
     
  6. Narkomanius

    Narkomanius New Member

    Публикаций:
    0
    Регистрация:
    14 апр 2003
    Сообщения:
    144
    а тем что все сискаллы пойдут неперехвачеными

    если это ХР конечно. в 2к такого безобразия нету
     
  7. zss

    zss New Member

    Публикаций:
    0
    Регистрация:
    11 июл 2004
    Сообщения:
    40
    Адрес:
    Чехов-2
    хм... не совсем понял - какая разница как будет вызвана функция - код то у нее один и тот же. А на этот код я и вешаю int1 - как же они миммо пройдут ?
     
  8. Narkomanius

    Narkomanius New Member

    Публикаций:
    0
    Регистрация:
    14 апр 2003
    Сообщения:
    144
    аааа. я не так тебя понял. в теме то прерывания, и я решил что перхват надо вести при переходе в ядро.

    попробуй перехватывать все таки int3 а чтоб софтайс не потер защити от него обработчик с помощью dr? и установи прерывание на обращение к отадочным регистрам.
     
  9. zss

    zss New Member

    Публикаций:
    0
    Регистрация:
    11 июл 2004
    Сообщения:
    40
    Адрес:
    Чехов-2
    с int1 удобнее - т.к. я в обработчике и ловлю и меняю байты опять (используя трассировку)



    просто другого способа пока не нашел :)
     
  10. zss

    zss New Member

    Публикаций:
    0
    Регистрация:
    11 июл 2004
    Сообщения:
    40
    Адрес:
    Чехов-2
    возможно, что проблеммы возникают и из-за SoftIce, но иначе никак не отладить :)
     
  11. nobody

    nobody New Member

    Публикаций:
    0
    Регистрация:
    8 сен 2004
    Сообщения:
    32
    Адрес:
    Afghanistan
    syscall\sysenter можно перехватить через MSR - регистры
     
  12. nobody

    nobody New Member

    Публикаций:
    0
    Регистрация:
    8 сен 2004
    Сообщения:
    32
    Адрес:
    Afghanistan




    NT хранит информацию о состоянии процессоров во внутренних

    стуктурах

    Посмотри на KeRaiseIRQL\KeGetCurrentIRQL в дизассемблере

    Их можно изменить и ручками - с тем же эффектом
     
  13. zss

    zss New Member

    Публикаций:
    0
    Регистрация:
    11 июл 2004
    Сообщения:
    40
    Адрес:
    Чехов-2
    это мне конечно понадобиться, но потом... :)



    а сейчас, как то отклонились от темы :)
     
  14. zss

    zss New Member

    Публикаций:
    0
    Регистрация:
    11 июл 2004
    Сообщения:
    40
    Адрес:
    Чехов-2
    меня пока больше интерисуют последствия int1 на IRQL > PASSIVE_LEVEL, или причины ошибок в другом ?
     
  15. CARDINAL

    CARDINAL Member

    Публикаций:
    0
    Регистрация:
    23 янв 2004
    Сообщения:
    551
    Адрес:
    Moscow
    zss



    Интересно, хотелось бы увидеть код. А вообще, поищи по сайту. Гдк то была подобная утилитка одного заграничного товарища, там всё работало.
     
  16. CARDINAL

    CARDINAL Member

    Публикаций:
    0
    Регистрация:
    23 янв 2004
    Сообщения:
    551
    Адрес:
    Moscow
    zss

    а вот irql тут вообще не при чём .
     
  17. zss

    zss New Member

    Публикаций:
    0
    Регистрация:
    11 июл 2004
    Сообщения:
    40
    Адрес:
    Чехов-2
    >> Интересно, хотелось бы увидеть код



    Это обработчик int1

    StartAddress и CurrAddress - глобальные dd

    ModuleImage - глобальная структура

    OldHandler - старый обработчик



    смысл - смотрим адрес. Если он является точкой входа какой-либо функции, то это мой int1 и я возвращаю оригинальный байт, ставлю трассировку и cli.

    Через 1-2 инструкции я опять попадаю в обработчик. Проверяю - если адрес != 0 то опять ставлю int1



    Иначе, если есть старый обработчик - то передаю ему управление, если нет, то просто iretd


    Код (Text):
    1.  
    2. pop [CurrAddress]
    3. pushad
    4.  
    5. cmp dword ptr [StartAddress], 0
    6. jz  _nonflag
    7.  
    8. // флаг взведен
    9.  
    10. mov ebx, cr0
    11. push    ebx
    12. and ebx, ~0x10000
    13. mov cr0, ebx           
    14.  
    15. mov esi, [StartAddress]
    16. mov al, 0xF1
    17. mov byte ptr [esi], al
    18.  
    19. pop ebx
    20. mov cr0, ebx
    21.  
    22. mov dword ptr [StartAddress], 0
    23. popad
    24. push    [CurrAddress]
    25. and dword ptr [esp + 8], 0xFFFFFEFF // TF  
    26. or  dword ptr [esp + 8], 0x00000200 // cli
    27. iretd
    28.  
    29. _nonflag:
    30.  
    31. mov esi, [CurrAddress]
    32. dec esi
    33. push    esi
    34. lea eax, [ModuleImage]
    35. push    eax
    36. call    IsFunc
    37. test    al, al
    38. je  _error
    39.  
    40. // начало функции
    41.  
    42. mov [StartAddress], esi
    43. mov ebx, cr0
    44. push    ebx
    45. and ebx, ~0x10000
    46. mov cr0, ebx           
    47.  
    48. mov byte ptr [esi], al
    49. pop ebx
    50. mov cr0, ebx
    51.  
    52. push    [StartAddress]
    53. call    WriteHookData
    54.  
    55. popad
    56. push    [StartAddress]
    57. or  dword ptr [esp + 8], 0x00000100 // TF
    58. and dword ptr [esp + 8], 0xFFFFFDFF //cli
    59. iretd
    60.  
    61. _error:
    62.  
    63. mov eax, [OldHandler]
    64. test    eax, eax
    65. je  _nonhandler
    66.  
    67. popad
    68. push    [CurrAddress]
    69. jmp [OldHandler]
    70.  
    71. _nonhandler:
    72. // нет обработчика
    73. popad
    74. push    [CurrAddress]
    75. iretd
    76.  
     
  18. CARDINAL

    CARDINAL Member

    Публикаций:
    0
    Регистрация:
    23 янв 2004
    Сообщения:
    551
    Адрес:
    Moscow
  19. zss

    zss New Member

    Публикаций:
    0
    Регистрация:
    11 июл 2004
    Сообщения:
    40
    Адрес:
    Чехов-2
    Спасибо за исходник :)



    у него эпилог и пролог обработчика такой же, а что происходит в самом обработчике - это не важно.



    Кстати - зачем он меняет сегментные регистры - ведь обработка происходит в контексте перехватываемого процесса ? Никуда дополнительно лесть ненадо :)



    Проблемма оказалась в другом. На некоторых функциях слетает на int1. В XP с кодом 8E, а в 2k с кодом 1E (KMODE_EXCEPTION_NOT_HANDLER).



    1.Есть подозрение, что все-таки int1 на каких-то уровнях IRQL приводит к BSOD. Больше грешить неначто, т.к. слетает именно на int1 (в частности на функции ExFreePoolWithTag)

    2.Есть вторая возможная причина. Установка бряков и собственного обработчика происходит в cli/sti - хотя это мало вероятно...



    Может кто сможет подсказать в чем дело ?



    P.S. IRQL ExFreePoolWithTag < DISPATH_LEVEL
     
  20. CARDINAL

    CARDINAL Member

    Публикаций:
    0
    Регистрация:
    23 янв 2004
    Сообщения:
    551
    Адрес:
    Moscow
    zss

    думаю, что гдето не клеятся какие нить взаимоблокировки. Та хрень, что я тебе послал, работает наура и без проблем



    кстати, а это здесь зачем ???

    or dword ptr [esp + 8], 0x00000100 // TF

    and dword ptr [esp + 8], 0xFFFFFDFF //cli



    ты интелловские мануалы хорошо читал ????

    Это лишнее, при выходе из обработчика процессор сам всё ставит на сви места



    а уровень прерывания тут не при чём. #DB , если он корректно написан, может быть вызван на любом уровне irql, главное, чтоб #PF не вызвал. Вот и всё :)