Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #69, АВГУСТ 2006 г.

ядро — на вилы

КРИС КАСПЕРСКИ АКА МЫЩЪХ

Спецвыпуск: Хакер, номер #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