ядро — на вилы КРИС КАСПЕРСКИ АКА МЫЩЪХ Спецвыпуск: Хакер, номер #069, стр. 069-032-2 Примеры готовых модулей можно найти непосредственно в самой NetBSD/OpenBSD, обратившись к каталогу /usr/share/lkm/, или скачать их напрямую из Сети (www.openbsd.org/cgi-bin/cvsweb/src/share/lkm). Забавно, но в OpenBSD эти файлы не модифицировались свыше 6 лет! Примеры из NetBSD посвежее будут — «всего» 5 лет выдержки, но, по большому счету, никакой разницы между ними нет, и они практически один в один повторяют друг друга. [MOD_SYSCALL-модуль.] Рассмотрим скелет простейшего MOD_SYSCALL-модуля, перехватывающего системный вызов #1 (mkdir) и устанавливающего на него свою хакерскую «заглушку», выводящую на экран «rock you» и мерзко пищащую спикером. При желании, из нее можно вызвать оригинальную функцию mkdir, передав управление по адресу, сохраненному в переменной old_mkdir. ЛИСТИНГ простейший LMK-модуль, демонстрирующий технику перехвата системных вызовов под NetBSD и OpenBSD /* модуль, перехватывающий mkdir и работающий под Net- и OpenBSD */ /* ============================================================== */ #include <sys/param.h> #include <sys/systm.h> #include <sys/ioctl.h> #include <sys/cdefs.h> #include <sys/conf.h> #include <sys/mount.h> #include <sys/exec.h> #include <sys/lkm.h> #include <sys/proc.h> #include <sys/syscallargs.h> #include <sys/syscall.h> /* объявляем переменную old_mkdir, в которую позже будет записан */ /* оригинальный адрес системного вызова mkdir */ int (*old_mkdir) (struct proc * p, void * v, register_t retval); /* функция-заглушка, устанавливаемая на место mkdir */ int hack(struct proc *p, void *v, int *retval) { printf ("rock you!\x7\n"); return 0; } /* процедура начальной загрузки модуля */ static int load(struct lkm_table *lkmtp, int cmd) { if (cmd == LKM_E_LOAD) /* загрузка модуля */ { printf ("syshack loadedd\n"); /* сохраняем адрес оригинального вызова mkdir */ (sy_call_t *)old_mkdir = sysent[SYS_mkdir].sy_call; /* устанавливаем вместо mkdir свою «заглушку» */ sysent[SYS_mkdir].sy_call = (sy_call_t *)hack; } if (cmd == LKM_E_UNLOAD) /* выгрузка модуля */ { printf ("syshack unloadedd\n"); /* снимаем свою «заглушку», возвращая на место mkdir */ sysent[SYS_mkdir].sy_call=(sy_call_t*)old_mkdir; } return(0); } /* точка входа в модуль */ int entry(struct lkm_table *lkmtp, int cmd, int ver) { /* сердце модуля - макрос DISPATCH */ DISPATCH(lkmtp, cmd, ver, load, load, lkm_nofunc); } Сердцем модуля является макрос DISPATCH, передающий управление функции инициализации и деинициализации (в нашем случае называется load), вызываемой при загрузке и выгрузке модуля. Для перехвата/освобождения системного вызова mkdir используется прямая правка таблицы системных вызовов sysent. В принципе, можно было воспользоваться макросом MOD_SYSCALL, но это малоинтересно. |