04. 细说Canary保护
一.canary保护:
在第二节课已经提到过,这里我们再把它引用过来复习:
CANARY (栈保护)
这个选项表示栈保护功能是否开启
栈溢出保护是一种缓冲区溢出攻击缓冲手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让shsellcode能够得到执行。当启用栈保护后,函数开始执行的时候会先往栈里插入cookie信息,当函数真正返回的时候会验证cookie信息是否合法,如果不合法就会停止程序运行。攻击者在覆盖返回地址的时候往往也会将cookie信息覆盖掉,导致栈保护检查失败而阻止shellcode的执行。在Linux中我们将cookie信息称为canary。
为了更加直观,画出有无canary保护的堆栈图对比一下:
无canary | 保护有canary保护 |
---|---|
局部变量 | 局部变量 |
EBP | Cookie信息 |
RET | EBP |
参数 | RET |
- | 参数 |
二.实例程序解读
root用户环境:
编写代码: vi canary.c
1 |
|
保存 :wq
1.无canary保护:
编译,不开启canary保护:gcc -no-pie -fno-stack-protector -m32 -o canary canary.c
编译成功出现一把小锁,权限不足,
提权:chmod 777 canary
这就没限制了:
运行调试器打开canary: gdb canary
先查看mian函数代码段:disass main
查看有什么断点:i b
删除断点:d 断点编号
加断点:b *地址
运行:run
可以看到这就运行到了我们加的断点的地方,也就是main函数入口处吧EP!
单步执行:next
分析代码:
第1行,把esp+4地址保存到ecx
+4行,内存对齐:
1 | 主流编译器规则规定“程序访问的地址必须向16字节对齐(被16整除的数)”内存对齐后可以提高访问效率。 |
原来3c往上推了3行到30,刚好16字节
+7行,把mian函数的返回地址压栈
+10行就开始第二节课讲的正常操作,压入栈帧了等等。
退出:q
2.有canary保护
重新覆盖编译:
开启canary保护,为所有函数插入保护:gcc -no-pie -fstack-protector-all -m32 -o canary canary.c
记得提权:chmod 777 canary
调试:gdb canary
查看main函数:disass main
可以看到正如定义红字可知,如上画线部分,向堆栈传入了gs段的一个参数,后面还做对比,决定是否需要跳转!
加断点到加保护处:b *0x080484af
再运行:
+41行,把待验证数据保存到ebx
+41就是把数据转存到堆栈了
一直单步执行到+90,这里进行异或运算,对吧堆栈哪个位置的数据是否还和ebx一样
查看全部寄存器:i r
0x286转化成二进制数后对照eip寄存器表:
je指令看的时ZF位,其实也可以知道【】号里面写出来的都是置1的标识位了
+90运行:
此时ZF位置1了,je达成跳转条件