之前写过一篇 IO_FILE——leak 任意读,但是在学习的时候偷懒了,没有深入去看,这次碰到 winmt 师傅出的题,就傻眼了,故再写一篇博客来记录一下。
例题 ctfshow Incomplete Menu :
洞在 edit 里,可以超过 size 进行一个置零的操作。
这里还是考虑利用 _IO_2_1_stdout_ 来泄露 libc 基址。这里就出现了一个在我上篇文章中忽略的知识点。上一篇文章是通过改 flag 的一系列操作来进行,而 _IO_2_1_stdout_ 还有另一种修改方式可以泄露 libc。及使 _IO_read_end == _IO_write_base,忽略源码在下面:
_IO_size_t new_do_write (_IO_FILE *fp, const char *data, _IO_size_t to_do) { _IO_size_t count; if (fp->_flags & _IO_IS_APPENDING) /* On a system without a proper O_APPEND implementation, you would need to sys_seek(0, SEEK_END) here, but is not needed nor desirable for Unix- or Posix-like systems. Instead, just indicate that offset (before and after) is unpredictable. */ fp->_offset = _IO_pos_BAD; else if (fp->_IO_read_end != fp->_IO_write_base) { _IO_off64_t new_pos = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1); if (new_pos == _IO_pos_BAD) return 0; fp->_offset = new_pos; } count = _IO_SYSWRITE (fp, data, to_do); if (fp->_cur_column && count) fp->_cur_column = _IO_adjust_column (fp->_cur_column - 1, data, count) + 1; _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base; fp->_IO_write_end = (fp->_mode <= 0 && (fp->_flags & (_IO_LINE_BUF | _IO_UNBUFFERED)) ? fp->_IO_buf_base : fp->_IO_buf_end); return count; }
03-06 23:15