DDexec / EverythingExec
Reading time: 4 minutes
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Контекст
У Linux, щоб запустити програму, вона повинна існувати як файл, вона повинна бути доступною якимось чином через ієрархію файлової системи (так працює execve()
). Цей файл може знаходитися на диску або в оперативній пам'яті (tmpfs, memfd), але вам потрібен шлях до файлу. Це дуже спростило контроль за тим, що запускається на системі Linux, полегшило виявлення загроз і інструментів зловмисників або запобігання їх спробам виконати щось своє (e. g. не дозволяючи неправа користувачам розміщувати виконувані файли будь-де).
Але ця техніка змінює все це. Якщо ви не можете запустити процес, який хочете... тоді ви захоплюєте вже існуючий.
Ця техніка дозволяє вам обійти загальні захисні техніки, такі як тільки для читання, noexec, білий список імен файлів, білий список хешів...
Залежності
Остаточний скрипт залежить від наступних інструментів, які повинні бути доступні в системі, яку ви атакуєте (за замовчуванням ви знайдете їх усі скрізь):
dd
bash | zsh | ash (busybox)
head
tail
cut
grep
od
readlink
wc
tr
base64
Техніка
Якщо ви можете довільно змінювати пам'ять процесу, то ви можете його захопити. Це можна використовувати для захоплення вже існуючого процесу та заміни його на іншу програму. Ми можемо досягти цього або за допомогою системного виклику ptrace()
(який вимагає, щоб ви мали можливість виконувати системні виклики або щоб gdb був доступний на системі), або, що більш цікаво, записуючи в /proc/$pid/mem
.
Файл /proc/$pid/mem
є одноосібним відображенням всього адресного простору процесу (e. g. від 0x0000000000000000
до 0x7ffffffffffff000
в x86-64). Це означає, що читання з цього файлу або запис у нього за зміщенням x
є тим самим, що читання з або модифікація вмісту за віртуальною адресою x
.
Тепер у нас є чотири основні проблеми, з якими потрібно зіткнутися:
- Загалом, тільки root і власник програми файлу можуть його змінювати.
- ASLR.
- Якщо ми спробуємо прочитати або записати за адресою, яка не відображена в адресному просторі програми, ми отримаємо помилку I/O.
Ці проблеми мають рішення, які, хоча й не ідеальні, є хорошими:
- Більшість оболонкових інтерпретаторів дозволяють створення дескрипторів файлів, які потім будуть успадковані дочірніми процесами. Ми можемо створити fd, що вказує на файл
mem
оболонки з правами на запис... тому дочірні процеси, які використовують цей fd, зможуть змінювати пам'ять оболонки. - ASLR навіть не є проблемою, ми можемо перевірити файл
maps
оболонки або будь-який інший з procfs, щоб отримати інформацію про адресний простір процесу. - Тому нам потрібно
lseek()
через файл. З оболонки це не можна зробити, якщо не використовувати infamousdd
.
Детальніше
Кроки відносно прості і не вимагають жодного роду експертизи для їх розуміння:
- Проаналізуйте двійковий файл, який ми хочемо запустити, і завантажувач, щоб дізнатися, які відображення їм потрібні. Потім створіть "shell" код, який, загалом, виконає ті ж кроки, що й ядро при кожному виклику
execve()
: - Створіть зазначені відображення.
- Прочитайте двійникові файли в них.
- Налаштуйте права.
- Нарешті, ініціалізуйте стек з аргументами для програми та розмістіть допоміжний вектор (необхідний завантажувачу).
- Стрибніть у завантажувач і дайте йому зробити решту (завантажити бібліотеки, необхідні для програми).
- Отримайте з файлу
syscall
адресу, до якої процес повернеться після виконання системного виклику. - Перезапишіть це місце, яке буде виконуваним, нашим shellcode (через
mem
ми можемо змінювати не записувані сторінки). - Передайте програму, яку ми хочемо запустити, в stdin процесу (буде
read()
цим "shell" кодом). - На цьому етапі завантажувачу залишається завантажити необхідні бібліотеки для нашої програми та стрибнути в неї.
Перевірте інструмент на https://github.com/arget13/DDexec
EverythingExec
Існує кілька альтернатив dd
, одна з яких, tail
, наразі є програмою за замовчуванням, що використовується для lseek()
через файл mem
(що було єдиною метою використання dd
). Ці альтернативи:
tail
hexdump
cmp
xxd
Встановлюючи змінну SEEKER
, ви можете змінити використовуваний seeker, e. g.:
SEEKER=cmp bash ddexec.sh ls -l <<< $(base64 -w0 /bin/ls)
Якщо ви знайдете ще одного дійсного seeker, який не реалізовано в скрипті, ви все ще можете його використовувати, встановивши змінну SEEKER_ARGS
:
SEEKER=xxd SEEKER_ARGS='-s $offset' zsh ddexec.sh ls -l <<< $(base64 -w0 /bin/ls)
Заблокуйте це, EDRs.
Посилання
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.