nataliadiak/windows-x86-shellcode-poc

GitHub: nataliadiak/windows-x86-shellcode-poc

旨在帮助初学者理解 Windows x86 环境下基于栈的缓冲区溢出漏洞利用及 Shellcode 注入原理的教学型 PoC。

Stars: 5 | Forks: 0

# 初学者的 Windows x86 缓冲区溢出 PoC 这是一个简单、独立的关于 32 位 Windows 基于栈的缓冲区溢出漏洞利用的教程。 无需外部指南——你需要的一切都在这里。 ## 这个仓库是什么? - `vulnerable.c`:一个包含不安全 `gets()` 函数的简单程序。 - `messageBox.asm`:一段会在溢出后执行的小型汇编 payload。 - `exploit.c`:演示如何触发溢出的示例。 本项目教授一个核心理念:不安全的输入读取可以让攻击者覆盖返回地址并重定向执行流。 ## 漏洞:`gets()` 没有大小限制 在 `vulnerable.c` 中,程序执行了以下操作: ``` char buffer[32]; gets(buffer); ``` 程序为 `buffer` 分配了 32 个字节,然后调用 `gets()` 读取输入。 问题在于:`gets()` 不检查缓冲区大小。 它会不断读取字符,直到遇到换行符。 如果用户输入了 40 或 50 个字符,多余的字符就会溢出这 32 字节的缓冲区。 ## 栈上的内存布局 当 C 函数运行时,栈(内存中的一块区域)会存储: 1. 局部变量(如 `buffer`) 2. 保存的 `EBP`(来自调用函数的基址指针) 3. 保存的返回地址(函数返回时 CPU 应该跳转到的位置) 如下所示: ``` Lower addresses (top of stack as drawn) [ buffer (32 bytes) ] [ saved EBP (4 bytes) ] [ return address (4 bytes) ] Higher addresses (bottom) ``` 当 `gets()` 因为输入过多而使 `buffer` 溢出时,多余的字节会覆盖保存的 `EBP`,然后覆盖返回地址。 如果我们精心构造溢出数据,在返回地址字段中填入一个特定的地址,当函数尝试返回时,CPU 就会跳转到该地址。 ## 漏洞利用原理:逐步解析 1. 程序启动并在栈上分配 `buffer[32]`。 2. 它调用 `gets(buffer)` 读取一行用户输入。 3. 我们发送一个长度超过 32 字节的字符串(比如 50 字节)。 4. `gets()` 没有大小检查,因此它将所有 50 个字节写入缓冲区。 5. 多余的 18 个字节溢出 `buffer` 并覆盖保存的 `EBP` 和返回地址。 6. 我们精心构造溢出数据,使返回地址指向栈上的 shellcode。 7. 当函数返回时,CPU 读取被覆盖的返回地址。 8. CPU 跳转到 shellcode。 9. shellcode 在该程序的权限下运行。 这是通过缓冲区溢出实现代码执行的最简单形式。 ## shellcode 中发生了什么:Payload `messageBox.asm` 是一段被设计为在溢出后运行的小段代码。 它执行以下操作: 1. **加载 USER32.DLL**:使用字符串 "USER32.DLL" 调用 `LoadLibraryA`,以确保该库已加载到内存中。 2. **为 MessageBoxA 准备参数**:将四个参数压入栈中(窗口句柄、消息文本、标题、按钮类型)。 3. **调用 MessageBoxA**:调用 Windows API 函数,显示一个包含文本 "CAN I HACK THE PC?" 的消息框。 4. **干净地退出**:调用 `ExitProcess` 以安全地终止程序。 关键点是:这是一段在溢出将执行流重定向到它之后运行的可执行代码。 当消息框出现在屏幕上时,它证明了三件事: 1. 缓冲区溢出成功并改写了返回地址。 2. 执行流跳转到了栈上的 shellcode。 3. shellcode 成功运行并调用了 Windows API。 在真实的攻击中,这个 payload 可以做任何事情:窃取数据、创建用户、下载恶意软件等。 消息框只是一种直观且安全的方式,用于演示发生了任意代码执行。 这个特定的 payload 为 `MessageBoxA` (0x751D8830) 和 `ExitProcess` (0x7437ADB0) 使用了硬编码的内存地址。 这些地址是特定于某个系统的。该 payload 需要针对不同的 Windows 版本或系统进行调整。 ![MessageBoxA](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/b0c4f91ed3135440.png) ## 如何构建和运行演示 ### 步骤 1:禁用保护机制 现代 Windows 拥有多个阻止此漏洞利用的安全特性: - **Stack Canaries** (GS flag):检测栈覆盖。 - **ASLR** (DYNAMICBASE):随机化内存地址,使硬编码的地址失效。 - **DEP/NX** (NXCOMPAT):将栈标记为不可执行,以防止在那里执行代码。 对于这个学习练习,我们禁用所有这些保护。 ### 步骤 2:在 Windows 上编译 使用带有特定标志的 MSVC (Microsoft Visual C++): ``` cl /c /GS- /W3 /Zl vulnerable.c link /SUBSYSTEM:CONSOLE /DYNAMICBASE:NO /NXCOMPAT:NO vulnerable.obj /OUT:vulnerable.exe ``` 标志含义: - `/GS-` 禁用栈缓冲区溢出保护。 - `/DYNAMICBASE:NO` 禁用地址空间布局随机化 (ASLR)。 - `/NXCOMPAT:NO` 禁用 DEP,允许在栈上执行代码。 如果你已经有了可执行文件,可以使用 `editbin` 禁用保护: ``` editbin /NXCOMPAT:NO /DYNAMICBASE:NO vulnerable.exe ``` ### 步骤 3:运行它 1. 启动 `vulnerable.exe`。 2. 出现提示时,输入一个长字符串(超过 32 个字符)。 3. 如果溢出成功,保存的返回地址将被覆盖。 4. 程序可能会崩溃、跳转到随机内存,或者(在具有适当 shellcode 的真实漏洞利用中)执行 payload。 ## 为什么这份 README 是完整的 本 README 解释了: 1. `gets()` 是什么以及为什么不安全(没有大小限制)。 2. 栈如何存储局部变量、保存的寄存器和返回地址。 3. 溢出如何覆盖返回地址。 4. 函数返回时 CPU 如何使用返回地址。 5. 当返回地址指向 shellcode 时,shellcode 是如何执行的。 6. 存在哪些保护机制以及我们为什么要禁用它们。 7. 如何构建和运行示例。 你现在了解了整个缓冲区溢出漏洞利用的流程。 阅读代码文件并将它们与本解释进行比较,以巩固你的理解。 ## 重要安全提示 此示例仅用于学习目的。 请勿对您不拥有或未获得明确测试许可的系统使用此技术。 未经授权访问计算机系统是违法行为。
标签:Golang, Go语言工具, PoC, Shellcode注入, Web报告查看器, Windows x86, 二进制漏洞, 内存安全, 安全教程, 安全编程, 客户端加密, 快速连接, 数据展示, 旧版系统漏洞, 暴力破解, 栈溢出, 汇编语言, 漏洞分析, 端点可见性, 红队, 缓冲区溢出, 网络安全, 自定义Shellcode, 路径探测, 隐私保护