IS-pwn-Linux-glibc-house-of-cat

glibc-2.29

house of cat通过修改虚表指针的偏移调用_IO_wfile_jumps中的_IO_wfile_seekoff函数,然后通过_IO_switch_to_wget_mode函数来劫持控制流.

在结合__malloc_assert的情况下只需修改vtable_IO_wfile_jumps + 0x10即可调用_IO_wfile_seekoff函数.

利用条件:

  1. 程序从main函数返回,或能调用exit函数,或能触发assert.
  2. 能泄露出heap地址和libc地址.
  3. 能任意地址写一个堆地址,如largebin_attack.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
off64_t _IO_wfile_seekoff (FILE *fp, off64_t offset, int dir, int mode) {
off64_t result;
off64_t delta, new_offset;
long int count;

if (mode == 0)
return do_ftell_wide (fp);
int must_be_exact = ((fp->_wide_data->_IO_read_base == fp->_wide_data->_IO_read_end) && (fp->_wide_data->_IO_write_base == fp->_wide_data->_IO_write_ptr));
bool was_writing = ((fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base) || _IO_in_put_mode (fp));
if (was_writing && _IO_switch_to_wget_mode (fp))
// rdx == 0
// fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base

// 不知道哪里来的条件
// fp->_wide_data->_IO_read_ptr != fp->_wide_data->_IO_read_end
// fp->_lock是一个可写地址
// fp->_mode = 0
return WEOF;
//other code
}
1
2
3
4
5
6
7
int _IO_switch_to_wget_mode (FILE *fp) {
if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base)
if ((wint_t)_IO_WOVERFLOW (fp, WEOF) == WEOF)
// fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base
return EOF;
// other code
}

观察_IO_switch_to_wget_mode汇编代码.

1
2
3
4
5
6
7
8
9
10
11
0x7f4cae745d30 <_IO_switch_to_wget_mode>       endbr64
0x7f4cae745d34 <_IO_switch_to_wget_mode+4> mov rax, qword ptr [rdi + 0xa0]
0x7f4cae745d3b <_IO_switch_to_wget_mode+11> push rbx
0x7f4cae745d3c <_IO_switch_to_wget_mode+12> mov rbx, rdi
0x7f4cae745d3f <_IO_switch_to_wget_mode+15> mov rdx, qword ptr [rax + 0x20]
0x7f4cae745d43 <_IO_switch_to_wget_mode+19> cmp rdx, qword ptr [rax + 0x18]
0x7f4cae745d47 <_IO_switch_to_wget_mode+23> jbe _IO_switch_to_wget_mode+56 <_IO_switch_to_wget_mode+56>

0x7f4cae745d49 <_IO_switch_to_wget_mode+25> mov rax, qword ptr [rax + 0xe0]
0x7f4cae745d50 <_IO_switch_to_wget_mode+32> mov esi, 0xffffffff
0x7f4cae745d55 <_IO_switch_to_wget_mode+37> call qword ptr [rax + 0x18]

可以发现rax,rdx都由rdi指向的内存区域控制,剩下的就是正常流程.

0%
;