+40

发布时间 2023-05-03 22:29:37作者: 呆唯可可爱爱

首先很容易发现这是64位文件 <br>

让我们打开ida看一下c语言代码,通过简单的浏览函数可以找到一个很明显的后门函数havedoor:

进这个函数看一下就可以看出这就是我们要溢出的地址:system_addr = 0x4011d6,甚至自己不用构造任何gadget

所以先过一遍函数流程可以发现这是一个根据随机值判断的,但是由于srand函数是伪随机,因此如果知道seed的值,则每一次<br>

都是对相同的数来判断,这里有两种方法可以获得正确的结果,第一种是直接打表,因为一共就10种可能,最终真实的值应该是2 7 2(T.T)<br>

但是由于我们是pwn✌,所以应该用正规手法,但是seed值怎么确定嘞-><br>

我们发现在执行循环之前要读s的值,而且局部变量在底层是连着的而且它们距离ebp的相对位置ida已经很贴心的给出来了:

可以发现s离seed很近而且没有什么防护措施,因此可以将s溢出到seed并改变seed变成自己写的确定的值,这样srand(seed)的值就可以确定了。<br>

即payload1 = b'a' *(0x16-0x8) + p64(1) //0x16-0x8是s与seed之间的距离。

然后我们就可以很顺利的进入secondwish函数。<br>

进里面一眼看到canary,再加上printf函数,由于这是一个签到题,所以大概就是格式化字符串漏洞获得canary的地址,然后通过这个地址绕过canary,最终在返回地址上填上havedoor函数的地址就行啦。<br>
所以现在的问题是怎么利用格式化字符串漏洞得到canary,我目前知道的方法就是一个一个试,因为canary上面就是ebp,因此当你参数位置超过canary的地址后程序会直接报错,通过这种方法可以构造这里的payload2 = "%11$p"。<br>

然后因为你是强行按照地址顺序走下去的,因此可能会在canary地址后面接接下来的数据,因为canary是以0x结尾的,所以接受数据接受到这里就行<br>

要获得正确的地址还要简单截断一下,即pc.recv(16)(只要前16位就行)。

这时你就得到canary的真实地址了,这时程序还在继续进行,再用相同的方法进入thirdwish,通过s的地址溢出到havedoor即可。即构造payload3 = p64(canary).rjust(0x30,b'a') + p64(deadbeef) + p64(havedoor_addr) //这里要用rjust因为要保证canary在栈底。

整个流程大概就是这样。