这道题是攻防世界上面一道六星的pwn题,比起之前的还是挺有难度,做完也有很大收获
题目分析
首先checksec查看开启的保护
可以看到这题比之前的题目多了一个PIE保护,下面就简单介绍一下什么是PIE
PIE全称是position-independent executable,中文解释为地址无关可执行文件,该技术是一个针对代码段(.text)、数据段(.data)、未初始化全局变量段(.bss)等固定地址的一个防护技术,如果程序开启了PIE保护的话,在每次加载程序时都变换加载地址,从而不能通过ROPgadget等一些工具来帮助解题
下面接着对源文件进行分析
main函数:
hint函数:
go函数:
在go函数中我们可以发现如果v2<=0的话,v5是不会被初始化的,而之前的hint函数中出现了system函数的地址,这个地址会不会在栈上保存呢?
接下来我们看一下hint函数的汇编代码:
可以看到system函数的地址被放到了rbp-110h的地方,而go函数中v5变量的位置正好就是rbp-110h
这里就出现了一个可利用的地方,如果我们进入go函数之后第一次输入小于等于0,system的地址就被保留在了栈上,而之后程序还会让我们进行一次输入,并把rbp-110h位置处的值变为加上新的输入的值,这个新的输入是没有限制的,意味着我们可以把system的地址改为libc中的任何地址。
接下来再看看play_game函数:
这里有一个明显的栈溢出,buf的大小仅为0x8,却可以读入最多0x400的数据,这意味着我们可以改变函数的返回地址,但是开启了PIE保护,意味着我们不知道程序执行时候的真实地址,那我们要把返回地址改成什么呢?
这里就需要利用vsyscall和之前保留在栈上的system函数了
vsyscall是什