原理
由于canary保护就是在距离EBP一定距离的栈帧中,用于验证是否程序有构造缓冲区的危险。而canary所在的位置一般也都在EBP-8的位置上存储着,因此 只要有机会泄露canary的位置,我们便有机会溢出程序
泄露方式
覆盖00字节读取
原理
由于canary是在栈中的,而一般情况下为防止read、printf等函数直接读出canary的数据,canary都是以\x00为结尾设计的。这时我们可以利用换行符在将buf填充满之后会将\x0a覆盖至canary结尾的\x00覆上,这样就能顺利的读出canary的数据了,之后再将cannary-\x0a即可得到真实的canary的数据

利用条件
- 存在
read/printf等读出字符串的函数 - 可以两次栈溢出
- 第一次是覆盖00字节,泄露canary
- 第二次是利用canary进行攻击
格式化字符串读取
原理
利用格式化字符串漏洞的任意读
由于canary的最低字节是0x00,所以不能用%s的格式当作字符串来读,而应该使用%p或者%x等当作一个数来读
从栈的情况看,var_8(即canary的值)距离栈顶n个字节,n/8 =x,64位Linux前六个参数用寄存器传递,后面的才从栈上读取,所以要使var_8是printf函数的第x+7个参数,因此使用“(x+6)$p”作为printf参数可以泄露出canary的值。
条件
存在格式化字符串漏洞
知识点补充:
%i$p是指打印出偏移format第i个参数的值
One by one 爆破猜解
原理
对于canary,虽然每次进程重启后canary会不同,但是同一个进程中的不同线程的canary却是相同的,并且通过fork函数创建的子进程中的canary也是相同的,因为fork函数会直接拷贝父进程的内存
最低位为0x00,之后逐位爆破,因此32位的话要循环3次、64位的则需要循环7次,每次从ascii码中取。
如果某一位爆破成功 如\x00\xXX将会覆盖当前的canary末尾的这两位,使之程序认为这便是原有的canary,所以程序会继续运行,反之则会报错,由此来判断是否爆破成功(这里 愚钝的我思考了很久很久…)。
利用条件
要求程序中有fork函数,可以使程序扩展子程序(暂时还没遇到过)