0x00 简介
在libc 2.24版本以后,对vtable的劫持进行了检测,但是这并没有增加利用的难度,反而更简单了。
参考:https://mp.weixin.qq.com/s/RDFsJrgkz4ywAwuFV7Rneg
https://ctf-wiki.github.io/ctf-wiki/pwn/linux/io_file/exploit-in-libc2.24-zh/#_io_str_jumps-finish
0x01 检测机制
我还是直接用的bookwriter这道题来绕过vtable的检测。
检测函数在/libio/libioP.h中:
1 | static inline const struct _IO_jump_t * |
可以看到glibc中是有一段完整的内存存放着各个vtable,其中__start___libc_IO_vtables
指向第一个vtable地址_IO_helper_jumps
,而__stop___libc_IO_vtables
指向最后一个vtable_IO_str_chk_jumps
结束的地址,最后进入_IO_vtable_check
触发报错。
进入该函数意味着目前的vtable不是glibc中的vtable,因此_IO_vtable_check
判断程序是否使用了外部合法的vtable(重构或是动态链接库中的vtable),如果不是则报错。
glibc2.24中vtable中的check机制可以小结为:
1.判断vtable的地址是否处于glibc中的vtable数组段,是的话,通过检查。2.否则判断是否为外部的合法vtable(重构或是动态链接库中的vtable),是的话,通过检查。3.否则报错,输出Fatal error: glibc detected an invalid stdio handle
,程序退出。
所以最终的原因是:exp中的vtable是堆的地址,不在vtable数组中,且无法通过后续的检查,因此才会报错。
0x02 利用方法
使用内部的vtable_IO_str_jumps
或_IO_wstr_jumps
来进行利用
如何利用_IO_str_jumps
或_IO_wstr_jumps
完成攻击?在vtable的check机制出现后,大佬们发现了vtable数组中存在_IO_str_jumps
以及_IO_wstr_jumps
两个vtable,_IO_wstr_jumps
与_IO_str_jumps
功能基本一致,只是_IO_wstr_jumps
是处理wchar的,因此这里以_IO_str_jumps
为例进行说明,后者利用方法完全相同。
_IO_str_jumps
的函数表如下
函数表中存在两个函数_IO_str_overflow
以及_IO_str_finish
,其中_IO_str_finish
源代码如下,在文件/libio/strops.c
中:
1 | void |
条件:
- _IO_buf_base 不为空
- _flags & _IO_USER_BUF(0x01) 为假
构造如下:
1 | _flags = (binsh_in_libc + 0x10) & ~1 |
0x03 示例 bookwriter
1 | from pwn import * |
0x04 2.27下利用fsop执行orw
1 | from pwn import * |