针对于canary的进一步利用手段:
一 : stack smash
样栗一:
gdb调试看看程序G的时候发生了什么
可以看到当程序检查到Canary被破坏之后,程序call了 stack_chk_fail 函数,
看下源码
再看fortify_fail函数
拖进ida
计算
样栗二:
由于flag保存到了栈中,若想利用stack smash的话先泄露栈地址。
进入while循环,判断v7是否大于等于v8,v8是3,v7初始是0,若判断为真,则程序就return ,main函数结束,若为假,则调用
这个函数:是fork一个子进程,如下图:
我们知道,第一次fork的话是父进程fork的子进程,会返回一个子进程的id,则if里边的判断会为假,执行++v7,然后fork的子进程再fork进程,而此时是子进程fork的进程,会返回一个返回值0,则此时if里的判断会为真,则break。
break后继续接下来的程序
肯定是猜不对的。考虑stack smash,但是得先知道栈地址。而前边我们知道是可以fork3次的,可以考虑先泄露libc,再泄露libc中的environ,而environ中保存着一个栈地址。然后计算保存flag的buf到栈地址的偏移,最后就能输出flag。
gdb调试,断电打在gets,运行到比对flag处:
发现我们输入的位置,然后查看栈中情况
用ded8减去我们输入字符串的地址ddb0,为128。(其实这就是相当于不借助ida分析缓冲区大小,直接gdb调试来知道缓冲区大小)
然后泄露libc地址
再次调试,gets下断点,计算environ中保存的栈 到flag的偏移
然后 dee8减去dd80,168的偏移
来通过environ泄露其中保存的栈地址,再减去偏移输出flag。
成功输出flag
注意:这是在libc2.23。
libc2.27下与2.23不一样,会多一个参数false
由于会传进来一个false,所以need_backtrace为false,这 个表达式只会输处unknown。也就是说stack smash在libc2.27已经不行了。
在2.31下也不行,
被砍了一个格式化字符%s。因此,stack smash方法在2.23以后已经不可行了。但libc2.23还是可行的。
二:多进程下的爆破
先来看下fork函数:
看一个栗题的源代码。
利用思路,我们知道64位程序canary是八个字节,其中最低字节默认为\x00,如下
exp如下:
Comments | 2 条评论
博主 潘
搞得不错,加油
博主 潘
加油