Память процессов (Proc Memory) - это техника внедрения в процесс, с помощью которой злоумышленники читают из памяти процесса или записывают в нее, что позволяет им внедрять и выполнять вредоносный код без создания нового процесса. Эта техника использует преимущества файловой системы /proc в Linux и Unix-системах, которая предоставляет интерфейс к информации, связанной с процессом, включая мапинг памяти и разрешения. Манипулируя памятью запущенного процесса, атакующие могут перехватить исполнение, изменить поведение приложения или извлечь конфиденциальные данные, такие как учетные данные и ключи шифрования.
Что такое память процессов?
В Unix-подобных операционных системах файловая система /proc - это виртуальная файловая система, предоставляющая доступ к информации о процессах, запущенных в системе. Внедрение памяти процесса включает в себя перечисление памяти процесса через файловую систему /proc и создание полезной нагрузки в виде программирования, ориентированного на возврат (ROP). ROP - это техника, которая предполагает использование небольших блоков кода, известных как «гаджеты», для выполнения произвольного кода в контексте другого процесса.
Как уже упоминалось, файловая система /proc реализована как виртуальная файловая система, то есть она не существует на физическом устройстве хранения. Вместо этого она представляет собой представление процессов системы и их состояния, а содержащаяся в ней информация генерируется ядром по запросу.
Одна из вещей, к которым файловая система /proc предоставляет доступ, - это память процессов, запущенных в системе. Например, файл /proc/[pid]/mem можно использовать для доступа к памяти процесса с указанным pid (идентификатором процесса). Каталог /proc/[pid] содержит несколько файлов, предоставляющих информацию о процессе, такую как мапинг памяти, дескрипторы открытых файлов и так далее. Это может быть полезно для таких задач, как отладка или обратная разработка, а также для обнаружения и устранения уязвимостей в памяти процесса.
Использование злоумышленниками Память процессов (Proc Memory)
Чтобы выполнить инъекцию памяти proc, атакующий сначала перечисляет память процесса, получая доступ к каталогу /proc/[pid] целевого процесса. Получив доступ к /proc/[pid], атакующий может изучить мапинг памяти процесса, чтобы найти гаджеты - небольшие блоки кода, которые могут быть использованы для выполнения произвольного кода в контексте процесса. Гаджеты обычно находятся в сегментах кода процесса, таких как текстовый сегмент, который содержит инструкции, составляющие программу.
Вот пример гаджета, который может быть использован для выполнения произвольного кода в контексте процесса:
1 2 3 4 | # поместите адрес выполняемого кода в регистр rdi pop rdi # возврат по адресу в регистре rdi ret |
Этот гаджет состоит из двух инструкций: инструкции «pop», которая выталкивает адрес с вершины стека и сохраняет его в регистре rdi, и инструкции «ret», которая возвращает адрес, сохраненный в регистре rdi.
Чтобы использовать этот гаджет, атакующий может перенаправить поток выполнения процесса на гаджет, а затем поместить адрес собственного кода в стек. Затем инструкция pop уберет этот адрес из стека и сохранит его в регистре rdi, а инструкция ret вернется по адресу, сохраненному в регистре rdi, что приведет к выполнению кода атакующего.
Гаджеты полезны для атакующих, поскольку позволяют им выполнять код без необходимости внедрять свой собственный код в память процесса. Вместо этого они могут использовать гаджеты, которые уже присутствуют в сегментах кода процесса, для выполнения собственного кода. Для поиска гаджетов атакующие могут использовать инструменты (такие как ROPgadget, Ropper и ROPChain), которые ищут в памяти процесса определенные инструкции или последовательности инструкций.
Например, злоумышленники могут использовать инструмент ROPgadget в следующем жизненном цикле атаки:
- Первым шагом для атакующего будет поиск целевого процесса, в который он хочет внедрить код.
- Затем атакующий использует ROPgadget для поиска гаджетов в двоичном коде целевого процесса, ища гаджеты, которые могут быть использованы для изменения потока выполнения, например, гаджеты, которые могут быть использованы для перехода к определенному адресу памяти или гаджеты, которые могут быть использованы для вызова определенной функции.
- После того как атакующий определит достаточное количество гаджетов, он может сконструировать полезную нагрузку ROP, соединив гаджеты в определенном порядке.
- Затем полезная нагрузка может быть внедрена в память процесса с помощью таких техник, как Ptrace System Calls или эксплуатация уязвимости в процессе.
- После выполнения полезной нагрузки атакующий может выполнить произвольный код в контексте процесса.