开启Canary若发生溢出

开启与不开启对比分析
Function Prlogue
- 多了两条命令
1 | mov %fs:0x28,%rax #从另一个segment的8byte(QWORD)数据拿出来放到rax |

- 运行到canary赋值后,第一个byte为’x’\00’(little-endian)

- 查看Stack情况,rbp-0x8为0,执行下一步再查看栈情况

- 执行一下指令,rbp-0x8位置已变为canary
1 | mov %rax,-0x8(%rbp) #放到rbp减8的地方,即rbp的栈增长方向上 |

输入溢出

- 查看Stack情况,发现都被覆盖为0x6161….包括canary

Function piloge
- 多了几条指令
1 | 401264: 48 8b 55 f8 mov -0x8(%rbp),%rdx # 把放到ebp上面的canary拿出来 |

- 把canary的值拿出来存放与RDX,发现已经被覆盖为0x6161…..

- 执行xor,发现不一样则不会跳转,然后__stack_chk_fail报错

Canary真实地址
- fs寄存器是执行当前栈的TLS结构,TLS(Thread Local Storage)的值由security_init初始化,每次重启后不同,同进程不同线程也是不同的,但是fork函数会copy父进程内存因此相同
- TLS加0x28为canary

- canary在map出来的一段,在stack前面很多,刚好在load的后面
- 很难在stack覆盖到canary地方,除非可以任意写地址可以覆盖真实canary

ByPass
劫持__stack_chk_fail 函数
覆盖 TLS(Thread Local Storage) 中储存的 Canary 值:TLS会保存在stack高地址的地方。所以,当我们溢出足够大的字节,就可以控制TLS结构体,进而控制canary,实现ROP。
爆破Canary