type
status
date
slug
summary
tags
category
icon
password
这个手法比较好理解,问题就是利用的条件比较多,再真实情况下可以不太好利用,当然也有可以是现在我用的版本比较高的情况,这个手法最多可以可以利用到glibc2.35。我下面要举得例子就是再
Ubuntu GLIBC 2.35-0ubuntu3.8
的条件下运行的。这个手法的具体过程不细讲,这里我简单说一下我的理解,不一定对
再程序中有一个报错的过程,当我们把topchunk的size段修改为页对齐的大小,其实就是
house of orange
用来产生unsortedbin
的过程,当我们此时申请一个大小大于这个topchunk的chunk时,程序就会执行如下的流程,当程序执行到
fflush
这个函数是会有如下的情况发生
程序会跳转执行
rbp+0x60
的地址,此时我们可以看见rbp中的值为_IO_file_jumps
的起始地址,如果此时我们把_IO_file_jumps+0x60
的值修改为后们函数的地址,那程序执行到这里时就会直接去执行后们函数

这里其实就包含了我们说的这种手法的困难点,这里我们用到这个种手法的版本一般都是比较高的版本,然后再高版本中ogg不太好直接用到,这里我们又没有上面办法进行传参,因此通过ROP去拿到shell相对来说比较困难。
还有一个点就是我们之前提到我们要做的就是修改程序中
_IO_file_jumps+0x60
的值,但是再glibc2.35的版本中这个地址是不可写的性质,因此我们还要使用mprotect
函数对这个地址进行修改,
因此这个手法说起来整体的思路就一个,修改程序中
_IO_file_jumps+0x60
的值为后门函数,然后让程序执行house of orange
的前半段。使程序执行后门函数。但问题就在与程序中是否有直接可以执行的完整后门函数,与
_IO_file_jumps+0x60
的所在地址是否有可写权限。然后就是如下的,可以调试一下看看,源于,感谢师傅写的poc。
调用
_IO_file_jumps
的时候,参数就是IO_2_1_stderr
的flag字段,所以当执行后门函数时把IO_2_1_stderr
的flag字段修改为/bin/sh
就可以执行system(/bin/sh)
当然上的其实还会有很多条件,那就是对当程序开启沙箱的时候使用的,这里就讲一下当程序开沙箱时要怎么整。
我们再堆题中对开了沙箱的题目,出了之前我提到的那种把栈上的地址打印出来的办法之外,用的最多的其实是控制程序执行
setcontext
函数中的命令,这里从setcontext+0x61
开始
总的来说程序会执行如上的命令来帮我修改寄存器的值,我就可以借助这个把栈顶指针rsp修改为我们构造好的ROP的地址。
重点就在上面标红的这3个命令,
1.把
rdx+0xa0
的地址内容传给rsp,这里我们就可以把
rdx+0xa0
的地址修改为ROP的起始地址,然后程序就会修改栈的地址为ROP2.把
rdx+0xa8
的地址内容传给rcx,rcx再压栈这里我们要把
rdx+0xa8
的地址修改ret
的地址,这样程序就会再执行完这个setcontext
函数后使程序通过ret跳转执行ROP上的orw。于是现在我们就要开始修找当程序执行到
setcontext
函数前rdx中的值为多少,其对应的+0xa0和0xa8的地址又是哪
这里我们就可以看到此时程序中的rbp执向的是
0x7ffff7e17600 (_IO_file_jumps)
(不要直接认为是_IO_file_jumps
的地址,这个再程序中有两个完全相同的,但地址不同)。于是我们就要修改0x7ffff7e17600+0xa0
为ROP的起始地址,0x7ffff7e17600+0xa8
为ret的地址。这里注意当在libc版本小于glibc2.35中
setcontext
函数中的这几个指令的修改用的是rdi寄存器,在遇到时要记得随机变化。当完成如上的修改后就可以直接把上面提到的后门函数地址修改为
setcontext+0x61
的地址然后程序就会执行,并把0x7ffff7e17600+0xa0
中的ROP的起始地址传给rsp
然后把ret压入栈中

当程序执行完这个函数后就会执行这个ret

然后就会执行ROP上布置好的orw,把flag读出来。

给上完整的poc,其实就是上面那个修改了3个命令
- 作者:wgiegie
- 链接:https://tangly1024.com/article/1623ecc9-5160-803f-9ed8-c241e575baaf
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章