
تنفيذ PoC على مستوى المستخدم ليُستخدم كأسلوب ناقل هجوم
يستبدل تنفيذ فضاء المستخدم صورة العملية الحالية داخل مساحة العناوين الحالية بأخرى جديدة. يحاكي سلوك استدعاء النظام execve، لكن البنى الخاصة بالعملية التي تصف صورة العملية تبقى دون تغيير. بعبارة أخرى، سيبقى اسم العملية كما تبلغه أدوات النظام بالاسم القديم.
يمكن استخدام هذه التقنية لتحقيق التخفي بعد الحصول على تنفيذ عشوائي للكود. ويمكن استخدامها أيضًا لتنفيذ الملفات الثنائية المخزنة في أقسام noexec.
أول تنفيذ في فضاء المستخدم صُنع بواسطة grugq. هذا المستودع مستوحى بشكل كبير من مكتبة Rapid7 Mettle، التي تتضمن وصفًا شاملًا في مدونة لهذه التقنية.
في البداية، كان جزء كبير من كود هذا المستودع يحاكي مكتبة Mettle، لكنه مُنذ ذلك الحين تم توسيعه ليشمل تعقيدات إضافية لتجاوز تحقق SELinux.
يتضمن SELinux تحقق execmem، الذي يضمن:
PROT_WRITE إلى PROT_EXEC باستخدام mprotect غير مسموح به).mprotectلتجاوز mprotect، من الضروري إنشاء ملف مؤقت. يمكن تحقيق ذلك باستخدام memfd_create مع munmap وmmap، وبذلك يتم تجنب استدعاء النظام mprotect بالكامل.
يوضح مثال elf_debugger.c أن أي ملف ELF يحتوي على منطقة PT_LOAD قابلة للتنفيذ والكتابة معًا. هذه المنطقة مطلوبة لتحميل معلومات البرنامج أثناء التنفيذ. ولمعالجة ذلك، أُنشئ تنفيذ bypass_wx.c. هذا التصميم:
SIGSEGV.PROT_EXEC إلى PROT_WRITE.| OS | Architect | Result |
|---|---|---|
| Ubuntu 24.04 | x86_64 | نجاح |
| Archlinux 6.12.4 | x86_64 | نجاح |
| CentOS | x86_64 | نجاح |
| Raspberry Pi OS | arm64 | نجاح |
| S23 Android 14 | arm64 | نجاح |
يصف هذا القسم كيفية البناء لأجهزة 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.