1.什么是栈溢出
栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致与其相邻的栈中的变量的值被改变。
通过栈溢出修改栈上的返回地址,这样cpu执行ret指令的时候,就会将被修改的值从栈上取出放入eip寄存器中,紧接着执行eip所指向的位置的指令,这样就相当于控制了程序的执行流。
没有canary保护,可以利用填充垃圾数据来修改返回地址。
ret2text思路:
首先通过栈溢出填充垃圾数据,覆盖到ret之前,再填入system函数地址,即可获得shell。
可能存在栈溢出的函数:
2.如何确定栈溢出所需要的垃圾数据长度?
通过ida可以观察出来,但有时结果不太准确,与动态调试的结果不同(有时候动态调试结果也不太准确,一般以动态调试结果为准,也可以动态调试结果和ida结果分别尝试一次)。
如何快速定位:测试非法地址
pwndbg:
cyclic 整数(整数不要太短):出现一堆字符,复制并输入至程序中,找到非法地址0xxxxxx
cyclic -l 0xxxxxx
得到的数据即为输入点到ret的距离
peda:
pattern create 整数
如果成功,程序会返回一段非法地址 //若未返回地址,而是停在ret,则取栈顶前四个字节
pattern offset 0xxxxxx //pattern offset AAAA
获得了偏移
3.找system函数
BSS段:用来存放程序中未初始化的全局变量的一块内存区域,属于静态内存分配。(在溢出时eip的值可以是BSS段的地址)
Data段:用来存放程序中已初始化的全局变量的一块内存区域,属于静态内存分配。
Text段:用来存放程序执行代码的一块内存区域,称为代码段。
rodata段:存放C中的字符串和#define定义的常量
(1)找到system函数的地址:
(2)通过地址找到对应汇编代码:
objdump -d -M intel ret2text
想知道0x8048763内容:
gdb ret2text
x/s 0xxxxxx
存放的是目标内容
(3)要调用system函数,需用mov那一行指令的地址覆盖,才能成功运行system函数