[PHASE 1. Sample Dasar LKM pada Kernel 2.6x] Loadable kernel module adl bagian dari kernel linux yang kita tambahkan ke base kernel (kode kernel linux dasar) secara on the fly. dengan adanya lkm keunggulanya adl lebih hemat memori dan kita gak perlu repot 2 recompile kernel kita klo kita mao nambahin modul ke dalem kernel. Kali ini kita akan bermain main dengan loadable kernel module untuk kernel 2.6x , pada contoh kali ini menggunakan kernel 2.6.35-22-generic untuk menyisipkan suatu modul baru ke kernel gunakan perintah insmod, contoh: ============ #insmod nama_modul.ko ============ n.b: harus dilakukan sebagai root. Untuk melihat kernel2 modul yg sedang diload bisa diliat di /proc/modules ============= ev1lut10n@ev1l:~$ cat /proc/modules binfmt_misc 6599 1 - Live 0xf8195000 parport_pc 26058 0 - Live 0xf8170000 ppdev 5556 0 - Live 0xf80be000 snd_hda_codec_realtek 217980 1 - Live 0xf82c4000 joydev 8735 0 - Live 0xf8097000 snd_hda_intel 22107 4 - Live 0xf8cb2000 snd_hda_codec 87552 2 snd_hda_codec_realtek,snd_hda_intel, Live 0xf8c82000 snd_hwdep 5040 1 snd_hda_codec, Live 0xf8afd000 snipped====== misal kita lihat yg binfmt_misc: binfmt_misc-- nama lkm 6599 -- ukuran lkm yg diload ke memori dalam byte 1 --- banyaknya dependensi Live --- berarti module sudah diload setelah init modul 0xf8195000 -- merupakan alamat memori di kernel space (offset module diload) Sebelum mulai install kernel header (linux kernel header dibutuhkan untuk mengkompile lkm kita nanti) ============ apt-get install kernel-headers-$(uname -r) ============ misal : ============= #uname -r 2.6.35-22-generic #apt-get install linux-headers-2.6.35-22-generic cek setelah instalasi: #ls /lib/modules/2.6.35-22-generic/build arch drivers init lib net sound usr block firmware ipc Makefile samples source virt crypto fs Kbuild mm scripts tools Documentation include kernel Module.symvers security ubuntu ============= struktur dasar lkm: - init_module ---- modul diinisialisasi int init_module(void) { } - cleanup_module ----------unload modul secara clean saat exit int cleanup_module(void) { } - entry dan exit function: module_init(init_module); module_exit(cleanup_module); Contoh lkm di sini kita pakai struktur dasar : ======================= #include <linux/module.h> MODULE_LICENSE("GREY HAT"); MODULE_AUTHOR("ev1lut10n"); int init_modulku( void ) { printk(KERN_INFO "hai dmesg ini fungsi init\n"); return 0; } void cleanup_modulku( void ) { printk(KERN_INFO "see u dmesg ini fungsi cleanup\n"); return; } module_init(init_modulku); module_exit(cleanup_modulku); ===================== selanjutnya misal simpan dengan nama : ev1lut10n.c siapkan suatu Makefile dengan isi misal (sesuaikan versi kernel): =================== obj-m += ev1lut10n.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean =================== selanjutnya ketikkan make: ===================================== # make make -C /lib/modules/2.6.35-22-generic/build M=/home/mywisdom/www/artikel modules make[1]: Entering directory `/usr/src/linux-headers-2.6.35-22-generic' CC [M] /home/mywisdom/www/artikel/ev1lut10n.o Building modules, stage 2. MODPOST 1 modules CC /home/mywisdom/www/artikel/ev1lut10n.mod.o LD [M] /home/mywisdom/www/artikel/ev1lut10n.ko make[1]: Leaving directory `/usr/src/linux-headers-2.6.35-22-generic' # ======================================= jika berhasil maka akan tercipta file ev1lut10n.ko =============== # ls -la *.ko -rw-r--r-- 1 root root 2787 2011-09-13 01:51 ev1lut10n.ko # modinfo ev1lut10n.ko filename: ev1lut10n.ko author: ev1lut10n license: GREY HAT srcversion: 0A941DA1D5AC55B86B25E1B depends: vermagic: 2.6.35-22-generic SMP mod_unload modversions 686 ================= selanjutnya untuk meload lkm tadi dengan insmod: ============= # insmod ev1lut10n.ko ============== untuk melihat hasil printk di kernel space bisa dengan dmesg: =============== # dmesg | tail [ 32.112080] Skipping EDID probe due to cached edid [ 32.593054] Skipping EDID probe due to cached edid [ 37.344059] Skipping EDID probe due to cached edid [ 116.906126] warning: `proftpd' uses 32-bit capabilities (legacy support in use) [ 2289.736043] Skipping EDID probe due to cached edid [ 6153.780062] device eth0 entered promiscuous mode [ 6195.524833] teredo: Disabled Privacy Extensions [ 6204.544338] teredo: no IPv6 routers present [ 6383.024787] device eth0 left promiscuous mode [16824.579333] hai dmesg ini fungsi init ================= [16824.579333] hai dmesg ini fungsi init ---- printk(KERN_INFO "hai dmesg ini fungsi init\n"); untuk melihat module yang tadi kita load: ===================== # cat /proc/modules | grep ev1l ev1lut10n 702 0 - Live 0xf8179000 (P) ===================== * PRINTK printk merupakan fungsi yang bisa dipakai untuk kernel debugging mode dikombinasikan dengan perintah dmesg. berikut ini beberapa level debugging dari printk: ==================== # cat /usr/include/linux/kernel.h | grep 'printk(K' printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__) --------pesan emergency biasanya muncul sebelum crash wkwkwkwk printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__) ------- butuh tindakan secepatnya printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__) -------pesan kritis biasanya berhubungan dengan kegagalan hardware atau software (critical damage) printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) ------- kondisi error printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__) ------------ peringatan printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__) -----------notice printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) ---informasi printk(KERN_CONT fmt, ##__VA_ARGS__) ------- melanjutkan baris yang sudah dimulai sebelumnya printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) ----- digunakan utk pesan pada debugging ===================== [PHASE 2. Simbol Kernel] simbol kernel akan banyak dipakai oleh programmer linux kernel. Daftar2 simbol kernel yang diload bisa didapatkan pada file2 berikut ini (baik secara plain maupun binary) ==================== /proc/kallsyms (kernel 2.6.x) /proc/ksyms (kernel 2.4.x) /boot/System.map* /usr/src/linux/System.map /lib/modules/*/System.map /boot/vmlinux /boot/vmlinuz and so on....bla bla bla ==================== misal untuk melihat simbol2 kernel yang diload : ================ ev1lut10n@ev1l:~$ cat /proc/kallsyms | grep cred c016c300 T override_creds c016c3a0 T get_task_cred c016c3f0 T __put_cred c016c440 t release_tgcred_rcu c016c480 t put_cred_rcu c016c520 T revert_creds c016c560 T abort_creds c016c590 T prepare_creds c016c640 T copy_creds c016c830 T commit_creds ==========cuted cuted cuted=========== ======================= daftar2 di atas merupakan nama 2 fungsi maupun variabel global. Simbol2 kernel di atas merujuk pada alamat2 memori kernel space. Jadi bisa dibilang simbol kernel sbg nama 2 yang merujuk pada alamat2 memori kernel space yang berisi variabel global maupun suatu fungsi pada suatu loadable kernel module. mari kita lihat dari lkm yg di atas kita buat tadi: ================ # cat /proc/kallsyms | grep modulku f80b9000 t cleanup_modulku [ev1lut10n] ================ f80b9000 --- merupakan alamat memori kernel space yang merujuk pada fungsi cleanup_modulku t - merupakan tipe simbol kernel pada banyak exploit2 kernel untuk escalate privilege kernel simbol ini biasanya akan dibaca untuk mendapatkan alamat memori fungsi 2 yang dibutuhkan untuk eksploitasi berikut ini potongan kode dari fungsi yang berjalan di userspace untuk mendapatkan kernel simbol yang dicomot dari salah satu local root exploit: ================= f = fopen("/proc/kallsyms", "r"); ---------membaca dari /proc/kallsyms if (f == NULL) { ----------jika tidak bisa f = fopen("/proc/ksyms", "r"); -----------------baca dari /proc/ksyms if (f == NULL) { goto fallback; } oldstyle = 1; ------------jika /proc/ksyms bisa dibaca berarti versi kernel di bawah kernel 2.6 } --------------biasanya setelah ini diikuti rutin untuk membaca /boot/System.Map***bla***bla** ================== sebenernya pada setiap local root exploit kekuranganya adl tidak adanya metode pembacaan kernel simbol secara lengkap, Untuk membuat local root exploit dengan metode pengambilan kernel simbol secara lebih lengkap bisa menggunakan ksymhunter yang bisa diambil dan bisa kita modifikasi dari: https://github.com/jonoberheide/ksymhunter untuk menggunakanya sangat mudah: ======================== root@ev1l:/home/ev1lut10n/jonoberheide-ksymhunter-2570d5b# ./ksymhunter usage: ./ksymhunter symbol_name root@ev1l:/home/ev1lut10n/jonoberheide-ksymhunter-2570d5b# ./ksymhunter cleanup_modulku [+] trying to resolve cleanup_modulku... [+] resolved cleanup_modulku using /proc/kallsyms [+] resolved cleanup_modulku to 0xf80b9000 root@ev1l:/home/ev1lut10n/jonoberheide-ksymhunter-2570d5b# ======================== di atas kita bisa melihat fungsi cleanup_modulku berada pada alamat memori kernel space : 0xf80b9000 [PHASE 3. Userspace dan Kernel Space] Kernel space kita analogikan saja sbg tempat kernel dieksekusi dan user space tempat semua program buatan si user di sistem linux berjalan. suatu program yang berjalan di userspace tidak bisa seenaknya mengakses kernel space, user space bisa mengontak kernel space melalui syscall. Berikut ini diagram cara kerja user space saat menggunakan syscall pada suatu program C: [User Space ] [Kernel Space] [./exploit] [c library] [kernel] ---------------setuid(0);--------->>> | ---argumen eax=__NR_setuid lalu panggil kernel dengan int 80h----->>>|----system_call_table[eax]-->>>|--->>> (sys_setuid()) * SYSCALL syscall merupakan penghubung antara aplikasi yang berjalan di user space dan layanan2 yang disediakan oleh kernel. pada linux kernel 2.6.35-22-generic, daftar syscall bisa dilihat di /usr/include/bits/syscall. ============================== root@ev1l# cat /usr/include/bits/syscall.h | grep define #define SYS__sysctl __NR__sysctl #define SYS_access __NR_access #define SYS_acct __NR_acct #define SYS_add_key __NR_add_key #define SYS_adjtimex __NR_adjtimex #define SYS_afs_syscall __NR_afs_syscall #define SYS_alarm __NR_alarm #define SYS_brk __NR_brk #define SYS_capget __NR_capget #define SYS_capset __NR_capset #define SYS_chdir __NR_chdir #define SYS_chmod __NR_chmod #define SYS_chown __NR_chown #define SYS_chroot __NR_chroot #define SYS_clock_getres __NR_clock_getres #define SYS_clock_gettime __NR_clock_gettime #define SYS_clock_nanosleep __NR_clock_nanosleep #define SYS_clock_settime __NR_clock_settime #define SYS_clone __NR_clone #define SYS_close __NR_close #define SYS_creat __NR_creat ------------------cuted-------------- ===================================