劫持stdout
file 结构体
amd64:
0x0:'_flags',
0x8:'_IO_read_ptr',
0x10:'_IO_read_end',
0x18:'_IO_read_base',
0x20:'_IO_write_base',
0x28:'_IO_write_ptr',
0x30:'_IO_write_end',
0x38:'_IO_buf_base',
0x40:'_IO_buf_end',
0x48:'_IO_save_base',
0x50:'_IO_backup_base',
0x58:'_IO_save_end',
0x60:'_markers',
0x68:'_chain',
0x70:'_fileno',
0x74:'_flags2',
0x78:'_old_offset',
0x80:'_cur_column',
0x82:'_vtable_offset',
0x83:'_shortbuf',
0x88:'_lock',
0x90:'_offset',
0x98:'_codecvt',
0xa0:'_wide_data',
0xa8:'_freeres_list',
0xb0:'_freeres_buf',
0xb8:'__pad5',
0xc0:'_mode',
0xc4:'_unused2',
0xd8:'vtable'
想要进行io leak,首先能将stdout结构体申请出来,写入一些数据就可以进行泄露地址数据.
我们需要覆盖stdout结构体中的 _flags字段为0xfbad1887,并且覆盖 _IO_read_ptr、 _IO_read_end、 _IO_read_base这三个指针为0,最后覆盖 _IO_write_base指针的最后一字节为00(这里并不是非要为00,因为到时候puts函数会泄露 _IO_write_base指针与 _IO_write_ptr指针之间的所有数据,只要将 _IO_write_base指针改的小于 _IO_write_ptr指针并且确定这二者之间存在libc地址,那么都是可以的,只不过我通常将其覆盖为x00)
至于为什么要将 _flags字段改为0xfbad1887这个值,是因为这个字段的各个比特位都属于标志位,不同比特位存在的意义不同,能绕过的检查也不同。而将 _flags字段改为0xfbad1887这个值,正好可以绕过阻止我们完成io leak的所有检查(具体是哪些检查又或者如何绕过的,可以去网上看一下其他师傅的博客),然后read那三个指针,我试了一下,他们的值无所谓(不一定非要写成00)。
house of apple2
劫持stdout进行io利用
利用思路
目前在glibc
源码中搜索到的_IO_WXXXXX
系列函数的调用只有_IO_WSETBUF
、_IO_WUNDERFLOW
、_IO_WDOALLOCATE
和_IO_WOVERFLOW
。其中_IO_WSETBUF
和_IO_WUNDERFLOW
目前无法利用或利用困难,其余的均可构造合适的_IO_FILE
进行利用。这里给出我总结的几条比较好利用的链。以下使用fp
指代_IO_FILE
结构体变量。
利用_IO_wfile_overflow函数控制程序执行流
对fp
的设置如下:
-
•
_flags
设置为~(2 | 0x8 | 0x800)
,如果不需要控制rdi
,设置为0
即可;如果需要获得shell
,可设置为sh;
,注意前面有两个空格 -
•
vtable
设置为_IO_wfile_jumps/_IO_wfile_jumps_mmap/_IO_wfile_jumps_maybe_mmap
地址(加减偏移),使其能成功调用_IO_wfile_overflow
即可 -
•
_wide_data
设置为可控堆地址A
,即满足*(fp + 0xa0) = A
-
•
_wide_data->_IO_write_base
设置为0
,即满足*(A + 0x18) = 0
-
•
_wide_data->_IO_buf_base
设置为0
,即满足*(A + 0x30) = 0
-
•
_wide_data->_wide_vtable
设置为可控堆地址B
,即满足*(A + 0xe0) = B
-
•
_wide_data->_wide_vtable->doallocate
设置为地址C
用于劫持RIP
,即满足*(B + 0x68) = C
函数的调用链如下:
_IO_wfile_overflow
_IO_wdoallocbuf
_IO_WDOALLOCATE
*(fp->_wide_data->_wide_vtable + 0x68)(fp)
利用_IO_wfile_underflow_mmap函数控制程序执行流
我这里利用的是puts函数,puts函数会调用vtable中的xsputn函数,我们加减一下偏移,让他调用_IO_wfile_overflow
vtable结构体:
void * funcs[] = {
0x0: '__dummy'
0x8: '__dummy2'
0x10: '__finish'
0x18: '__overflow'
0x20: '__underflow'
0x28: '__uflow'
0x30: '__pbackfail'
0x38: '__xsputn'
0x40: '__xsgetn'
0x48: '__seekoff'
0x50: '__seekpos'
0x58: '__setbuf;
0x60: '__sync'
0x68: '__doallocate'
0x70: '__read'
0x78: '__write'
0x80: '__seek'
0x88: '__close'
0x90: '__stat'
0x98: '__showmanyc'
0x100: '__imbue'
};
劫持rsp布置rop
2.31 的 setcontext+orw和之前版本的区别是setcontext 的位置变成了 setcontext+61
一个gadget配合使用
把栈迁移到你能控制的地方就可以进行愉快的orw啦
今天的知识你学会了多少呢?
长按下方的二维码关注我们
下周的干货已经在等你了!!![【表哥有话说 第82期】劫持stdout 【表哥有话说 第82期】劫持stdout]()
原文始发于微信公众号(SKSEC):【表哥有话说 第82期】劫持stdout
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论