
ядро — на вилы
КРИС КАСПЕРСКИ АКА МЫЩЪХ
Спецвыпуск: Хакер, номер #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, но это малоинтересно.
Назад на стр. 069-032-1 Содержание Вперед на стр. 069-032-3
|