测试栗子:https://github.com/tower111/software.git blind
stdout指针指向的数据
pwndbg> x /50xg 0x00007fdc0a660620
0x7fdc0a660620 <_IO_2_1_stdout_>: 0x00000000fbad2887 0x00007fdc0a6606a3
0x7fdc0a660630 <_IO_2_1_stdout_+16>: 0x00007fdc0a6606a3 0x00007fdc0a6606a3
0x7fdc0a660640 <_IO_2_1_stdout_+32>: 0x00007fdc0a6606a3 0x00007fdc0a6606a3
0x7fdc0a660650 <_IO_2_1_stdout_+48>: 0x00007fdc0a6606a3 0x00007fdc0a6606a3
0x7fdc0a660660 <_IO_2_1_stdout_+64>: 0x00007fdc0a6606a4 0x0000000000000000
0x7fdc0a660670 <_IO_2_1_stdout_+80>: 0x0000000000000000 0x0000000000000000
0x7fdc0a660680 <_IO_2_1_stdout_+96>: 0x0000000000000000 0x00007fdc0a65f8e0
0x7fdc0a660690 <_IO_2_1_stdout_+112>: 0x0000000000000001 0xffffffffffffffff
0x7fdc0a6606a0 <_IO_2_1_stdout_+128>: 0x000000000a000000 0x00007fdc0a661780
0x7fdc0a6606b0 <_IO_2_1_stdout_+144>: 0xffffffffffffffff 0x0000000000000000
0x7fdc0a6606c0 <_IO_2_1_stdout_+160>: 0x00007fdc0a65f7a0 0x0000000000000000
0x7fdc0a6606d0 <_IO_2_1_stdout_+176>: 0x0000000000000000 0x0000000000000000
0x7fdc0a6606e0 <_IO_2_1_stdout_+192>: 0x00000000ffffffff 0x0000000000000000
0x7fdc0a6606f0 <_IO_2_1_stdout_+208>: 0x0000000000000000 0x00007fdc0a65e6e0
这里是file结构(stdout被命名为IO_2_1_stdout_)
FLIE结构被封装为_IO_FILE_plus
struct _IO_FILE_plus
{
_IO_FILE file;
IO_jump_t *vtable;
}
pwndbg> print _IO_2_1_stdout_
$1 = {
file = {
_flags = 0xfbad2887,
_IO_read_ptr = 0x7fdc0a6606a3 <_IO_2_1_stdout_+131> "\n",
_IO_read_end = 0x7fdc0a6606a3 <_IO_2_1_stdout_+131> "\n",
_IO_read_base = 0x7fdc0a6606a3 <_IO_2_1_stdout_+131> "\n",
_IO_write_base = 0x7fdc0a6606a3 <_IO_2_1_stdout_+131> "\n",
_IO_write_ptr = 0x7fdc0a6606a3 <_IO_2_1_stdout_+131> "\n",
_IO_write_end = 0x7fdc0a6606a3 <_IO_2_1_stdout_+131> "\n",
_IO_buf_base = 0x7fdc0a6606a3 <_IO_2_1_stdout_+131> "\n",
_IO_buf_end = 0x7fdc0a6606a4 <_IO_2_1_stdout_+132> "",
_IO_save_base = 0x0,
_IO_backup_base = 0x0,
_IO_save_end = 0x0,
_markers = 0x0,
_chain = 0x7fdc0a65f8e0 <_IO_2_1_stdin_>,
_fileno = 0x1,
_flags2 = 0x0,
_old_offset = 0xffffffffffffffff,
_cur_column = 0x0,
_vtable_offset = 0x0,
_shortbuf = "\n",
_lock = 0x7fdc0a661780 <_IO_stdfile_1_lock>,
_offset = 0xffffffffffffffff,
_codecvt = 0x0,
_wide_data = 0x7fdc0a65f7a0 <_IO_wide_data_1>,
_freeres_list = 0x0,
_freeres_buf = 0x0,
__pad5 = 0x0,
_mode = 0xffffffff,
_unused2 = '\000' <repeats 19 times>
},
vtable = 0x7fdc0a65e6e0 <_IO_file_jumps>
}
需要关注vtable = 0x7fdc0a65e6e0 <_IO_file_jumps>
pwndbg> print _IO_file_jumps
$2 = {
__dummy = 0x0,
__dummy2 = 0x0,
__finish = 0x7fdc0a3149c0 <_IO_new_file_finish>,
__overflow = 0x7fdc0a315730 <_IO_new_file_overflow>,
__underflow = 0x7fdc0a3154a0 <_IO_new_file_underflow>,
__uflow = 0x7fdc0a316600 <__GI__IO_default_uflow>,
__pbackfail = 0x7fdc0a317980 <__GI__IO_default_pbackfail>,
__xsputn = 0x7fdc0a3141e0 <_IO_new_file_xsputn>,
__xsgetn = 0x7fdc0a313ec0 <__GI__IO_file_xsgetn>,
__seekoff = 0x7fdc0a3134c0 <_IO_new_file_seekoff>,
__seekpos = 0x7fdc0a316a00 <_IO_default_seekpos>,
__setbuf = 0x7fdc0a313430 <_IO_new_file_setbuf>,
__sync = 0x7fdc0a313370 <_IO_new_file_sync>,
__doallocate = 0x7fdc0a308180 <__GI__IO_file_doallocate>,
__read = 0x7fdc0a3141a0 <__GI__IO_file_read>,
__write = 0x7fdc0a313b70 <_IO_new_file_write>,
__seek = 0x7fdc0a313970 <__GI__IO_file_seek>,
__close = 0x7fdc0a313340 <__GI__IO_file_close>,
__stat = 0x7fdc0a313b60 <__GI__IO_file_stat>,
__showmanyc = 0x7fdc0a317af0 <_IO_default_showmanyc>,
__imbue = 0x7fdc0a317b00 <_IO_default_imbue>
}
fwrite
size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
fwrite的代码位于/libio/iofwrite.c中,函数名为_IO_fwrite。在_IO_fwrite中主要是调用_IO_XSPUTN来实现写入的功能。
_IO_XSPUTN对应的默认函数_IO_new_file_xsputn。
_IO_new_file_xsputn中会调用_IO_OVERFLOW。_IO_OVERFLOW默认对应的函数是_IO_new_file_overflow。
在_IO_new_file_overflow内部最终会调用系统接口write函数。
FILE *fopen(char *filename, *type);
使用malloc分配FILE结构
设置FILE结构的vtable
初始化分配的FILE结构
将初始化的FILE结构链入FILE结构链表中
调用系统调用打开文件