0x01 漏洞位置
程序很简单,调用 fgets() 从 stdin 中读取 1337 bytes 数据到 yolo 数组中,由于 yolo 内存空间为 1024 bytes,但输入数据长度大于 1024 时会导致栈溢出。
0x02. 漏洞利用
首先,检查程序开启的安全机制,发现没有开任何安全机制。
1. 第一次尝试
由于题目给了 libc 文件,所以可以尝试 ret2libc 进行利用。
但很不幸,服务器开启了 ASLR,libc 加载基址的随机化会使得 libc 中 system 函数地址和 “/bin/sh” 字符串地址发生变化,导致利用失败。
2. 第二次尝试
由于开启了 ASLR,利用过程就不能依赖堆栈以及内存中共享库的地址。程序汇编代码如下:
分析汇编代码后发现,通过两次输入可以把 shellcode 写入 .bss 段中,然后跳转到 .bss 段执行 shellcode,具体思路如下:
- 利用 fgets() 写内存溢出,把 rbp 寄存器修改到 .bss 段的 0x601440(0x601030 + 0x400 + 0x10) 地址处,其中,0x400 为 yolo 的内存大小,偏移0x10 是为了不破坏 .bss 中 stdin 的值 ;同时,把返回地址覆盖为 0x4005D5,以便进行第二次调用 fgets() 进行写内存。
- 利用第二次调用 fgets() 把 shellcode 写入 .bss 中,由于 rbp 被修改到 .bss 段的 0x601440,所以会把数据写入到 0x601040( [rbp - 0x400] );同时,把返回地址覆盖为 shellcode 地址 0x601040。
- 最终 ret 时跳转到 shellcode 执行。
利用脚本如下: