GNU/Linux >> Tutoriales Linux >  >> Linux

¿Por qué es necesario modificar las tablas de llamadas del sistema en Linux?

Puede verificar si son de solo lectura buscando los símbolos del kernel. La "R" significa solo lectura.

$ grep sys_call_table /proc/kallsyms
0000000000000000 R sys_call_table
0000000000000000 R ia32_sys_call_table
0000000000000000 R x32_sys_call_table

Así que son solo lectura, y lo han sido desde el kernel 2.6.16. Sin embargo, un rootkit del kernel tiene la capacidad de hacer que se puedan volver a escribir. Todo lo que necesita hacer es ejecutar una función como esta en modo kernel (directamente o a través de dispositivos ROP suficientemente flexibles, de los cuales hay muchos) con cada dirección como argumento:

static void set_addr_rw(const unsigned long addr)
{
    unsigned int level;
    pte_t *pte = lookup_address(addr, &level);

    if (pte->pte &~ _PAGE_RW)
        pte->pte |= _PAGE_RW;

    local_flush_tlb();
}

Esto cambia los permisos de la tabla syscall y permite editarla. Si esto no funciona por cualquier motivo, la protección contra escritura en el núcleo se puede desactivar globalmente con el siguiente ASM:

cli
mov %cr0, %eax
and $~0x10000, %eax
mov %eax, %cr0
sti

Esto deshabilita las interrupciones, deshabilita el bit WP (Write-Protect) en CR0 y vuelve a habilitar las interrupciones. El uso de ensamblaje permite que esto funcione a pesar de write_cr0(read_cr0() & ~0x10000) fallando debido a la función predefinida para escribir en CR0 ahora fijando bits sensibles. Sin embargo, ¡asegúrate de volver a habilitar WP después!

Entonces, ¿por qué está marcado como de solo lectura si es tan fácil de desactivar? Una de las razones es que existen vulnerabilidades que permiten modificar la memoria del kernel pero no necesariamente ejecutar directamente el código. Al marcar áreas críticas del kernel como de solo lectura, se vuelve más difícil explotarlas sin encontrar un adicional vulnerabilidad para marcar las páginas como escribibles (o deshabilitar la protección contra escritura por completo). Ahora bien, esto no proporciona una seguridad muy sólida, por lo que la razón principal por la que se marca como de solo lectura es para que sea más fácil detener accidental. sobrescribe para que no provoque un bloqueo del sistema catastrófico e irrecuperable.

* El ejemplo particular dado es para un procesador x86_64. La primera tabla es para llamadas al sistema en modo nativo de 64 bits (x64). El segundo es para llamadas al sistema en modo de 32 bits (IA32). El tercero es para el ABI syscall x32 que rara vez se usa y que permite que los programas usen todas las funciones del modo de 64 bits (por ejemplo, SSE en lugar de x87 para operaciones de punto flotante) mientras usan punteros y valores de 32 bits.

† ​​La API interna del kernel cambia todo el tiempo, por lo que esta función exacta puede no funcionar en kernels más antiguos o más nuevos. Deshabilitar globalmente CR0.WP en ASM, sin embargo, está garantizado que funcionará en todos los sistemas x86 independientemente de la versión del kernel.


Como señaló forest, el Linux moderno no permite esto, pero es fácil de anular.

Sin embargo, históricamente fue útil (y tal vez todavía lo sea) por motivos de seguridad:parches en caliente contra vulnerabilidades. En la década de 1990 y principios de la de 2000, cada vez que se anunciaba una nueva vulnerabilidad para una llamada al sistema, no necesitaba absolutamente (ptrace era muy común en ese entonces), escribiría un módulo del kernel para sobrescribir la dirección de la función en la tabla syscall con la dirección de una función que acaba de ejecutar return -ENOSYS; . Esto eliminó la superficie de ataque hasta que estuvo disponible un kernel actualizado. Para algunas llamadas al sistema dudosas, no necesitaba que tuvieran vulnerabilidades repetidamente, simplemente hice esto por ellas de manera preventiva y dejé el módulo habilitado todo el tiempo.


Linux
  1. Cómo verificar la versión del Kernel en Linux

  2. Linux:¿métodos de invocación de llamadas al sistema en el nuevo kernel?

  3. Linux:¿por qué existe una política de kernel de Linux para nunca romper el espacio del usuario?

  4. Linux:¿por qué el kernel no puede ejecutar Init?

  5. Tabla de llamadas del sistema Linux o hoja de trucos para ensamblaje

¿Linux es un sistema operativo o un kernel?

¿Por qué necesitamos un gestor de arranque en un dispositivo integrado?

La llamada al sistema Linux más rápida

¿Cómo pasar parámetros a la llamada del sistema Linux?

¿Por qué Linux es similar a Unix si su núcleo es monolítico?

Fork vs Clone en 2.6 Kernel Linux