canary


原理

由于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函数,可以使程序扩展子程序(暂时还没遇到过)


文章作者: Pr0b1em
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Pr0b1em !
  目录