最近经常遇到没有show函数的堆了,吃了不少没有地址的亏,在这里记录一下泄露的方法
其实主要思路就是修改stdout的flag位为0xfbad1800
,并且将_IO_write_base
的最后一个字节改小,从而实现多输出一些内容,这些内容里面就包含了libc地址。
为什么flag要改成0xfbad1800
,看源码:
puts函数在源码中是由_IO_puts
实现的,而_IO_puts
函数内部会调用_IO_sputn
,结果会执行_IO_new_file_xsputn
,最终会执行_IO_overflow
1 | int |
可以看到_IO_do_write
是最后调用的函数,而_IO_write_base
是我们要修改的目标。
这里f->_flag & _IO_NO_WRITES
的值应该为0,为了不进入第一个if分支
同时使f->_flag &_IO_CURRENTLY_PUTTING
的值为1,为了不进入第二个if分支
_IO_do_write
函数的参数为:stdout结构体、_IO_write_base
和size(由f->_IO_write_ptr - f->_IO_write_base
决定),而_IO_do_write
实际会调用new_do_write
,参数一样。
1 | static |
这里,_IO_SYSWRITE
就是我们的目标,这相当于write(fp,data,to_do)
。
_IO_SYSSEEK
只是简单的调用lseek,但是我们不能完全控制fp->_IO_write_base - fp->_IO_read_end
的值,如果fp->_IO_read_end
的值设置为0,那么_IO_SYSSEEK
的第二个参数值就会过大,如果设置fp->_IO_write_base = fp->_IO_read_end
的话,那么在其它地方就会有问题,因为fp->_IO_write_base 不能大于 fp->_IO_write_end
。所以这里要设置fp->_flags | _IO_IS_APPENDING
,避免进入else if 分支。
最终需要构造的fp-flags
是这样的,才能绕过上面提到的分支。
1 | _flags = 0xfbad0000 |
所以通常将stdout的flags修改成0xfbad1800
,将_IO_write_base
改小,就可以造成libc的泄漏。
这里以De1CTF的weapon和数字经济云的 fkroman为例
weapon
程序保护全开,got不可写
1 | 1. create you weapon |
三个功能,没有show函数
1 | unsigned __int64 delete() |
delete中存在UAF漏洞
利用思路:
利用UAF申请到stdout结构体上面,修改flags泄漏libc,将malloc_hook覆盖成onegadget
为了方便调试这里先把asrl关了sudo sh -c "echo 0 > /proc/sys/kernel/randomize_va_space"
接下来说一下我具体的做法,首先申请大小为0x70的chunk0,chunk1,chunk2,将chunk0,chunk1释放掉,此时fastbin:chunk1->chunk0
自用UAF使得fastbin:chunk1->chunk0内部
实现overlap为下一步修改地址做准备,比如我是:0x70: 0x555555757070 —▸ 0x555555757000 ◂— 0x0
–> 0x70: 0x555555757070 —▸ 0x555555757010 ◂— 0x0
再将0x555555757010
申请为chunk4,现在rename chunk4就可以修改chunk1的大小了。free chunk1,修改chunk1大小为0x90
再次free chunk1,这个时候fastbin中的chunk1的fd和bk就会被写入一个main_arena+88
1 | pwndbg> bins |
在stdout往上找到一个0x7f
的位置充当size,将main_arena+88低2字节覆盖成25dd
(5dd是固定的,但是2是随机的,1/16)
申请出来,修改flags和_IO_write_base
低字节
1 | pwndbg> p _IO_2_1_stdout_ |
得到libc后,就UAF将onegadget写入malloc_hook
1 | #coding:utf-8 |
fkroman
程序同样保护全开,没有show功能
漏洞:UAF,任意长度堆溢出
利用思路一样,先攻击stdout泄漏libc,再将onegadget写入malloc_hook
只不过这题更简单,堆溢出直接改size不用overlap
1 | #coding:utf-8 |