I understand that this module could not use the system call table address in /boot/System.map-$(uname -r)
because of KASLR. By booting with nokaslr
, the module worked. With that solved, i moved on to actually hook the kill function, but could not; insmod
again returns "Killed" on module load, while dmesg
now logs a write access permission error, which occurs on the emphasized line.
I thought that the purpose of unsetting the write protection bit on the control register was to "unset write protection". Is there anything other than that (or my code) preventing the kernel module to overwrite the system call table?
Code
#include <linux/module.h>
#include <linux/kernel.h>
typedef asmlinkage int (*sys_kill_ptr_t)(pid_t, int);
static sys_kill_ptr_t sys_kill_ptr;
static unsigned long *syscall_table;
static inline void set_cr0_wp_bit(void) { write_cr0(read_cr0() & ~0x1000); }
static inline void unset_cr0_wp_bit(void) { write_cr0(read_cr0() | 0x1000); }
asmlinkage int hooked_kill(pid_t pid, int sig)
{
printk(KERN_INFO "[+] LKM: hooked_kill called\n");
return sys_kill_ptr(pid, sig);
}
static int __init lkm_init(void)
{
printk("[+] LKM: init\n");
// System call table address in /boot/System.map-$(uname -r)
syscall_table = (unsigned long *)0xffffffff81c002a0;
printk(KERN_EMERG "[+] LKM: syscall_table @ 0x%lx\n",
(unsigned long)syscall_table);
sys_kill_ptr = (sys_kill_ptr_t)syscall_table[__NR_kill];
printk(KERN_EMERG "[+] LKM: syscall_table[__NR_kill] @ 0x%lx\n",
(unsigned long)sys_kill_ptr);
set_cr0_wp_bit();
/* Error */
syscall_table[__NR_kill] = (unsigned long)hooked_kill;
/* Error */
unset_cr0_wp_bit();
printk(KERN_EMERG "[+] LKM: syscall_table[__NR_kill] hooked @ %lx\n",
(unsigned long)hooked_kill);
return 0;
}
static void __exit lkm_exit(void)
{
set_cr0_wp_bit();
/* Error */
syscall_table[__NR_kill] = (unsigned long)sys_kill_ptr;
/* Error */
unset_cr0_wp_bit();
printk("[-] LKM: exit\n");
}
module_init(lkm_init);
module_exit(lkm_exit);
dmesg
[ 4218.114119] [+] LKM: init
[ 4218.115931] [+] LKM: syscall_table @ 0xffffffff81c002a0
[ 4218.117025] [+] LKM: syscall_table[__NR_kill] @ 0xffffffff81092fa0
[ 4218.118087] BUG: unable to handle page fault for address: ffffffff81c00490
[ 4218.119159] #PF: supervisor write access in kernel mode
[ 4218.120267] #PF: error_code(0x0003) - permissions violation