DDexec / EverythingExec
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
В Linux, щоб запустити програму, вона повинна існувати як файл, вона повинна бути доступною якимось чином через ієрархію файлової системи (так працює execve()
). Цей файл може знаходитися на диску або в оперативній пам'яті (tmpfs, memfd), але вам потрібен шлях до файлу. Це дуже спростило контроль за тим, що запускається на системі Linux, полегшило виявлення загроз і інструментів зловмисників або запобігання їх спробам виконати щось своє (e. g. не дозволяючи неправа користувачам розміщувати виконувані файли будь-де).
Але ця техніка змінює все це. Якщо ви не можете запустити процес, який хочете... тоді ви захоплюєте вже існуючий.
Ця техніка дозволяє вам обійти загальні захисні техніки, такі як тільки для читання, noexec, білий список імен файлів, білий список хешів...
Остаточний скрипт залежить від наступних інструментів для роботи, вони повинні бути доступні в системі, яку ви атакуєте (за замовчуванням ви знайдете їх усі скрізь):
Якщо ви можете довільно змінювати пам'ять процесу, то ви можете його захопити. Це можна використовувати для захоплення вже існуючого процесу та заміни його на іншу програму. Ми можемо досягти цього або за допомогою системного виклику ptrace()
(який вимагає, щоб ви мали можливість виконувати системні виклики або щоб gdb був доступний на системі), або, що більш цікаво, записуючи в /proc/$pid/mem
.
Файл /proc/$pid/mem
є одноосібним відображенням всього адресного простору процесу (e. g. від 0x0000000000000000
до 0x7ffffffffffff000
в x86-64). Це означає, що читання з цього файлу або запис у нього за зміщенням x
є тим самим, що читання з або модифікація вмісту за віртуальною адресою x
.
Тепер нам потрібно вирішити чотири основні проблеми:
Загалом, лише root і власник програми файлу можуть його змінювати.
ASLR.
Якщо ми спробуємо прочитати або записати за адресою, яка не відображена в адресному просторі програми, ми отримаємо помилку введення/виведення.
Ці проблеми мають рішення, які, хоча й не є ідеальними, є хорошими:
Більшість оболонок дозволяють створення дескрипторів файлів, які потім успадковуються дочірніми процесами. Ми можемо створити fd, що вказує на файл mem
оболонки з правами запису... тому дочірні процеси, які використовують цей fd, зможуть змінювати пам'ять оболонки.
ASLR навіть не є проблемою, ми можемо перевірити файл maps
оболонки або будь-який інший з procfs, щоб отримати інформацію про адресний простір процесу.
Отже, нам потрібно lseek()
по файлу. З оболонки це не можна зробити, якщо не використовувати infamous dd
.
Кроки відносно прості і не вимагають жодного роду експертизи для їх розуміння:
Проаналізуйте двійковий файл, який ми хочемо запустити, і завантажувач, щоб дізнатися, які відображення їм потрібні. Потім створіть "shell" код, який, загалом, виконає ті ж кроки, що й ядро при кожному виклику execve()
:
Створіть зазначені відображення.
Прочитайте двійникові файли в них.
Налаштуйте права.
Нарешті, ініціалізуйте стек з аргументами для програми та розмістіть допоміжний вектор (необхідний завантажувачу).
Перейдіть до завантажувача і дайте йому зробити решту (завантажити бібліотеки, необхідні для програми).
Отримайте з файлу syscall
адресу, до якої процес повернеться після виконання системного виклику.
Перезапишіть це місце, яке буде виконуваним, нашим shellcode (через mem
ми можемо змінювати невиконувані сторінки).
Передайте програму, яку ми хочемо запустити, до stdin процесу (буде read()
цим "shell" кодом).
На цьому етапі завантажувачу залишається завантажити необхідні бібліотеки для нашої програми та перейти до неї.
Перевірте інструмент на https://github.com/arget13/DDexec
Існує кілька альтернатив dd
, одна з яких, tail
, наразі є програмою за замовчуванням, що використовується для lseek()
через файл mem
(що було єдиною метою використання dd
). Ці альтернативи:
Встановлюючи змінну SEEKER
, ви можете змінити використовуваний seeker, e. g.:
Якщо ви знайдете ще одного дійсного seeker, який не реалізований у скрипті, ви все ще можете його використовувати, встановивши змінну SEEKER_ARGS
:
Заблокуйте це, EDRs.
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)