本文主要是介绍IO_FILE——leak 任意读,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Python微信订餐小程序课程视频
https://edu.csdn.net/course/detail/36074
Python实战量化交易理财系统
https://edu.csdn.net/course/detail/35475
在堆题没有show函数时,我们可以用 IO_FILE 进行leak,本文就记录一下如何实现这一手法。
拿一个输出函数 puts 来说,它在源码里的表现形式为 _IO_puts 。
\_IO\_puts (const char *str)
{int result = EOF;\_IO\_size\_t len = strlen (str);\_IO\_acquire\_lock (\_IO\_stdout);if ((\_IO\_vtable\_offset (\_IO\_stdout) != 0|| \_IO\_fwide (\_IO\_stdout, -1) == -1)&& \_IO\_sputn (\_IO\_stdout, str, len) == len&& \_IO\_putc\_unlocked ('\n', \_IO\_stdout) != EOF)result = MIN (INT\_MAX, len + 1);\_IO\_release\_lock (\_IO\_stdout);return result;
}
我们可以看到 _IO_puts 又调用了一个叫 _IO_sputn 的函数。
#define \_IO\_sputn(\_\_fp, \_\_s, \_\_n) \_IO\_XSPUTN (\_\_fp, \_\_s, \_\_n)
它是一个宏,它的作用就是调用 _IO_2_1_stdout_ 里 vtable 所指向的 _IO_XSPUTN,也就是 _IO_new_file_xsputn
\_IO\_size\_t
\_IO\_new\_file\_xsputn (\_IO\_FILE *f, const void *data, \_IO\_size\_t n)
{const char *s = (const char *) data;\_IO\_size\_t to\_do = n;int must\_flush = 0;\_IO\_size\_t count = 0;............else if (f->\_IO\_write\_end > f->\_IO\_write\_ptr)count = f->\_IO\_write\_end - f->\_IO\_write\_ptr; /* Space available. *//* Then fill the buffer. */if (count > 0){
............if (\_IO\_OVERFLOW (f, EOF) == EOF)
当 f->_IO_write_end > f->_IO_write_ptr 时,会调用 memcpy 拷贝数据至缓冲区。之后还会判断目标输出数据是否还有剩余。如果还有剩余就要调用 _IO_OVERFLOW 函数,刷新缓冲区。这个函数在 vtable 中为 _IO_overflow ,也就是 _IO_new_file_overflow 。
int
\_IO\_new\_file\_overflow (\_IO\_FILE *f, int ch)
{if (f->\_flags & \_IO\_NO\_WRITES) /* SET ERROR */{f->\_flags |= \_IO\_ERR\_SEEN;\_\_set\_errno (EBADF);return EOF;}/* If currently reading or no buffer allocated. */if ((f->\_flags & \_IO\_CURRENTLY\_PUTTING) == 0 || f->\_IO\_write\_base == NULL){/* Allocate a buffer if needed. */if (f->\_IO\_write\_base == NULL){\_IO\_doallocbuf (f);\_IO\_setg (f, f->\_IO\_buf\_base, f->\_IO\_buf\_base, f->\_IO\_buf\_base);}/* Otherwise must be currently reading.If \_IO\_read\_ptr (and hence also \_IO\_read\_end) is at the buffer end,logically slide the buffer forwards one block (by setting theread pointers to all point at the beginning of the block). Thismakes room for subsequent output.Otherwise, set the read pointers to \_IO\_read\_end (leaving thatalone, so it can continue to correspond to the external position). */if (\_\_glibc\_unlikely (\_IO\_in\_backup (f))){size\_t nbackup = f->\_IO\_read\_end - f->\_IO\_read\_ptr;\_IO\_free\_backup\_area (f);f->\_IO\_read\_base -= MIN (nbackup,f->\_IO\_read\_base - f->\_IO\_buf\_base);f->\_IO\_read\_ptr = f->\_IO\_read\_base;}if (f->\_IO\_read\_ptr == f->\_IO\_buf\_end)f->\_IO\_read\_end = f->\_IO\_read\_ptr = f->\_IO\_buf\_base;f->\_IO\_write\_ptr = f->\_IO\_read\_ptr;f->\_IO\_write\_base = f->\_IO\_write\_ptr;f->\_IO\_write\_end = f->\_IO\_buf\_end;f->\_IO\_read\_base = f->\_IO\_read\_ptr = f->\_IO\_read\_end;f->\_flags |= \_IO\_CURRENTLY\_PUTTING;if (f->\_mode <= 0 && f->\_flags & (\_IO\_LINE\_BUF | \_IO\_UNBUFFERED))f->\_IO\_write\_end = f->\_IO\_write\_ptr;}if (ch == EOF)return \_IO\_do\_write (f, f->\_IO\_wr
这篇关于IO_FILE——leak 任意读的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!