栈溢出-pwn
目的
能够粗略的看懂汇编代码,学会使用一些pwn入门工具!
学习过程
打开命名为pwn的可执行文件,将其用IDA静态调试器打开
简易进行相关汇编代码的分析,基本了解栈的结构
按F5对汇编代码进行反汇编,得到源代码
对setvbuf代码进行简单学习,也算是增长新知识,如下:
功 能: 把缓冲区与流相关;
用 法: int setvbuf(FILE *stream, char *buf, int type, unsigned size);
参数:stream:指向流的指针;buf:期望缓冲区的地址;type:期望缓冲区的类型;size : 缓冲区内字节的数量。
根据源代码也可知程序的相关内容,比如设置缓冲区,输出内容等。
开辟的buf缓存区共0x64个字节,但read最多可以读0x100个字节,那么就会造成缓存区溢出,我们就可以加以利用,将栈中ret地址覆盖。
接下来,根据pwn一些题目的设置,找到getflag函数:
其中cat flag在终端可以理解为获取旗的内容。
接下来我们将对其进行动态调试,拖入Ubuntu Unix
在终端中执行./pwn,发现可以输入,便随机输入123456,回车
输入gdb pwn 进行动态调试:
在主函数mai处加入断点,并运行:
n指令,单步运行,直到执行到read输入处
此时我们需要求输入函数相对于ebp的偏移量,这样才能根据相对位置找出函数位置距返回寄存器ret的长度,从而输入无关参数覆盖到ret处,并将我们需要的函数地址覆盖掉ret寄存器里的地址,达到取得系统权限的目的。
计算偏移量的大小共有两种,一种是直接计算,一种是输入多于buffer大小的参数,让系统报错,报出出现错误的地址,即可。在这里我们采用第一种方法:
由上图可知,此时目标地址为esp+0x1c,寄存器esp中值为0xffffcf90,ebp值为0xffffd018,根据栈结构,ret=ebp+0x4,故ret地址为0xffffd1c,故其偏移量为0x70(十六进制)=112(十进制),即我们需要输入112个无关参数进行覆盖。
再次打开IDA静态调试器,找到getflag函数的起始地址,作为我们覆盖ret的地址:
在pwn所在文件下输入脚本:
当然,在这个脚本中,ELF所在该行代码并不是必须的,他只是以二进制的格式打开文档,删除该句并运行脚本效果不会变化。
接着在终端运行脚本,覆盖掉ret地址,获取系统权限:
此时由于是本地的练习,flag是并不存在的,所以我们在pwn所在文件下创建一个文档作为flag,由于函数名为cat f1ag,故文档名为f1ag:
再次运行脚本,得到flag的内容:
此时便算是简单完成栈溢出的小练习。