ROP - Leaking LIBC address
Швидкий огляд
Знайдіть зміщення переповнення
Знайдіть гаджети
POP_RDI
,PUTS_PLT
таMAIN_PLT
Використовуйте попередні гаджети для витоку адреси пам'яті puts або іншої функції libc та знайдіть версію libc (завантажте її)
З бібліотекою обчисліть ROP та використовуйте його
Інші посібники та бінарні файли для практики
У цьому посібнику буде використано код/бінарний файл, запропонований у цьому посібнику: https://tasteofsecurity.com/security/ret2libc-unknown-libc/ Інші корисні посібники: https://made0x78.com/bseries-ret2libc/, https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html
Код
Ім'я файлу: vuln.c
ROP - Витік шаблону LIBC
Я збираюся використати код, розташований тут, щоб створити експлойт. Завантажте експлойт та помістіть його в ту саму теку, що і вразливий бінарний файл, і надайте необхідні дані скрипту:
pageROP - Leaking LIBC template1- Пошук зсуву
Шаблон потребує зсуву перед продовженням експлойту. Якщо ніякий не наданий, він виконає необхідний код для його знаходження (за замовчуванням OFFSET = ""
):
Виконайте python template.py
, відкриється консоль GDB зі збоєм програми. У цій консолі GDB виконайте x/wx $rsp
, щоб отримати байти, які будуть перезаписувати RIP. Нарешті, отримайте зсув за допомогою консолі Python:
Після знаходження зсуву (у цьому випадку 40) змініть змінну OFFSET всередині шаблону, використовуючи це значення.
OFFSET = "A" * 40
Інший спосіб - використовувати: pattern create 1000
-- виконати до ret -- pattern seach $rsp
з GEF.
2- Пошук гаджетів
Тепер нам потрібно знайти гаджети ROP всередині бінарного файлу. Ці гаджети ROP будуть корисні для виклику puts
для пошуку використовуваної libc, а пізніше для запуску кінцевої атаки.
PUTS_PLT
потрібно для виклику функції puts.
MAIN_PLT
потрібно для виклику головної функції знову після одного взаємодії для експлуатації переповнення знову (безкінечні раунди експлуатації). Використовується в кінці кожного ROP для виклику програми знову.
POP_RDI потрібно для передачі параметра у викликану функцію.
На цьому етапі вам не потрібно виконувати нічого, оскільки все буде знайдено за допомогою pwntools під час виконання.
3- Пошук бібліотеки LIBC
Тепер час знайти, яка версія бібліотеки libc використовується. Для цього ми збираємося витікати адресу в пам'яті функції puts
, а потім ми збираємося шукати, в якій версії бібліотеки знаходиться версія puts за цією адресою.
Для цього найважливішим рядком виконаного коду є:
Це відправить деякі байти, поки перезаписання RIP не стане можливим: OFFSET
.
Потім воно встановить адресу гаджета POP_RDI
, щоб наступна адреса (FUNC_GOT
) була збережена в реєстрі RDI. Це тому, що ми хочемо викликати puts, передаючи йому адресу PUTS_GOT
як адресу в пам'яті функції puts, яка зберігається за адресою, на яку вказує PUTS_GOT
.
Після цього буде викликано PUTS_PLT
(з PUTS_GOT
всередині RDI), тому puts буде читати вміст всередині PUTS_GOT
(адреса функції puts в пам'яті) і виведе її.
Нарешті, знову викликається головна функція, щоб ми могли знову використовувати переповнення.
Таким чином, ми обманули функцію puts, щоб вона вивела адресу в пам'яті функції puts (яка знаходиться в бібліотеці libc). Тепер, коли у нас є ця адреса, ми можемо з'ясувати, яка версія libc використовується.
Оскільки ми експлуатуємо деякий локальний бінарний файл, не потрібно визначати, яка версія libc використовується (просто знайдіть бібліотеку в /lib/x86_64-linux-gnu/libc.so.6
).
Але в разі віддаленого використання уразливості я поясню, як ви можете це зробити:
3.1- Пошук версії libc (1)
Ви можете знайти, яка бібліотека використовується на веб-сторінці: https://libc.blukat.me/ Це також дозволить вам завантажити виявлену версію libc
3.2- Пошук версії libc (2)
Ви також можете зробити:
$ git clone https://github.com/niklasb/libc-database.git
$ cd libc-database
$ ./get
Це займе деякий час, будьте терплячі. Для того, щоб це працювало, нам потрібно:
Ім'я символу libc:
puts
Витік адреси libc:
0x7ff629878690
Ми можемо визначити, яка libc найімовірніше використовується.
Ми отримуємо 2 відповіді (ви повинні спробувати другу, якщо перша не працює). Завантажте перший:
Скопіюйте libc з libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so
в наш робочий каталог.
3.3- Інші функції для витоку
4- Знаходження адреси на основі бібліотеки libc та експлуатація
На цьому етапі ми повинні знати, яку бібліотеку libc використовується. Оскільки ми експлуатуємо локальний бінарний файл, я використовуватиму лише: /lib/x86_64-linux-gnu/libc.so.6
Таким чином, на початку template.py
змініть змінну libc на: libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it
Надавши шлях до бібліотеки libc, решта експлойту буде автоматично розрахована.
У функції get_addr
буде розрахована базова адреса libc:
Зверніть увагу, що кінцева базова адреса libc повинна закінчуватися на 00. Якщо це не ваш випадок, ви, можливо, витікали неправильну бібліотеку.
Потім адреса функції system
та адреса рядка "/bin/sh" будуть обчислені від базової адреси libc та задані бібліотекою libc.
Нарешті, експлойт виконання /bin/sh буде підготовлений для відправки:
Давайте поясним цей останній ROP.
Останній ROP (rop1
) завершився викликом функції main знову, тоді ми можемо знову використати переповнення (ось чому тут знову є OFFSET
). Потім ми хочемо викликати POP_RDI
, спрямовуючи на адресу "/bin/sh" (BINSH
) і викликати функцію system (SYSTEM
), оскільки адреса "/bin/sh" буде передана як параметр.
Нарешті, викликається адреса функції виходу, щоб процес коректно завершився і не було створено жодного сповіщення.
Таким чином, експлойт виконає оболонку _/bin/sh_.
4(2)- Використання ONE_GADGET
Ви також можете використовувати ONE_GADGET , щоб отримати оболонку замість використання system та "/bin/sh". ONE_GADGET знайде всередині бібліотеки libc якийсь спосіб отримати оболонку, використовуючи лише одну адресу ROP.
Однак, зазвичай є деякі обмеження, найпоширеніші та легкі для уникнення, такі як [rsp+0x30] == NULL
. Оскільки ви контролюєте значення в RSP, вам просто потрібно відправити ще деякі значення NULL, щоб уникнути обмеження.
ВИКОРИСТАННЯ ФАЙЛУ
Ви можете знайти шаблон для використання цієї вразливості тут:
pageROP - Leaking LIBC templateЗАГАЛЬНІ ПРОБЛЕМИ
MAIN_PLT = elf.symbols['main'] не знайдено
Якщо символ "main" не існує. Тоді ви можете просто де знаходиться основний код:
і встановити адресу вручну:
Puts не знайдено
Якщо бінарний файл не використовує Puts, вам слід перевірити, чи він використовує
sh: 1: %s%s%s%s%s%s%s%s: not found
sh: 1: %s%s%s%s%s%s%s%s: not found
Якщо ви знайдете цю помилку після створення всіх експлойтів: sh: 1: %s%s%s%s%s%s%s%s: not found
Спробуйте відняти 64 байти від адреси "/bin/sh":
Last updated