
Userland exec PoC to be used as attack vector technique
Userland exec, वर्तमान एड्रेस स्पेस के भीतर मौजूदा प्रोसेस इमेज को एक नई प्रोसेस इमेज से बदल देता है। यह execve सिस्टम कॉल के व्यवहार की नकल करता है, लेकिन प्रोसेस इमेज का वर्णन करने वाली प्रोसेस संरचनाएं अपरिवर्तित रहती हैं। दूसरे शब्दों में, सिस्टम उपयोगिताओं द्वारा रिपोर्ट किया गया प्रोसेस नाम पुराने प्रोसेस नाम को ही बनाए रखेगा।
इस तकनीक का उपयोग मनमाना कोड निष्पादन (arbitrary code execution) प्राप्त करने के बाद स्टील्थ (stealth) प्राप्त करने के लिए किया जा सकता है। इसका उपयोग noexec पार्टीशन में संग्रहीत बायनेरीज़ को निष्पादित करने के लिए भी किया जा सकता है।
पहला userland exec grugq द्वारा बनाया गया था। यह रिपॉज़िटरी Rapid7 Mettle library से अत्यधिक प्रेरित है, जिसमें इस तकनीक का एक व्यापक ब्लॉग विवरण शामिल है।
प्रारंभ में, इस रिपॉज़िटरी के अधिकांश कोड ने Mettle लाइब्रेरी की नकल की थी, लेकिन तब से इसे SELinux सत्यापन को बायपास करने के लिए अतिरिक्त जटिलता शामिल करने हेतु विस्तारित किया गया है।
SELinux में execmem सत्यापन शामिल है, जो निम्नलिखित सुनिश्चित करता है:
mprotect का उपयोग करके PROT_WRITE को PROT_EXEC में बदलना अस्वीकृत है)।mprotect को बायपास करनाmprotect को बायपास करने के लिए, एक अस्थायी फ़ाइल बनाना आवश्यक है। इसे munmap और mmap के साथ संयुक्त memfd_create का उपयोग करके प्राप्त किया जा सकता है, जिससे mprotect सिस्टम कॉल को पूरी तरह से टाला जा सकता है।
elf_debugger.c उदाहरण प्रदर्शित करता है कि किसी भी ELF में एक PT_LOAD क्षेत्र होता है जो निष्पादन योग्य और लिखने योग्य दोनों होता है। निष्पादन के दौरान प्रोग्राम जानकारी लोड करने के लिए यह क्षेत्र आवश्यक है। इस समस्या के समाधान के लिए, bypass_wx.c कार्यान्वयन बनाया गया था। यह डिज़ाइन:
SIGSEGV सिग्नल ट्रिगर करता है।PROT_EXEC से PROT_WRITE में गतिशील रूप से बदल देता है।यह अनुभाग वर्णन करता है कि Android और x86 मशीनों के लिए कैसे निर्माण किया जाए। आगे बढ़ने से पहले सुनिश्चित करें कि libelf स्थापित है।
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 $
CentOS पर, libc लाइब्रेरी असामान्य व्यवहार प्रदर्शित कर सकती है। इस समस्या के समाधान के लिए, असेंबली में लिखा गया एक सरल "Hello, World" प्रोग्राम, hello_nolibc.s, प्रदान किया गया है। यह उदाहरण cmake के साथ मिलकर प्रदर्शित करता है कि libc से लिंक किए बिना प्रोग्राम कैसे बनाया और निष्पादित किया जाए।
यदि आपका CMAKE 4.0 से ऊपर है तो आप बिल्ड में -DCMAKE_POLICY_VERSION_MINIMUM=3.5 जोड़ सकते हैं।
यह रिपॉज़िटरी GPL-3.0 लाइसेंस का उपयोग करती है।
| OS | आर्किटेक्चर | परिणाम |
|---|
| Ubuntu 24.04 | x86_64 | सफलता |
| Archlinux 6.12.4 | x86_64 | सफलता |
| CentOS | x86_64 | सफलता |
| Raspberry Pi OS | arm64 | सफलता |
| S23 Android 14 | arm64 | सफलता |