unixoidКрис КасперскиВ поискахшапки-невидимкиОбнаружение компрометации ядер Linux и xBSD, или Руткиты тожеоставляют следы…Рост популяции руткитов, оккупировавших никсы, продолжается ударнымитемпами. Они поражают системы, не обремененные антивирусами ипрочими защитными механизмами, которые уже давно стали привычнымисредствами обороны в мире Windows. Поэтому приходится выдумыватьчто-то концептуальное.Согласно общепринятой классификации, руткитами называютпрограммы (обычно безвредные), предназначенные длясокрытия сетевых соединений, процессов и дисковых файлов,а также других программ, чаще всего довольно агрессивныхпо натуре (чего им тогда шифроваться, спрашивается). Классификация— это прекрасно, но на практике нам приходится бороться не с руткитамив чистом виде (тоже мне, понимаешь, сферические кони в вакууме), а сразличными механизмами маскировки. Огромное количество червей (ипрочей малвари) имеет встроенные руткиты с полиморфным движком. Поэтомуусловимся понимать под руткитами любую нечисть, занимающуюсясокрытием системных объектов (файлов, процессов, сетевых соединений).Своих или чужих — неважно. Попробуем разобраться — как же работает эташапка-невидимка, и какие способы обнаружения руткитов существуют.Кочевые племена против оседлых форм жизниСуществуют два типа руткитов: первые, внедряясь в систему, создаютновые файлы или модифицируют уже существующие, получая управлениепри каждой загрузке операционной системы. Другие же — вообщене прикасаются к диску, не создают новых процессов, ограничиваясьмодификацией оперативной памяти. Естественно, руткиты такого типаумирают при перезагрузке и выглядят не слишком-то жизнеспособными,однако до тех пор, пока дыра, через которую проникает руткит, остается неxàêåð 07 /115/ 08078
unixoidОсновное место околоруткитной тусовки — www.rootkit.comДизассемблерный листинг функции system_call, обращающейся к таблицесистемных вызовов sys_call_tableзалатанной, он будет приходить вновь и вновь. Закрытие дырымало чего изменит, ведь там, где есть одна дыра, найдутся идругие — создателю руткита достаточно переписать несколькодесятков строк кода, ответственных за внедрение первичногозагрузчика в целевую систему, — и дело сделано.В распределенных сетях (ботнетах) перезагрузка одного илинескольких узлов — вообще не проблема, к тому же после перезагрузкиузел будет инфицирован вновь. Этот факт очень труднообнаружить, ведь никаких изменений на диске нет! А сетевыесоединения современные руткиты скрывают весьма эффективно.Прошли те времена, когда открытые порты обнаруживалисьтривиальным сканированием с соседней машины. Продвинутыеруткиты не открывают никаких портов. Они садятся на сетевойинтерфейс, контролируя трафик и модифицируя определенныеполя в заголовках TCP/IP-пакетов, значения которых согласноRFC выбираются случайным образом. Скремблер скроет фактмодификации (независимо от передаваемых руткитом данныхмы получим такое же хаотичное распределение, как и на незараженноймашине), а несимметричный шифратор предотвратитдекодирование перехваченной информации. Даже если мызаведомо знаем, что руткит есть!Откуда мы узнаем, что он есть? Объем трафика в норме,никаких изменений на диске не наблюдается (что кардинальнымобразом отличается от руткитов первого типа, которыеобнаруживаются настолько тривиально, насколько этоможно себе представить). Загружаемся с LiveCD и проверяемконтрольные суммы всех файлов (или просто осуществляемпобайтовое сравнение с дистрибутивом). Конечно, для серверовтакой способ не очень-то пригоден — их вообще лучшене перезагружать, но сервера, критичные к перезагрузкам,обычно оснащены RAID-массивами с hot-plug’ом. Так чтопросто вытаскиваем один набор дисков из матрицы, ставимего на другую машину, проверяем контрольную сумму и делаеморгвыводы.Короче говоря, руткиты, вносящие изменения в файловуюсистему, нам неинтересны, и дальше мы будем говорить исключительноо заразе, обитающей непосредственно в оперативнойпамяти и получающей управление путем модификацииядра (поскольку на прикладном уровне нормальному руткитуделать нечего).Методы борьбы, или была б катана —сделал бы харакириПрежде чем продвигаться вглубь, сразу выбросим на помойкунесколько популярных, но безнадежно устаревших способовборьбы с руткитами. Чтение памяти ядра через /dev/[k]memxàêåð 07 /115/ 08(при активом рутките!) — это курам на смех. Поиск следовкомпрометации при помощи GDB — из той же оперы. Руткитуничего не стоит отследить обращение к любому файлу/устройству,«вычистив» следы своего пребывания или совершить«харакири» при запуске GDB. Чуть сложнее — ввестив заблуждение GDB, оставаясь при этом активным, живым издоровым.Достойных отладчиков ядерного уровня под никсы не существует.Ну, не то, чтобы совсем нет, но в штатный комплект поставкиуж точно ни один не входит. Хорошо еще, если установкаотладчика не требует перекомпиляции ядра, не говоря уже оперезагрузке. Самих же отладчиков довольно много: NLKD,KDB, LinIce, DDB, и ни один из них не обладает неоспоримымипреимуществами перед остальными. Кстати, для ловли руткитовиметь готовый к употреблению отладчик необязательно.Достаточно написать загружаемый модуль ядра, считывающийи передающий на прикладной уровень все критичные кперехвату структуры данных вместе с машинным кодом (естественно,ядро должно быть скомпилировано с поддержкоймодульности). Что это за данные — мы сейчас выясним.Магические аббревиатуры — GDT, LDT, IDTСокрытие чего бы там ни было базируется на перехвате/модификацииядерных структур данных/системного кода. Способовперехвата придумано множество, и каждый день появляютсяновые. Однако количество самих системных структур ограничено,что существенно упрощает борьбу с заразой.Начнем с простого. С таблиц глобальных/локальных дескрипторов(Global/Local Description Table или, сокращенно,GDT/LDT), хранящих базовые адреса, лимиты и атрибутыселекторов. Чем они могут помочь руткиту? Ну, кое-чем могут.Linux/xBSD используют плоскую модель памяти, при которойселекторы CS (код), DS (данные) и SS (стек) «распахнуты» навсе адресное пространство: от нуля до самых верхних егоокраин. Создание нового селектора с базой, отличной от нуля,с последующей его загрузкой в один из сегментных регистровсущественно затрудняет дизассемблирование руткита,особенно тех экземпляров, что выдраны из памяти чужоймашины. Таблицы дескрипторов в распоряжении реверсеранет и не будет (руткит умер). Грубо говоря, мы вообще не можемопределить, к каким данным осуществляется обращение,ведь база селектора неизвестна! Реверсеров и сотрудниковантивирусных компаний такие руткиты просто доводят добешенства, затягивая анализ, а вместе с ним и приготовление«вакцины».Побочным эффектом этого антиотладочного приема стано-info• Перехват системноговызова sys_readпозволяет руткитуконтролироватьобращения ко всемфайлам, устройствами псевдоустройствам.• Начиная с версии2.5, ядро Linux поддерживаетмеханизмбыстрых системныхвызовов, реализуемыйкомандамиSYSENTER/SYSEXIT(Intel) и SYSCALL/SYSRET (AMD), существеннооблегчающийперехват и делающийего труднозаметным.• Продвинутыеруткиты не открываютникаких портов, онисадятся на сетевойинтерфейс, контролируятрафики модифицируя определенныеполяв заголовках TCP/IPпакетов.079