
Молниеносно быстрый™ многопоточный поисковик ROP-гаджетов. Альтернатива ropper / ropgadget (пока только x86).
ropr — это невероятно быстрый многопоточный поисковик ROP-гаджетов
ROP (Return Oriented Programming) гаджеты — это небольшие фрагменты из нескольких инструкций ассемблера, обычно заканчивающиеся инструкцией ret, которые уже существуют как исполняемый код в каждом бинарном файле или библиотеке. Эти гаджеты могут использоваться для эксплуатации бинарных уязвимостей и для обхода уязвимых исполняемых файлов.
Когда адреса множества ROP-гаджетов записываются в буфер, мы формируем ROP-цепочку. Если атакующий может переместить указатель стека на эту ROP-цепочку, то управление может быть полностью передано атакующему.
Большинство исполняемых файлов содержат достаточно гаджетов для создания полной по Тьюрингу ROP-цепочки. Для тех, у кого их нет, всегда можно использовать динамические библиотеки, находящиеся в том же адресном пространстве, такие как libc, если известны их адреса.
Прелесть использования ROP-гаджетов в том, что не нужно создавать новый исполняемый код — атакующий может достичь своей цели, используя только уже существующий в программе код.
Обычно первым требованием для использования ROP-гаджетов является наличие места для записи вашей ROP-цепочки — это может быть любой доступный для чтения буфер. Просто запишите адреса каждого гаджета, который вы хотите использовать, в этот буфер. Если буфер слишком мал, может не хватить места для записи длинной ROP-цепочки, поэтому атакующий должен быть осторожен при создании своей ROP-цепочки, чтобы она была достаточно эффективной и уместилась в доступном пространстве.
Следующее требование — возможность управлять стеком. Это может быть реализовано через переполнение стека, которое позволяет записать ROP-цепочку непосредственно под указателем стека, или через «stack pivot» (поворот стека) — обычно это один гаджет, который перемещает указатель стека на остальную часть ROP-цепочки.
Как только указатель стека окажется в начале вашей ROP-цепочки, следующая инструкция ret запустит выполнение гаджетов по порядку — каждый использует следующий как свой обратный адрес в своём стековом кадре.
Также можно добавлять в ROP-цепочку указатели на функции — при этом необходимо следить, чтобы аргументы функции были предоставлены после следующего элемента ROP-цепочки. Обычно это комбинируется с «pop-гаджетом», который извлекает аргументы из стека, чтобы плавно перейти к следующему гаджету после аргументов функции.
Быстрая установка:
cargo install ropr
приложение установится в ~/.cargo/bin
Из исходников:
git clone https://github.com/Ben-Lichtman/ropr
cd ropr
cargo build --release
полученный бинарный файл будет находиться в target/release/ropr
Альтернативно:
git clone https://github.com/Ben-Lichtman/ropr
cd ropr
cargo install --path .
приложение установится в ~/.cargo/bin
USAGE:
ropr [OPTIONS] <BINARY>
ARGS:
<BINARY> The path of the file to inspect
OPTIONS:
-b, --base-pivot Фильтрует гаджеты, которые изменяют базовый указатель
-c, --colour <COLOUR> Принудительно задаёт вывод с цветом или обычным текстом (`true` или `false`)
-h, --help Вывести справку
-j, --nojop Удаляет «JOP-гаджеты» — они могут иметь управляемую ветвь, вызов и т.д. вместо простого `ret` в конце
-m, --max-instr <MAX_INSTR> Максимальное количество инструкций в гаджете [по умолчанию: 6]
-n, --noisy Включает потенциально низкокачественные гаджеты, такие как префиксы, условные ветвления и ближние переходы (найдёт значительно больше гаджетов)
-p, --stack-pivot Фильтрует гаджеты, которые изменяют указатель стека
-r, --norop Удаляет обычные «ROP-гаджеты»
-R, --regex <REGEX> Выполняет поиск по регулярному выражению среди найденных гаджетов для удобной фильтрации
--range <RANGE> Поиск в диапазоне адресов (в шестнадцатеричном формате), например `0x1234-0x4567`
--raw <RAW> Обрабатывает входной файл как блок кода (`true` или `false`)
-s, --nosys Удаляет системные вызовы и другие прерывания
-V, --version Вывести информацию о версии
Например, если я искал способ заполнить rax значением из другого регистра, я мог бы отфильтровать по регулярному выражению ^mov eax, ...;:
❯ ropr /usr/lib/libc.so.6 -R "^mov eax, ...;" > /dev/null
==> Найдено 197 гаджетов за 0.118 секунды
Теперь я могу добавить некоторые фильтры в командную строку для получения наилучших результатов:
❯ ropr /usr/lib/libc.so.6 -m 2 -j -s -R "^mov eax, ...;"
0x000353e7: mov eax, eax; ret;
0x000788c8: mov eax, ecx; ret;
0x00052252: mov eax, edi; ret;
0x0003ae43: mov eax, edx; ret;
0x000353e6: mov eax, r8d; ret;
0x000788c7: mov eax, r9d; ret;
==> Найдено 6 гаджетов за 0.046 секунды
Теперь у меня есть хороший кандидат mov-гаджет по адресу 0x00052252