stackoverflow之ret2text
Preface
随着NX保护机制的开启,直接往栈或堆上注入代码的方式不再能达成效果。
这时候ROP技术的提出达成了绕过NX的目的。
1、NX
NX(No-eXecute),不可执行,DEP(Data Execution Prevention),数据执行保护。Linux下为NX,Windows为DEP。
其能够在内存上执行额外检查以防止在系统上运行恶意代码。
通过将数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时, 程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是执行shellcode。
NX保护机制的开关:
1 | gcc nx.c -o nx #默认情况下,开启NX保护机制 |
2、ROP
ROP(Return Oriented Programming),在缓冲区溢出的基础上,利用程序中已有的gadgets来改变某些寄存器或变量值,从而控制程序的执行流程。
ROP攻击的条件:
- 存在溢出且可控制返回地址。
- 存在满足条件的gadgets和gadgets的地址。
3、gadgets
以ret结尾的指令序列。通过这些指令序列,可以改变某些地址的内容,方便控制程序的执行流程。
ROP就是利用指令集中的ret指令,改变指令流的执行顺序。
Ret2text
ret2text,基本ROP之一,控制程序执行本身已有的代码(.text)。
Example
以 github-ctf-wiki中的ret2text样例程序举例:
32位的binary,开启了NX。
1、IDA:
可以看到,危险函数gets,在没有控制好写入空间大小的情况下,可向内存写入一段0x64
大小的数据。
同时binary中还有一个后面secure
函数,其内调用了systen("/bin/sh")
。
2、GDB:
根据前面IDA的分析,可以看到该binary中存在栈溢出,那么溢出空间的偏移量是0x64
吗?
这里我用gdb调试说明:
可以看到s的位置在[esp+0x1c],把断点设置为call gets函数处0x80486ae
。
可以看到ebp=0xffffd048;esp=0xffffcfc0,s的地址=esp+0x1c=0xffffcfc0+0x1c=0xffffcfdc。
那么,相对于ebp的偏移量为offset=ebp-s_addr=0xffffd048-0xffffcfdc=0x6c
。相对于ret_addr的偏移量offset=0x6c+4
。
另一种解释:可以看到在IDA的伪代码中发现
__cdecl 函数调用约定会把形参自右向左依次压入栈中。
一般情况是一个参数,所以相对于ret_addr的偏移量offset=0x64+4
,现在有两个形参,所以offset=0x64+4+4+4
。
3、pwn:
劫持到system(“/bin/sh”)
4、exploit:
1 | from pwn import * |
Reference
github-ctf-wiki