GNU/Linux >> Tutoriales Linux >  >> Linux

Permiso ejecutivo inesperado de mmap cuando se incluyen archivos de ensamblaje en el proyecto

Linux tiene un dominio de ejecución llamado READ_IMPLIES_EXEC , lo que hace que todas las páginas se asignen con PROT_READ también se le dará PROT_EXEC . Los kernels de Linux más antiguos solían usar esto para ejecutables que usaban el equivalente de gcc -z execstack . Este programa le mostrará si eso está habilitado por sí mismo:

#include <stdio.h>
#include <sys/personality.h>

int main(void) {
    printf("Read-implies-exec is %s\n", personality(0xffffffff) & READ_IMPLIES_EXEC ? "true" : "false");
    return 0;
}

Si compila eso junto con un .s vacío archivo, verá que está habilitado, pero sin uno, estará deshabilitado. El valor inicial de esto proviene de la metainformación de ELF en su binario. Haz readelf -Wl example . Verás esta línea cuando compilaste sin el .s vacío archivo:

  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10

Pero este cuando compilaste con él:

  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RWE 0x10

Nota RWE en lugar de solo RW . La razón de esto es que el enlazador asume que sus archivos de ensamblaje requieren read-imlies-exec a menos que se le indique explícitamente que no lo hacen, y si alguna parte de su programa requiere read-imlies-exec, entonces está habilitado para todo su programa. . Los archivos de ensamblaje que compila GCC le dicen que no necesita esto, con esta línea (lo verá si compila con -S ):

    .section        .note.GNU-stack,"",@progbits

Los permisos de sección predeterminados no incluyen ex CE. Ver la parte ELF del .section documentación sobre el significado de las "banderas" y @atributos.

(Y no olvide cambiar a otra sección como .text o .data después de eso .section directiva, si su .s confiaba en .text porque la sección predeterminada en la parte superior del archivo.)

Pon esa línea en example.s (y cualquier otro .s archivo en su proyecto). La presencia de ese .note.GNU-stack servirá para decirle al enlazador que este archivo de objeto no depende de una pila ejecutable, por lo que el enlazador usará RW en lugar de RWE en el GNU_STACK metadatos, y su programa funcionará como se esperaba.

De manera similar para NASM, un section directiva con las banderas correctas especifica pilas no ejecutables.

Los kernels de Linux modernos entre 5.4 y 5.8 cambiaron el comportamiento del cargador de programas ELF. Para x86-64, nada enciende READ_IMPLIES_EXEC más. Como máximo (con un RWE GNU_STACK añadido por ld ), obtendrá que la pila en sí sea ejecutable, no todas las páginas legibles. (Esta respuesta cubre el último cambio, en 5.8, pero debe haber habido otros cambios antes de eso, ya que esa pregunta muestra la ejecución exitosa del código en .data en x86-64 Linux 5.4)

exec-all (READ_IMPLIES_EXEC ) solo ocurre con ejecutables heredados de 32 bits donde el enlazador no agregó un GNU_STACK entrada de encabezado en absoluto. Pero como se muestra aquí, ld moderno siempre agrega eso con una configuración u otra, incluso cuando una entrada .o al archivo le falta una nota.

Deberías seguir usando este .note sección para señalar pilas no ejecutables en programas normales. Pero si esperaba probar el código automodificable en .data o siguiendo algún tutorial antiguo para probar Shellcode, esa no es una opción en los núcleos modernos.


Como alternativa a la modificación de sus archivos ensamblados con variantes de directivas de sección específicas de GNU, puede agregar -Wa,--noexecstack a su línea de comando para crear archivos de ensamblaje. Por ejemplo, vea cómo lo hago en configure de musl :

https://git.musl-libc.org/cgit/musl/commit/configure?id=adefe830dd376be386df5650a09c313c483adf1a

Creo que al menos algunas versiones de clang con ensamblador integrado pueden requerir que se pase como --noexecstack (sin el -Wa ), por lo que su script de configuración probablemente debería verificar ambos y ver cuál es aceptado.

También puedes usar -Wl,-z,noexecstack en el momento del enlace (en LDFLAGS ) para obtener el mismo resultado. La desventaja de esto es que no ayuda si su proyecto produce estática (.a ) archivos de biblioteca para que los use otro software, ya que no controla las opciones de tiempo de enlace cuando otros programas lo usan.


Linux
  1. Copiar archivos en la terminal de Linux

  2. Mover archivos en la terminal de Linux

  3. ¿Qué sucede exactamente cuando ejecuto un archivo en el Shell?

  4. ¿Grep Word dentro de un archivo y luego copia el archivo?

  5. ¿A dónde van los archivos cuando se emite el comando Rm?

Las 6 mejores formas de ver archivos en Linux

Gestión de archivos de Linux desde la terminal

¿Cómo cambiar el permiso en un solo archivo?

La mejor "trituradora de archivos" para eliminar archivos del sistema.

Cómo modificar los archivos en función de los resultados del comando de búsqueda

¿Cómo eliminar archivos .fuse_hidden*?