GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Unerwartete Exec-Berechtigung von mmap, wenn Assembly-Dateien im Projekt enthalten sind

Linux hat eine Ausführungsdomäne namens READ_IMPLIES_EXEC , was bewirkt, dass alle Seiten mit PROT_READ zugewiesen werden auch PROT_EXEC zu geben . Ältere Linux-Kernel verwendeten dies für ausführbare Dateien, die das Äquivalent von gcc -z execstack verwendeten . Dieses Programm zeigt Ihnen, ob das für sich selbst aktiviert ist:

#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;
}

Wenn Sie das zusammen mit einem leeren .s kompilieren -Datei sehen Sie, dass sie aktiviert ist, aber ohne eine wird sie deaktiviert. Der Anfangswert davon stammt aus den ELF-Metainformationen in Ihrer Binärdatei. Führen Sie readelf -Wl example aus . Sie werden diese Zeile sehen, wenn Sie ohne den leeren .s kompiliert haben Datei:

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

Aber dieses, als Sie damit kompiliert haben:

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

Beachten Sie RWE statt nur RW . Der Grund dafür ist, dass der Linker davon ausgeht, dass Ihre Assemblydateien read-implies-exec erfordern, es sei denn, es wird ausdrücklich darauf hingewiesen, dass dies nicht der Fall ist, und wenn ein Teil Ihres Programms read-implies-exec erfordert, ist es für Ihr gesamtes Programm aktiviert . Die Assembly-Dateien, die GCC kompiliert, teilen ihm mit dieser Zeile mit, dass dies nicht erforderlich ist (Sie werden dies sehen, wenn Sie mit -S kompilieren ):

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

Die standardmäßigen Abschnittsberechtigungen enthalten nicht ex ec. Siehe den ELF-Teil des .section Dokumentation zur Bedeutung der "Flags" und @attributes.

(Und vergessen Sie nicht, zu einem anderen Abschnitt wie .text zu wechseln oder .data danach .section Direktive, wenn Ihr .s stützte sich auf .text weil der Standardabschnitt am Anfang der Datei.)

Fügen Sie diese Zeile in example.s ein (und alle anderen .s Datei in Ihrem Projekt). Das Vorhandensein dieses .note.GNU-stack -Abschnitt dient dazu, dem Linker mitzuteilen, dass diese Objektdatei nicht von einem ausführbaren Stack abhängt, sodass der Linker RW verwendet statt RWE auf der GNU_STACK Metadaten, und Ihr Programm wird dann wie erwartet funktionieren.

Ähnlich für NASM, ein section Direktive mit den richtigen Flags gibt nicht ausführbare Stacks an.

Moderne Linux-Kernel zwischen 5.4 und 5.8 haben das Verhalten geändert des ELF-Programmladers. Für x86-64 wird READ_IMPLIES_EXEC nicht aktiviert mehr. Höchstens (mit einem RWE GNU_STACK hinzugefügt von ld ), erhalten Sie den Stapel selbst ausführbar, nicht jede lesbare Seite. (Diese Antwort deckt die letzte Änderung in 5.8 ab, aber es muss vorher andere Änderungen gegeben haben, da diese Frage die erfolgreiche Ausführung des Codes in .data zeigt auf x86-64 Linux 5.4)

exec-all (READ_IMPLIES_EXEC ) tritt nur bei älteren ausführbaren 32-Bit-Dateien auf, bei denen der Linker keinen GNU_STACK hinzugefügt hat Header-Eintrag überhaupt. Aber wie hier gezeigt, modernes ld fügt das immer mit der einen oder anderen Einstellung hinzu, auch wenn eine Eingabe .o Datei fehlt ein Hinweis.

Sie sollten trotzdem diesen .note verwenden -Abschnitt, um nicht ausführbare Stacks in normalen Programmen zu signalisieren. Aber wenn Sie gehofft haben, selbstmodifizierenden Code in .data zu testen oder einem alten Tutorial zum Testen von Shellcode zu folgen, das ist keine Option für moderne Kernel.


Als Alternative zum Modifizieren Ihrer Assembly-Dateien mit GNU-spezifischen Abschnittsdirektiven-Varianten können Sie -Wa,--noexecstack hinzufügen zu Ihrer Befehlszeile zum Erstellen von Assemblydateien. Sehen Sie sich zum Beispiel an, wie ich es in configure von musl mache :

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

Ich glaube, dass zumindest einige Versionen von Clang mit integriertem Assembler erfordern, dass es als --noexecstack übergeben wird (ohne den -Wa ), also sollte Ihr Konfigurationsskript wahrscheinlich beide überprüfen und sehen, welches akzeptiert wird.

Sie können auch -Wl,-z,noexecstack verwenden zur Verbindungszeit (in LDFLAGS ) um das gleiche Ergebnis zu erhalten. Der Nachteil davon ist, dass es nicht hilft, wenn Ihr Projekt statische (.a )-Bibliotheksdateien für die Verwendung durch andere Software, da Sie dann die Verbindungszeitoptionen nicht kontrollieren, wenn sie von anderen Programmen verwendet werden.


Linux
  1. Nehmen Sie die erste Spalte aus 2 Dateien und schreiben Sie sie in eine 3. Datei?

  2. Wie entferne ich die Bom aus einer UTF-8-Datei?

  3. Wie ändere ich die Berechtigung für eine einzelne Datei?

  4. Der beste „Datei-Shredder“, um Dateien aus dem System zu entfernen.?

  5. Untersuchen von Berkeley-DB-Dateien über die CLI

Kopieren Sie Dateien im Linux-Terminal

Verschieben Sie Dateien im Linux-Terminal

Die 6 besten Möglichkeiten zum Anzeigen von Dateien unter Linux

Linux-Dateiverwaltung über das Terminal

Lesen aus einer Datei in Assembly

So ändern Sie die Dateien basierend auf den Ergebnissen des Befehls find