ret2text
ret2text
一、原理
控制程序执行程序本身已有的代码(.text)。这种攻击是一种笼统的描述,被称为ROP攻击,即通过面向返回编程来攻击。ROP攻击利用了程序中已经存在的代码段(称为“gadget”),并通过操纵程序的返回地址来控制程序的执行流程。
GCC编译ret2text文本文件:
1 | gcc -fno-stack-protector -z noexecstack -no-pie -z norelro -m32 - ret2text.c -o ret2text //编译的文件禁用栈保护、开启NX保护、关闭RELRO并且是32位 |
二、程序分析
通过checksec检查程序
32位程序小端存储,除了NX栈不可执行开启,其它都是关闭状态。因为开启了栈不可执行,所以无法在栈中进行跳转,那么就考虑调用程序本身的函数,或者使用ROP技术获取gadget
使用ida静态分析程序,main函数中调用gets()函数来获取数据,因为此函数没有数据限制,所以存在栈溢出漏洞
v4作为参数,v4距离栈顶指针esp为1Ch,距离栈底指针ebp为64h,所以能就知道了能存的最大字符串数了
在main函数汇编中发现secure函数中调用了system(“/bin/sh”)的代码
溢出思路:由于gets函数对输入的字符长度没有限制,所以可以构成足够长的字符串填充栈空间,由于cannary也没有开启,所以可以继续覆盖savedebp地址和ret返回地址。如果将调用的system(‘\bin\sh’)的地址0X0804863A地址覆盖到ret返回地址处,那么程序结束的时候就会获取shell。
三、溢出
需要考虑起始地址距离main函数返回地址的距离
方法1:
ida中查看main函数汇编代码
在main接收字符串是通过esp进行索引的,用gdb查看索引时的esp和ebp位置。在call处下断点(0x080486AE),程序停在call处的初始位置,此时字符串进栈,此时寄存器中显示的就是字符串的esp和ebp
esp+1Ch就是字符串起始地址,再拿ebp-起始地址就是字符串的总长度,再加上4字节(覆盖savedebp)就是ret返回地址,所以想要改变返回地址就需要0x64+4个字节才能到达ret
方法2:
通过cyclic工具创建200个字符串(明确溢出的长度)
复制字符串到程序ret2text,通过gdb
字符串输入过长,产生报错,程序停在0x62616164,所以可以用工具查看停止处字符串长度
1 | cyclic -l 0x62616164 |
得到112,这个长度就是字符串在栈中起始地址到ret地址的字节数
四、EXP
通过偏移量和思路写出exp:
1 | from pwn import * #引用pwntools库 |