kernel-mode перехват для антивируса

Тема в разделе "WASM.NT.KERNEL", создана пользователем whitequark, 24 фев 2008.

  1. EvilPhreak

    EvilPhreak New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2007
    Сообщения:
    154
    Clerk
    А что собственно не устраивает в правке SDT? Сейчас все современные антивирусы юзают этот метод. Сплайс имеет более сложную реализацию и меньшую стабильность. Снять хуки смогут всегда, имхо надо использовать самый стабильный метод, которым и язвляется правка SDT. Ну я могу ошибатся, но пока в этом топе никто более стабильного не озвучил.

    2FED
    Читают файл ядра с диска и сравнивают. Насчет 20 байт неправда, можно сканить хоть до конца, все зависит от степени извращенности автора и предпологаемых методов поиска.
     
  2. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Именно тем и не устраивает, SDT юзают все и вся; это простой способ для новичков в этом деле; сплайсинг более стабилен, тут никакой сложности нету, его обнаружить сложнее. Нужно упомянуть тут что многие структуры и функции вызываются косвенно, через ссылки в переменных секции данных, а загружаются они при инициализации ядра - с образа на диске не востановиш и не сравниш. Проблемы с синхронизацией решаются с помощью APIC и сплайсингом не первых байт функции, а инструкции далее, занимающей размер >= размеру jmp(ведь процессор на половине инструкции переключить задачу не может). Можно использовать таблицу, другую чем определена в KeServiceDescriptorTable; или вообще не использовать эти таблицы. Кстати тут надо упомянуть про IDT, тут тоже по вашему надо юзать; но на многопроцессорной машине это приведёт к некоторым сложностям, темболее просто изменить дескрипторы или даже idtr и вызвать сервис посредством прерывания, в обход SDT
     
  3. nxbit159

    nxbit159 AntiEXE

    Публикаций:
    0
    Регистрация:
    20 фев 2008
    Сообщения:
    13
    Сплайсинг в чистом виде без навешивания патч протекта давным давно умер товарищ Clerk, и не х. трясти тут вековой пылью.
     
  4. Deyton

    Deyton Member

    Публикаций:
    0
    Регистрация:
    7 мар 2007
    Сообщения:
    94
    Clerk
    Удалять гланды через задницу тоже можно, но не стоит; но это так - оффтоп.
     
  5. 2FED

    2FED New Member

    Публикаций:
    0
    Регистрация:
    20 фев 2008
    Сообщения:
    1.002
    Clerk а что такое APIC?
     
  6. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    и как же?
    есть вероятность того, что в момент генерации широковещательного IPI, один из CPU уже выполнил часть пролога
     
  7. fret

    fret New Member

    Публикаций:
    0
    Регистрация:
    30 янв 2008
    Сообщения:
    24
    Ну-ну. Значит ты не новичок и не ищешь легких путей? Спаси меня боже от софта таких "не новичков", ибо худшего кг/ам'а не бывает.
     
  8. tylerdurden

    tylerdurden New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2004
    Сообщения:
    322
    Хукай сисентер
     
  9. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    От инструкции sysenter до перехода на сервис в SST процессор выполняет сотни инструкций;
    При вызове функции ZwXX в ядре управление передаётся на KiSystemServiceRepeat;
    sysenter->KisystemService->KiSystemServiceRepeat->KiSystemServiceCopyArguments->...
    Этот код(многие места в этом коде) можно перенаправить на свой обработчик, он будет вызван перед вызовом сервиса в SDT;
    Кстати, если GUI сервис -> call [_KeGdiFlushUserBatch] ;.data - здесь сплайсинг не нужен
    Надо ещё раз сказать что адреса многих функций определены в переменных, например:
    IoAllocateIrp:
    mov edi,edi
    push ebp
    mov ebp,esp
    pop ebp
    jmp dword ptr ds:[485788h]
    На эту функцию множество ссылок в ntos, для её перехвата сплайсинг вовсе не нужен;
    Можно перехватить многие функции в hal, которые очень часто вызываются из микроядра.
    Касательно синхронизации ядер наверно можно использовать префикс LOCK перед инструкциями, я точно не знаю, наверно одновременно писать код по адресу и выполнять его там несколько процессоров не могут - изза блокировки шины.
     
  10. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    допустим есть код
    Код (Text):
    1.     push ebp
    2.     mov ebp, esp
    и двуядерный процессор
    на первом ядре выполняется код, осуществляющий модификацию приведенного выше кода
    на втором ядре выполняется вышеприведенный код
    допустим, выполнение инструкции
    push ebp
    завершилось и тут же возникло прерывание (например, по таймеру)
    а первое ядро в этот момент модифицирует код
    на какую инструкцию будет осуществлен возврат из обработчика прерывания? ;)
    тут дело не совсем в LOCK (хотя он тоже нужен), а в том, что нет гарантии, что часть модифицируемого кода уже не выполнена
    единственный вариант, искать инструкцию, которая будет по размеру >= размеру внедряемой инструкции
     
  11. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Я это и имел ввиду, конечно с приведённым кодом работать не будет;
    jmp near занимает пять байт, jmp short занимает два байта; надо изменить команду, которая будет занимать >= чем два байта на jmp short Reference_; найтити свободное место поблизости модифицируемой команды - это будет адрес Reference_ и записать команду перехода по этому адресу на наш обработчик. Конечно последовательность записи должна быть соответствующей, тоесть последним должна изменятся перехватываемая команда.
    Это если модифицируемая команда занимает два байта, иначе придётся искать более длинные команды что не всегда возможно.
     
  12. PROFi

    PROFi New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2003
    Сообщения:
    690
    Clerk

    "Проблемы с синхронизацией решаются с помощью APIC" - и как же это они решаются :) Может и исключения CPU тоже так решать :)? А что делать если у процессоров вооще нет общей шины APIC (Advanced Prog. Interrupt Controller) - blade сервер например.

    "Кстати тут надо упомянуть про IDT" - нужно, нужно конечно, не понял конечно в чем проблема "но на многопроцессорной машине это приведёт к некоторым сложностям" - отсылаем всем процессорам DPC процедуру, в ней в свою очередь меняем на всех процессорах IDT (про ассемблерную инструкцию cli не забываем), только по sysenter (или syscall у AMD) забыли...


    "модификация кода" - на работающей машине вполне возможна из ядра как - см абзац выше. Естественно нормальный руткит такого себе непозволит, а антивирус может. Вот только вопрос - манипуляция объектами ядра уже сейчас не новость - причем работающая и под вистой, насколько реально загрузить второй ntoskrnl.exe отмепировать его и поюзать неперехваченные функции - вот это уже поновее (да забыл сказать - секции данных естественно копируются с оригинала) и дружно отсылает любую модификацию кода в указанном модуле. Чтобы было понятнее - пример - есть драйвер который выводит инфу в инет, крутой антивирус хакает этот драйвер, чтобы никто по его мнению не отправил данные - а крутой вирус просто подгружает поверх исходный бинарник драйвера, оставляя секцию данных нетронутой - как сделать см. абзац выше - и всем хукам кранты, но если вирус еще круче - большинство устройств имеют PCI конф область - считал данные и шуруй напрямую в порты, и плевать такому вирусу на все хуки.

    В общем со "Основные требования - стабильность, переносимость" это никак не вяжется.

    А что вяжется - Тут нужно понять функционал антивируса. 1) это только сканер - тогда ему нужно до диска добраться напрямую + парсер файловой системы (куда ж без него). Причем правило кто первый в ядре сдесь не всегда играет роль, если антивирус сумел запустить драйвер - то дальше все зависит от знаний автора антивируса 2) это проактивка - вот тут то хуков ставь непереставь. Но работает простой принцип - все, что может выполнится - начиная с кода БИОСА и т.д. по ходу загрузки системы, должно быть проверено - пример BitLocker в Висте - ой как висту все не любят, а если еще битлокер подключить... Причем битлокер - это не антивирус - просто шифрование. 3) это антируткит - еще проще - весь ввод вывод должен идти через драйвер антируткита. Т.е. на самом низком уровне антируткит должен подменять собой все драйверы ввода вывода, как бы обвалакивая их, и чтобы никто в системе не усомнился в том, что драйвер устройства может иметь другое имя кроме как имя антируткита. - На сегодняшний день это конечно VTx или Pacifica (AMD), но кто ж их знает, этож сложно даже для Касперского.

    Вот такая ситуация вырисовывается.
     
  13. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Гыы.. Поновее..
     
  14. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    шутишь?
    две lock-инструкции работают, к сожалению, не атомарно
    если ты внедришь short jump, то есть вероятность, что по этому jump осуществится переход не на твою инструкцию (которую ты просто не успеешь заменить), а на другую, а это уже нарушение семантики исходного кода
    вот проверенный мной вариант, правда для Linux
    1. вызываем on_each_cpu() с функцией, которая изменяет IA32_LSTAR (RIP для SYSCALL)
    т. к рано или поздно будет осуществлен переход R3 -> R0 на каждом CPU в системе
    2. при передаче управления на мою функцию, каждый CPU атомарно (lock) декрементирует счетчик (первоначально значение равно числу CPU в системе)
    если результат не ноль, переходим на цикл из двух инструкций
    Код (Text):
    1.     monitor
    2.     mwait
    если ноль, тот CPU, для которого это условие выполнилось, модифицирует какой угодно код
    и далее осуществляет запись в область адресного пространства, для которой работает монитор на всех остальных CPU
    далее каждый CPU восстанавливает IA32_LSTAR и передает управление на оригинальный обработчик SYSCALL
     
  15. synus0ida

    synus0ida New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2008
    Сообщения:
    20
    PROFi,
    хм, а можно чуть подробнее об этом, у всех ли сетевых есть этот конфиг, отличается ли он у разных сетевух, ка на асме разговаривать с сетевухой взяв за основу конфиг?
     
  16. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Прошу прщения, описался <=
     
  17. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Надо читать внимательно, зачем две lock-иструкции ?, jmp short занимает два байта, которые заменяются одной инструкцией lock mov или xchg, короче кто хотел тот понял о чём речь.
    Зачем ?
    Ведь можно выполнить манипуляции с ThreadAffinityMask или обождать процессор через чтение в цикле ApicId.

    synus0ida
    Очём Ты ?
     
  18. tylerdurden

    tylerdurden New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2004
    Сообщения:
    322
    Какие сотни, надо просто настроить сегментные регистры, стека ядра и все. Выполнить ф-ю напрямую так вообще одна строка.
     
  19. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    для этого целевой код должен находится в пределах от -128 до +127 байт от short jmp
    что нереально (или почти нереально)
    удачи
    для того, чтобы гарантировать невыполнение процессором модифицируемого кода
    причем здесь привязка CPU к потоку и APIC ID?
     
  20. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    если сетевой контроллер является устройством PCI, то он обязательно поддерживает конфигурационное пространство
    конфигурационное пространство содержит ряд регистров, которые должны поддерживаться устройством обязательно
    остальные не специфицированы
    найти через BAR (в конфигурационном пространстве) адрес, куда отображены регистры устройства
    дальше используя спецификацию читать/записывать в них нужную информацию