这里恬不知耻的先粘贴一大段i春秋关于ssp leak打法的讲解。其实就是菜,自己讲不出个所以然
除了通过各种方法泄露canary之外,我们还有一个可选项——利用__stack_chk_fail
函数泄露信息。这种方法作用不大,没办法让我们getshell。但是当我们需要泄露的flag或者其他东西存在于内存中时,我们可能可以使用一个栈溢出漏洞来把它们泄露出来。这个方法叫做SSP(Stack Smashing Protect) Leak
.
在开始之前,我们先来回顾一下canary起作用到程序退出的流程。首先,canary被检测到修改,函数不会经过正常的流程结束栈帧并继续执行接下来的代码,而是跳转到call __stack_chk_fail
处,然后对于我们来说,执行完这个函数,程序退出,屏幕上留下一行*** stack smashing detected ***:[XXX] terminated
。这里的[XXX]是程序的名字。很显然,这行字不可能凭空产生,肯定是__stack_chk_fail
打印出来的。而且,程序的名字一定是个来自外部的变量(毕竟ELF格式里面可没有保存程序名)。既然是个来自外部的变量,就有修改的余地。我们看一下__stack_chk_fail
的源码,会发现其实现如下:
1 | void __attribute__ ((noreturn)) __stack_chk_fail (void) |
我们看到__libc_message
一行输出了*** %s ***: %s terminated\n
。这里的参数分别是msg和__libc_argv[0]
。char *argv[]
是main函数的参数,argv[0]
存储的就是程序名,且这个argv[0]就存在于栈上。
这里贴一个vidar的 Veritas501 师傅的讲解
可见,__libc_message 的第二个%s
输出的是argv[0],argv[0]是指向第一个启动参数字符串的指针,而在栈中,大概是这样一个画风
所以SSP leak的玩法就是通过修改栈上的argv[0]指针,从而让__stack_chk_fail
被触发后输出我们想要知道的东西。
所以…… 这位vidar的pwn王意思就是,管他三七二十一,暴力覆盖就是了,别管多长,只要你要的数据的地址你能拿到,覆盖!
这里放一个例题,三叶草的纳新题,canary2
一看,无法泄露,也不能爆破,那自然就想到ssp leak打法
flag的地址在buf里面,你又能通过printf get buf地址。 那剩下的就只有暴力覆盖了
这里贴上exp:
1 | from pwn import * |
对了,这里记录一点我个人的小问题,recv接收后的key是字符串类型,所以不进行p64(key)直接发过去的是ascll,不是我们想要的指针类型。
寻思着,那打包一下就可以了吧。发现p64(key)失败,探究了一下,发现是字符串型转字符串型失败。又想着key = int(key),也不成功。那是因为,int()是有两个参数的,我以前一直以为直接int(x)就好了。2333333333