House Of Pig
通过 libc-2.31 下的 largebin attack 以及 FILE 结构利用,来配合 libc-2.31 下的 tcache stashing unlink attack 进行组合利用的方法
- 运用场景:
- 主要适用于程序中仅有 calloc 函数来申请 chunk,而没有调用 malloc 函数的情况
- 核心技术点:
- 利用了 glibc 中
IO_str_overflow
函数内会连续调用 malloc,memcpy,free 函数的特点,并且这三个函数的参数都可以由 FILE 结构内的数据来控制
- 利用了 glibc 中
House Of Pig 原理
House Of Pig 通常是配合 tcache_stashing_unlink 使用的
在 tcache 中有如下检查:
1 | if (in_smallbin_range (nb)) |
- 但 small chunk 即将进入 tcache 时,就会触发以上检查
- 可以发现程序只检查了 bck->fd 是否等于自己,但 bck 是可以被我们伪造的
函数 calloc 可以越过 tcache,去直接使用 smallbin,我们可以利用 UAF 修改 small chunk->bk(同时伪造 fake chunk->fd),然后使用 calloc 去申请它,并将 chunk->bk 指向的 fake chunk 给接入 tcache
这就是 tcache_stashing_unlink 的基本思路,但这个思路在全使用 calloc 的程序中并不适用,因为没有 malloc 就意味着 fake chunk 没有办法被申请出来
这时就要借助 IO_str_overflow
了:
1 | int |
- 对于这个函数我们只需要关注3个函数即可:
malloc memcpy free
- 如果在此之前我们已经布置好了 tcache_stashing_unlink 并把
free hook
设置为 fake chunk,那么malloc
就会申请到free hook
,memcpy
就会往free hook
中写入数据,free
就会触发free hook
劫持 _IO_list_all
将其 vtable 由 _IO_file_jumps 修改为 _IO_str_jumps,那么当原本应该调用 IO_file_overflow 的时候,就会转而调用 IO_str_overflow
- 控制
_IO_buf_end
和_IO_buf_base
,我们就可以控制 malloc 的 size 以及写入的数据
House Of Pig 利用姿势
House Of Pig 文字版详细过程:
- 先用 UAF 漏洞泄露 libc 地址 和 heap 地址
- 再用 UAF 修改 largebin 内 chunk 的 fd_nextsize 和 bk_nextsize 位置,完成一次 largebin attack,将一个堆地址写到
__free_hook-0x8
的位置,使得满足之后的 tcache stashing unlink attack 需要目标 fake chunk 的 bk 位置内地址可写的条件 - 先构造同一大小的5个 tcache,继续用 UAF 修改该大小的 smallbin 内 chunk 的 fd 和 bk 位置,完成一次 tcache stashing unlink attack,由于前一步已经将一个可写的堆地址,写到了
__free_hook-0x8
,所以可以将__free_hook-0x10
的位置当作一个 fake chunk,放入到 tcache 链表的头部,但是由于没有 malloc 函数,我们无法将他申请出来 - 最后再用 UAF 修改 largebin 内 chunk 的 fd_nextsize 和 bk_nextsize 位置,完成第二次 largebin attack,将一个堆地址写到
_IO_list_all
的位置,从而在程序退出前 flush 所有 IO 流的时候,将该堆地址当作一个 FILE 结构体,我们就能在该堆地址的位置来构造任意 FILE结构了 - 在该堆地址构造 FILE 结构的时候,重点是将其 vtable 由 _IO_file_jumps 修改为 _IO_str_jumps,那么当原本应该调用 IO_file_overflow 的时候,就会转而调用如下的 IO_str_overflow
- 而该函数是以传入的 FILE 地址本身为参数的,同时其中会连续调用 malloc,memcpy,free 函数,且三个函数的参数又都可以被该 FILE 结构中的数据控制,那么适当的构造 FILE 结构中的数据,就可以实现利用 IO_str_overflow 函数中的 malloc 申请出那个已经被放入到 tcache 链表的头部的包含
__free_hook
的 fake chunk - 紧接着可以将提前在堆上布置好的数据,通过 IO_str_overflow 函数中的 memcpy 写入到刚刚申请出来的包含
__free_hook
的这个 chunk,从而能任意控制__free_hook
,这里可以将其修改为 system 函数地址 - 最后调用 IO_str_overflow 函数中的 free 时,就能够触发
__free_hook
,同时还能在提前布置堆上数据的时候,使其以字符串 “/bin/sh\x00” 开头,那么最终就会执行 system(“/bin/sh”)
版本对 House Of Pig 的影响
适用于 libc-2.31 及以后的新版本 libc