GNU/Linux >> Tutoriels Linux >  >> Linux

Autorisation exec inattendue de mmap lorsque les fichiers d'assemblage sont inclus dans le projet

Linux a un domaine d'exécution appelé READ_IMPLIES_EXEC , ce qui fait que toutes les pages sont allouées avec PROT_READ à attribuer également PROT_EXEC . Les anciens noyaux Linux l'utilisaient pour les exécutables qui utilisaient l'équivalent de gcc -z execstack . Ce programme vous montrera si cela est activé pour lui-même :

#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 vous compilez cela avec un .s vide fichier, vous verrez qu'il est activé, mais sans un, il sera désactivé. La valeur initiale de ceci provient des méta-informations ELF dans votre binaire. Faites readelf -Wl example . Vous verrez cette ligne lorsque vous aurez compilé sans le .s vide fichier :

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

Mais celui-ci lorsque vous l'avez compilé :

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

Remarque RWE au lieu de simplement RW . La raison en est que l'éditeur de liens suppose que vos fichiers d'assemblage nécessitent read-implies-exec à moins qu'il ne soit explicitement indiqué qu'ils ne le font pas, et si une partie de votre programme nécessite read-implies-exec, alors il est activé pour l'ensemble de votre programme . Les fichiers d'assemblage compilés par GCC lui indiquent qu'il n'en a pas besoin, avec cette ligne (vous le verrez si vous compilez avec -S ):

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

Les autorisations de section par défaut n'incluent pas ex ec. Voir la partie ELF du .section documentation pour la signification des "drapeaux" et des @attributs.

(Et n'oubliez pas de passer à une autre section comme .text ou .data après cela .section directive, si votre .s s'appuyait sur .text car la section par défaut en haut du fichier.)

Mettez cette ligne dans example.s (et tous les autres .s fichier dans votre projet). La présence de ce .note.GNU-stack servira à dire à l'éditeur de liens que ce fichier objet ne dépend pas d'une pile exécutable, donc l'éditeur de liens utilisera RW au lieu de RWE sur le GNU_STACK métadonnées, et votre programme fonctionnera alors comme prévu.

De même pour NASM, un section directive avec les bons drapeaux spécifie des piles non exécutables.

Les noyaux Linux modernes entre 5.4 et 5.8 ont changé le comportement du chargeur de programme ELF. Pour x86-64, rien ne s'allume READ_IMPLIES_EXEC plus. Au plus (avec un RWE GNU_STACK ajouté par ld ), vous obtiendrez la pile elle-même exécutable, pas toutes les pages lisibles. (Cette réponse couvre le dernier changement, dans 5.8, mais il doit y avoir eu d'autres changements avant cela, puisque cette question montre une exécution réussie du code dans .data sur x86-64 Linux 5.4)

exec-all (READ_IMPLIES_EXEC ) ne se produit que pour les anciens exécutables 32 bits où l'éditeur de liens n'a pas ajouté de GNU_STACK entrée d'en-tête du tout. Mais comme montré ici, le ld moderne ajoute toujours cela avec un paramètre ou l'autre, même lorsqu'une entrée .o il manque une note au fichier.

Vous devriez toujours utiliser ce .note section pour signaler les piles non exécutables dans les programmes normaux. Mais si vous espériez tester le code auto-modifiable en .data ou suivre un ancien tutoriel pour tester le shellcode, ce n'est pas une option sur les noyaux modernes.


Au lieu de modifier vos fichiers d'assemblage avec des variantes de directive de section spécifiques à GNU, vous pouvez ajouter -Wa,--noexecstack à votre ligne de commande pour créer des fichiers d'assemblage. Par exemple, voyez comment je le fais dans configure de musl :

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

Je crois qu'au moins certaines versions de clang avec assembleur intégré peuvent nécessiter qu'il soit passé en tant que --noexecstack (sans le -Wa ), donc votre script de configuration devrait probablement vérifier les deux et voir lequel est accepté.

Vous pouvez également utiliser -Wl,-z,noexecstack au moment de la liaison (en LDFLAGS ) pour obtenir le même résultat. L'inconvénient est que cela n'aide pas si votre projet produit des statiques (.a ) les fichiers de bibliothèque à utiliser par d'autres logiciels, puisque vous ne contrôlez alors pas les options de temps de liaison lorsqu'elles sont utilisées par d'autres programmes.


Linux
  1. Que se passe-t-il exactement lorsque j'exécute un fichier dans le shell ?

  2. Facl Ignorant La Permission "x" Mais Uniquement Sur Les Fichiers ?

  3. Grep Word dans un fichier puis copier le fichier ?

  4. Prendre la première colonne de 2 fichiers et l'écrire dans un 3ème fichier ?

  5. Comment supprimer le Bom d'un fichier UTF-8 ?

Copier des fichiers dans le terminal Linux

Déplacer des fichiers dans le terminal Linux

Les 6 meilleures façons d'afficher des fichiers sous Linux

Gestion de fichiers Linux depuis le terminal

Examen des fichiers Berkeley DB à partir de la CLI

Comment supprimer les lignes qui apparaissent sur le fichier B d'un autre fichier A ?