Разница в защите от записи ядра между 4.15 и 5.3 - PullRequest
2 голосов
/ 25 марта 2020

Я пишу простой руткит (просто чтобы узнать, как работает ядро;)), который перехватывает функцию filldir в ядре.

Я использую метод inline hook - запись кода операции JMP в начале функции.

функция выглядит так -

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

При компиляции и тестировании в Ubuntu 16.04 (ядро 4.15) все работает просто отлично, но при использовании Ubuntu 19.10 (Kernel 5.3) - я получаю cra sh каждый раз, когда я insmod.

cra sh, потому что permissions при записи в защищенную память - это означает (я так думаю), что строка отключения защиты от записи не работает (write_cr0(read_cr0() & (~ 0x10000));).

Я не нашел никакой документации, объясняющей, почему она не работает в новой версии ядра, действительно ли она связана с версией ядра? или я делаю что-то не так? Я предполагаю, что в новой версии был добавлен какой-то новый метод защиты, и «старое» отключение защиты больше не работает ...

также, если это действительно проблема версии ядра, есть ли способ отключить эту защиту в новой версии ядра?

btw, попробуйте также отключить, используя этот код -

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