一.基本概念:
(1)ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。
(2)EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。
一般来说,我们会有如下的覆盖需求
- 覆盖函数返回地址,这时候就是直接看 EBP 即可。
- 覆盖栈上某个变量的内容,这时候就需要更加精细的计算了。
- 覆盖 bss 段某个变量的内容。
- 根据现实执行情况,覆盖特定的变量或地址的内容。
之所以我们想要覆盖某个地址,是因为我们想通过覆盖地址的方法来直接或者间接地控制程序执行流程。
确定填充长度 主要是计算我们所要操作的地址与我们所要覆盖的地址的距离。常见的操作方法就是打开 IDA,根据其给定的地址计算偏移。一般变量会有以下几种索引模式
- 相对于栈基地址的的索引,可以直接通过查看 EBP 相对偏移获得
- 相对应栈顶指针的索引,一般需要进行调试,之后还是会转换到第一种类型。
- 直接地址索引,就相当于直接给定了地址。
二.解题步骤(gdb调试):
(1).打开vm利用pwntools进行基本分析 :
(2).打开ida按f5反编译进行静态分析:
(3).由文件得有且仅有一输入的过程可操作,而gets是一个高危函数,因此联想到栈溢出的知识点。点开s找相应覆盖的偏移距离:
由此得偏移地址为0F+08=25
ps:后门相关知识点:
(4).shift+f12找相应后门发现:
而/bin/sh在函数fun()中
则将fun函数的地址返回给在s数组后看到的r中就可以
(5).进入虚拟机运行调试,ni直到进行到gets操作:
(6).按si进入gets函数观察输入效果:
此时a已重复输入被gets读取存入栈中,顺序跟踪程序运行。
(7).执行到leave操作:
leave:leave指令将RSP寄存器的内容复制到RBP寄存器中,然后RSP寄存器的地址+8。
(8).程序根据输入后跳转到后门函数0X401185:
跟随程序运行至字符串(bin/sh)
拿到程序控制权后,通过后门函数ls获取菜单,catflag即可拿到flag。