Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
Tools/GitHubGitHub/tgies/copy-fail-c
Privilege EscalationExploit-FrameworksSchwachstellenanalyseExploitationPapers & ForschungLernen & BildungPayload-EntwicklungBinary-Exploitation
GitHubtgies/copy-fail-c

copy-fail-c

Plattformübergreifender C-Port des Copy Fail Linux LPE (CVE-2026-31431). Offengelegt 2026-04-29 von Theori / Xint.

Repository anzeigen
4401213vor 1 MonatVon Kitploit geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

Copy Fail (CVE-2026-31431) – C-Portierung

Englisch (en) ∙ 日本語 (ja) ∙ 简体中文 (zh-cn) ∙ 한국어 (ko) ∙ Русский (ru)

Eine plattformunabhängige C-Neuimplementierung des Copy-Fail-Linux-LPE (CVE-2026-31431), offengelegt am 29.04.2026 von Theori / Xint. Die vollständige Schwachstellenbeschreibung, der Zeitplan und der Entdeckungsprozess von Theori finden Sie im offiziellen Writeup unter copy.fail.

Der öffentlich veröffentlichte Proof-of-Concept ist ein 732 Byte großes Python-Skript. Diese C-Portierung zeigt, dass derselbe Exploit als portables C ausgedrückt werden kann, das auf jede Architektur kompilierbar ist, die nolibc unterstützt – ohne architekturspezifische Hex-Blobs oder Inline-Assembler im eigenen Quellcode des Projekts.

Autor dieser Portierung: Tony Gies [email protected]. Entdeckung und ursprüngliche Offenlegung: Theori / Xint.

Repository-Struktur

root@kitploit:~
copy-fail-c/
├── exploit.c           the dropper (binary-mutation variant)
├── exploit-passwd.c    the dropper (/etc/passwd UID-flip variant)
├── vulnerable.c        non-destructive vulnerability checker
├── payload.c           the body that gets dropped (setgid+setuid+execve sh)
├── utils.c, utils.h    shared AF_ALG/splice page-cache mutation primitive
├── Makefile            build orchestration
├── nolibc/             vendored from torvalds/linux tools/include/nolibc
└── README.md           this file

After make:

root@kitploit:~
├── payload             tiny static ELF, embedded into the dropper as bytes
├── payload.o           payload wrapped as a relocatable .o by `ld -r -b binary`
├── exploit             dropper, binary-mutation variant
├── exploit-passwd      dropper, /etc/passwd UID-flip variant
└── vulnerable          non-destructive vulnerability checker

exploit.c öffnet die Ziel-Binärdatei schreibgeschützt und führt dann für jedes 4-Byte-Fenster des eingebetteten Payloads eine einzelne fehlerhafte AEAD-Entschlüsselung über AF_ALG durch, deren Chiffrat-Eingabe per splice() von den Page-Cache-Seiten des Ziels bereitgestellt wird. Die In-Place-Optimierung der authencesn-Vorlage behandelt die gesplicten Quellseiten sowohl als Chiffrat-Eingabe als auch als Klartext-Ziel, sodass die (fehlschlagende) Entschlüsselung die Page-Cache-Seite bereits überschrieben hat, wenn die Authentifizierungsprüfung die Anforderung ablehnt. Nach 4 * N Iterationen wurde das zwischengespeicherte Image des Ziels Byte für Byte durch den Payload ersetzt. Ein execve() des Ziels lädt die mutierten Seiten; der Inode auf der Festplatte ist immer noch setuid root, sodass der Kernel Root-Berechtigungen gewährt und den Payload ausführt.

payload.c ist einfaches portables C: setgid(0); setuid(0); execve("/bin/sh", ...). nolibc liefert _start, die Syscall-Mechanik und das architekturspezifische Register-Management.

Eine zweite Variante, exploit-passwd.c, mutiert vier Bytes des Page-Caches von /etc/passwd anstelle des Images einer setuid-Binärdatei. Sie benötigt keinen eingebetteten Payload und funktioniert auf Systemen, auf denen der Binärmutationsweg blockiert ist, aber ihre „Cashout“-Oberfläche ist viel schmaler.

vulnerable.c ist kein Exploit. Es erstellt eine lokale testfile mit dem String init und führt dann dieselbe patch_chunk()-Primitive gegen den Page-Cache dieser Datei aus, um die Bytes mit vulnerable zu überschreiben. Stimmen die zurückgelesenen Inhalte überein, befindet sich der laufende Kernel im Fenster von CVE-2026-31431. Der Inode auf der Festplatte wird nie geändert; testfile wird beim Beenden gelöscht; die Page-Cache-Mutation verschwindet mit ihm. Läuft ohne Privilegien. Beendet sich mit 100, wenn anfällig, mit 0, wenn die Primitive lief, aber die Mutation nicht wirksam wurde, mit 2, wenn die AF_ALG-Socket-Familie oder die authencesn-Vorlage nicht verfügbar ist, sodass der Patch-Status nicht bestimmt werden kann, und mit 1 für andere Laufzeitfehler.

Build

Standard (Host-Architektur nativ):

root@kitploit:~
make

Cross-Kompilieren nach aarch64 (oder eine andere Linux-Architektur, für die ein Cross-Toolchain installiert ist):

root@kitploit:~
make CC=aarch64-linux-gnu-gcc LD=aarch64-linux-gnu-ld

Von der mitgelieferten nolibc unterstützte Architekturen (laut Upstream): x86_64, i386, arm, aarch64, riscv32/64, mips, ppc, s390x, loongarch, m68k, sh, sparc. nolibc wählt anhand der Architektur-Makros des Compilers aus, daher reicht die Auswahl der richtigen CC/LD.

Erforderlich zum Bauen:

  • ein C-Compiler (cc, gcc oder eine beliebige Cross-Variante)
  • ein Linker, der ld -r -b binary unterstützt (sowohl binutils ld als auch lld tun das)
  • Kernel-UAPI-Header mit linux/if_alg.h und <asm/unistd.h> (Debian/Ubuntu: linux-libc-dev; Cross-Varianten: normalerweise durch das Cross-Toolchain-Paket mitgeliefert)

Headersets älter als Linux 5.6 haben __kernel_old_time_t und struct __kernel_old_timespec nicht, die die mitgelieferte nolibc verwendet. compat.h (wird beim Payload-Build per Force-Include eingebunden) liefert sie, wenn sie fehlen, sodass auch ein älteres linux-libc-dev noch baut. Bei 5.6+ Headern ist es ein No-Op.

Es gibt keine externen Bibliotheksabhängigkeiten. Der Payload wird freistehend gegen nolibc gebaut; der Dropper linkt nur für fprintf und perror gegen die Host-libc.

Architekturentscheidungen

Einige kleine Toolchain-Funktionen tragen den Großteil dazu bei, den Quellcode portabel und den Payload klein zu halten.

nolibc

nolibc/ ist der winzige Header-Only-libc-Ersatz des Kernels, aus torvalds/linux tools/include/nolibc/ übernommen. Es stellt _start, ein portables syscall()-Makro und Inline-Syscall-Wrapper bereit, wobei die architekturspezifischen Registerkonventionen in nolibc/arch-*.h codiert sind. Das Bauen des Payloads mit -nostdlib -static -ffreestanding -Inolibc erzeugt ein winziges statisches ELF, das direkt in den Kernel aufruft, ohne glibc-Startup, TLS-Init oder Stack-Canary-Infrastruktur mitzuschleppen. Ergebnis nach Packen und Section-Stripping (beide unten): ~720 Bytes auf x86_64, ~1,2 KB auf aarch64, gegenüber ~17 KB für dasselbe payload.c gelinkt gegen musl-static oder ~700 KB gegen glibc-static.

ld -r -b binary zum Einbetten

Das Makefile verwandelt das gebaute payload-ELF in payload.o mittels ld -r -b binary -o payload.o payload. Der Linker gibt die Eingabe-Bytes wörtlich als Datensektion einer verschiebbaren Objektdatei aus und synthetisiert drei Symbole aus dem Eingabedateinamen:

root@kitploit:~
_binary_payload_start    Adresse des ersten Payload-Bytes
_binary_payload_end      Adresse ein Byte hinter dem letzten Payload-Byte
_binary_payload_size     absolutes Symbol, dessen Wert die Größe in Bytes ist

exploit.c deklariert die ersten beiden als extern const unsigned char[] und berechnet die Größe als _binary_payload_end - _binary_payload_start.

-Wl,-N plus enges max-page-size

Der Payload wird statisch gelinkt mit -Wl,-N -Wl,-z,max-page-size=0x10, was .text/.rodata/.data in ein einzelnes LOAD-Segment mit 16-Byte-Dateiausrichtung zusammenfasst, anstatt der Standard-Kernelseiten-Ausrichtung von 4 KB pro Segment. Dies erzeugt eine „RWX permissions“-Warnung von ld, die nur informativ ist – der Laufzeitspeicherschutz des Payloads spielt für sein einziges Ziel keine Rolle. Ohne dieses Flag linkt derselbe Code auf ~13 KB auf x86_64 (meistens Zwischensegment-Nullfüllung); damit auf ~1,3 KB vor dem unten beschriebenen Section-Header-Strip.

Entfernen von Section-Headern

Nach dem Linken entfernt objcopy --strip-section-headers die Section-Header-Tabelle und .shstrtab des Payloads. Der Kernel-ELF-Loader mappt ein Programm ausschließlich aus seinen Programm-Headern, daher werden diese Bytes nie zur Laufzeit geladen, und da payload wörtlich eingebettet wird, blähen sie auch den Drop und die patch_chunk-Iterationsanzahl auf. Das Entfernen reduziert den x86_64-Payload von ~1,3 KB auf 720 Bytes (322 Vier-Byte-Iterationen auf 180). Zwei Linker-Flags sparen den Rest: -Wl,--build-id=none entfernt die Build-Id-Notiz und -fcf-protection=none entfernt die x86-CET-Notiz, wo der Compiler dies unterstützt.

Der Strip benötigt binutils >= 2.40. Cross-Builds übergeben das objcopy des Ziels mittels OBJCOPY= (z. B. OBJCOPY=aarch64-linux-gnu-objcopy); wenn objcopy dies nicht kann, gibt der Build einen Hinweis aus und behält einen gültigen, größeren Payload.

Varianten und Cashout-Viabilität

Dieses Repository enthält zwei Exploit-Varianten, die sich die AF_ALG/Splice-Page-Cache-Mutationsprimitive teilen, aber unterschiedlich in Root-Ausführung münden. Ihre Zuverlässigkeitsprofile sind nicht gleichwertig, und der Unterschied ist wichtig, wenn man über reale Bedrohungsmodelle nachdenkt.

Binärmutationsvariante (exploit)

Mutiert den Page-Cache einer Ziel-setuid-Binärdatei mit den eingebetteten Payload-Bytes und führt dann die Binärdatei aus. Der Kernel gewährt Root-Berechtigungen aus dem unberührten setuid-Bit der Binärdatei auf der Festplatte, lädt das korrumpierte In-Memory-Image und führt den Payload aus.

Funktioniert überall dort, wo der Angreifer open(target, O_RDONLY) für eine beliebige Root-setuid-Binärdatei im System aufrufen kann. Wird mehr oder weniger ausgehebelt durch Umgebungen, die setuid-Binärdateien hinter Verzeichnissen mit eingeschränktem Lesezugriff absichern, sowie durch setuid-freie Systemdesigns.

Variante mit UID-Flip in /etc/passwd (exploit-passwd)

Mutiert vier Bytes des Page-Caches von /etc/passwd, um das UID-Feld des laufenden Benutzers auf „0000“ zu setzen. /etc/passwd ist auf jedem Standard-Linux-System weltweit lesbar, daher ist die Mutation universell. Die Umwandlung in Root-Ausführung hängt davon ab, dass ein Prozess mit Root-Rechten den Benutzer über getpwnam/getpwuid auflöst und basierend auf der aufgelösten UID handelt, ohne Quervalidierung. Viele solche Verbraucher existieren; viele davon prüfen defensiv gegen die Kernel-Sicht der aufrufenden UID oder gegen Dateibesitzer auf der Festplatte, was das Cashout unterbricht.

Cashout-Viabilitätsmatrix

Umsteigen, nachdem su fehlschlägt

exploit-passwd führt nach der Mutation su <user> aus, als denkbar einfachstes Cashout. Das funktioniert gegen util-linux su, schlägt aber gegen shadow-utils su mit „Cannot determine your user name“ fehl. Die Page-Cache-Mutation ist zu diesem Zeitpunkt noch vorhanden, und ein Umstieg auf jedes andere Cashout (z. B. Verwendung eines Daemons, der Benutzer via getpwnam ohne Quervalidierung auflöst) ist zu diesem Zeitpunkt möglich. Führen Sie echo 3 > /proc/sys/vm/drop_caches als root aus, um den korrumpierten Page-Cache nach Abschluss der Tests zu leeren.

Betroffene Kernel

root@kitploit:~
Untergrenze: torvalds/linux 72548b093ee3   August 2017, v4.14
                                            (AF_ALG iov_iter-Umarbeitung, die
                                             die Dateiseiten-Schreibprimitive via
                                             splice in die AEAD-Streuliste einführte)

Obergrenze:  torvalds/linux a664bf3d603d   April 2026, mainline
                                            (macht die In-Place-Optimierung von
                                             algif_aead von 2017 rückgängig; trennt
                                             Quell- und Ziel-Streulisten, sodass
                                             Page-Cache-Seiten nicht länger ein
                                             beschreibbares Crypto-Ziel sein können)

Dazwischen: alle großen Distro-Kernel, die den Fix nicht zurückportiert haben. Ubuntu, RHEL, SUSE, Amazon Linux und Debian wurden zum Zeitpunkt der Offenlegung in ihren Standard-Cloud-Image-Kernels als anfällig bestätigt. Backports auf Distro-Ebene begannen um den 29.04.2026 zusammen mit der öffentlichen Offenlegung. Um zu überprüfen, ob ein Zielkernel im Fenster liegt, prüfen Sie, ob a664bf3d603d (oder der distrospezifische Backport) im Git-Log des Kernels oder im Changelog der Distribution vorhanden ist.

Kommerzieller Support

Für kostenpflichtige Sicherheitsüberprüfungen, kundenspezifische Portierungsarbeiten oder private Sicherheitshinweise kontaktieren Sie den Autor über seine Beratungsfirma Crash United, LLC.

Kontakt: [email protected] · https://crashunited.com
GitHub: @tgies · X/Twitter: @me_irl

Lizenz und Credits

Entdeckung und ursprüngliche Offenlegung von CVE-2026-31431: Theori / Xint. Öffentliches Writeup: https://copy.fail/.

Diese C-Portierung: Tony Gies [email protected]

nolibc/: aus dem Linux-Kernel-Baum übernommen, dual-lizenziert LGPL-2.1-or-later ODER MIT (siehe nolibc/nolibc.h und individuelle Datei-SPDX-Header).

Die Dropper- und Payload-Quellen in diesem Repository werden unter denselben dualen LGPL-2.1-or-later ODER MIT-Bedingungen wie der nolibc-Baum veröffentlicht, von dem sie abhängen, um die Lizenzkompatibilität für jeden zu gewährleisten, der dieses gesamte Verzeichnis in eigene Arbeiten übernimmt.

Der Exploit und der Payload werden zu Sicherheitsforschungs- und defensiven Erkennungszwecken veröffentlicht. Die Verwendung gegen Systeme, die Ihnen nicht gehören oder für die Sie keine ausdrückliche Testberechtigung haben, ist Ihr Problem, nicht das des Autors.

Tool herunterladen
CashoutVorab-Root-Setup nötigAnmerkungen
WSL2-SitzungsstartNeinWSLs sitzungsbezogener setuid(getpwnam(default_user)->pw_uid) führt keine Validierung durch. Funktioniert sauber.
util-linux suNeinNachsichtige Handhabung der Aufruferidentität.
shadow-utils suJagetpwuid(getuid())-Aufruferidentitätsprüfung schlägt fehl, weil die Mutation die echte UID unmappt.
sshd (Standard StrictModes yes)Ja (StrictModes deaktivieren)StrictModes erfordert, dass das Home-Verzeichnis root oder pw->pw_uid gehört. Mutation setzt pw_uid=0; Besitzer auf der Festplatte bleibt bei ursprünglicher UID; Konflikt verweigert Authentifizierung.
MTA-Lokalzustellung (postfix, exim usw.)VariabelAbhängig von den Home-Berechtigungsprüfungen des MDA. Pro MTA testen.