Leaking libc address with ROP
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)
Знайти переповнення зсув
Знайти гаджет POP_RDI
, гаджети PUTS_PLT
та MAIN
Використати попередні гаджети для витоку адреси пам'яті функції 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
Завантажте експлойт і помістіть його в ту ж директорію, що й вразливий бінар, і надайте необхідні дані скрипту:
Leaking libc - templateШаблон потребує зсуву перед продовженням з експлойтом. Якщо будь-який зсув надано, він виконає необхідний код для його знаходження (за замовчуванням OFFSET = ""
):
Виконайте python template.py
, відкриється консоль GDB з програмою, що зазнала збою. Всередині цієї консолі GDB виконайте x/wx $rsp
, щоб отримати байти, які збиралися перезаписати RIP. Нарешті, отримайте зсув за допомогою консолі python:
Після знаходження зсуву (в цьому випадку 40) змініть змінну OFFSET всередині шаблону, використовуючи це значення.
OFFSET = "A" * 40
Інший спосіб - використовувати: pattern create 1000
-- виконати до ret -- pattern seach $rsp
з GEF.
Тепер нам потрібно знайти ROP гаджети всередині бінарного файлу. Ці ROP гаджети будуть корисні для виклику puts
, щоб знайти libc, що використовується, а пізніше для запуску фінального експлойту.
PUTS_PLT
потрібен для виклику функції puts.
MAIN_PLT
потрібен для повторного виклику головної функції після одного взаємодії, щоб використати переповнення знову (безкінечні раунди експлуатації). Він використовується в кінці кожного ROP для повторного виклику програми.
POP_RDI потрібен для передачі параметра до викликаної функції.
На цьому етапі вам не потрібно нічого виконувати, оскільки все буде знайдено за допомогою pwntools під час виконання.
Тепер час дізнатися, яка версія бібліотеки 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
).
Але в випадку віддаленої експлуатації я поясню, як ви можете це знайти:
Ви можете шукати, яка бібліотека використовується на веб-сторінці: https://libc.blukat.me/ Це також дозволить вам завантажити виявлену версію libc
Ви також можете зробити:
$ 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
до нашого робочого каталогу.
На цьому етапі ми повинні знати, яка бібліотека libc використовується. Оскільки ми експлуатуємо локальний бінарний файл, я використаю просто: /lib/x86_64-linux-gnu/libc.so.6
Отже, на початку template.py
змініть змінну libc на: libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Встановіть шлях до бібліотеки, коли знаєте його
Надавши шлях до бібліотеки 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" буде передана як параметр.
Нарешті, адреса функції exit викликається, щоб процес коректно завершився і не було згенеровано жодних сповіщень.
Таким чином, експлойт виконає _/bin/sh_** оболонку.**
Ви також можете використовувати ONE_GADGET , щоб отримати оболонку замість використання system і "/bin/sh". ONE_GADGET знайде в бібліотеці libc спосіб отримати оболонку, використовуючи лише одну ROP адресу.
Однак, зазвичай є деякі обмеження, найпоширеніші та легкі для уникнення - це такі, як [rsp+0x30] == NULL
. Оскільки ви контролюєте значення всередині RSP, вам просто потрібно надіслати ще кілька значень NULL, щоб уникнути обмеження.
Ви можете знайти шаблон для експлуатації цієї вразливості тут:
Leaking libc - templateЯкщо символ "main" не існує. Тоді ви можете знайти, де знаходиться основний код:
і встановіть адресу вручну:
Якщо бінар не використовує Puts, вам слід перевірити, чи використовує він
sh: 1: %s%s%s%s%s%s%s%s: не знайдено
Якщо ви знайдете цю помилку після створення всіх експлойтів: sh: 1: %s%s%s%s%s%s%s%s: не знайдено
Спробуйте відняти 64 байти від адреси "/bin/sh":
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)