
Userland-Exec-PoC als Angriffsvektor-Technik
Userland exec ersetzt das bestehende Prozess-Image im aktuellen Adressraum durch ein neues. Es ahmt das Verhalten des Systemaufrufs execve nach, aber die Prozessstrukturen, die das Prozess-Image beschreiben, bleiben unverändert. Mit anderen Worten: Der Prozessname, der von Systemprogrammen gemeldet wird, behält den alten Prozessnamen.
Diese Technik kann verwendet werden, um nach der Erlangung beliebiger Codeausführung Tarnung zu erreichen. Sie kann auch verwendet werden, um Binärdateien auszuführen, die auf noexec-Partitionen gespeichert sind.
Der erste Userland-Exec wurde von grugq erstellt. Dieses Repository ist stark von der Rapid7 Mettle-Bibliothek inspiriert, die eine umfassende Blog-Beschreibung der Technik enthält.
Anfangs ahmte ein großer Teil des Codes dieses Repositories die Mettle-Bibliothek nach, wurde aber seitdem erweitert, um zusätzliche Komplexität zur Umgehung der SELinux-Überprüfung zu enthalten.
SELinux umfasst die execmem-Überprüfung, die Folgendes sicherstellt:
PROT_WRITE zu PROT_EXEC mittels ist nicht erlaubt).mprotectmprotectZur Umgehung von mprotect ist es notwendig, eine temporäre Datei zu erstellen. Dies kann durch die Kombination von memfd_create mit munmap und mmap erreicht werden, wodurch der Systemaufruf mprotect vollständig vermieden wird.
Das Beispiel elf_debugger.c zeigt, dass jede ELF-Datei eine PT_LOAD-Region enthält, die sowohl ausführbar als auch beschreibbar ist. Diese Region ist erforderlich, um die Programminformationen während der Ausführung zu laden. Um dies zu adressieren, wurde die Implementierung bypass_wx.c erstellt. Dieses Design:
SIGSEGV-Signal aus.PROT_EXEC zu PROT_WRITE.| OS | Architektur | Ergebnis |
|---|---|---|
| Ubuntu 24.04 | x86_64 | Erfolg |
| Archlinux 6.12.4 | x86_64 | Erfolg |
| CentOS | x86_64 | Erfolg |
| Raspberry Pi OS | arm64 | Erfolg |
| S23 Android 14 | arm64 | Erfolg |
Dieser Abschnitt beschreibt, wie für Android- und x86-Maschinen gebaut wird. Stellen Sie sicher, dass libelf installiert ist, bevor Sie fortfahren.
mkdir build && cd build
cmake ..
make
desktop % strace ./uexec hello others args here 2>&1 | grep exec
execve("./uexec", ["./uexec", "hello", "others", "args", "here"], 0x7ffc34ec02f0 /* 54 vars */) = 0
desktop % strace bash -c ./hello 2>&1 | grep exec
execve("/usr/bin/bash", ["bash", "-c", "./hello"], 0x7ffebecc3130 /* 54 vars */) = 0
newfstatat(AT_FDCWD, "/desktop/userland-exec/build", {st_mode=S_IFDIR|0755, st_size=4096, ...}, 0) = 0
newfstatat(AT_FDCWD, "/desktop/userland-exec", {st_mode=S_IFDIR|0755, st_size=4096, ...}, 0) = 0
execve("./hello", ["./hello"], 0x5fb22658e2a0 /* 54 vars */) = 0
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Debug ..
make
mkdir build && cd build
cmake -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-30 ..
make
desktop % adb push uexec hello /data/local/tmp
uexec: 1 file pushed, 0 skipped. 113.9 MB/s (22912 bytes in 0.000s)
hello: 1 file pushed, 0 skipped. 184.9 MB/s (6936 bytes in 0.000s)
2 files pushed, 0 skipped. 0.3 MB/s (29848 bytes in 0.090s)
desktop % adb shell
dm3q:/ $ cd /data/local/tmp
dm3q:/data/local/tmp $ chmod +x uexec
dm3q:/data/local/tmp $ ./hello
Hello World
dm3q:/data/local/tmp $ ./uexec hello
Hello World
dm3q:/data/local/tmp $
Auf CentOS kann die libc-Bibliothek ein ungewöhnliches Verhalten aufweisen. Um dieses Problem zu beheben, wurde ein einfaches „Hallo, Welt“-Programm in Assemblersprache bereitgestellt: hello_nolibc.s. Dieses Beispiel zusammen mit dem cmake zeigt, wie ein Programm ohne Verknüpfung mit libc gebaut und ausgeführt wird.
Wenn Ihr CMAKE über 4.0 liegt, können Sie im Build -DCMAKE_POLICY_VERSION_MINIMUM=3.5 anhängen.
Dieses Repository verwendet die GPL-3.0-Lizenz.