SROP
基本介绍:https://ctf-wiki.org/pwn/linux/user-mode/stackoverflow/x86/advanced-rop/srop/
wiki写的很详细了。
在传统的ROP上基于Sigreturn系统调用,伪造回调栈的frame,就是SROP
32位sigframe context:
1 | struct sigcontext |
64位:
1 | struct _fpstate |
以上两个栈帧context排布看起来比较复杂。但是我们完全不需要记,pwntools已经集成了 SigreturnFrame()这个函数,用来生成一个frame,然后我们可以指定其中寄存器的值。相当于一键伪造栈并快速控制其中寄存器的值。
伪造之后栈上的布局示例如上图,当然这些都是SigreturnFrame()会排布好的。
srop的题目肯定会给一条syscall;或者syscall;ret;的gadget,这是用来触发syscall_rt_sigreturn和read等等系统调用的关键
其次是对于rax的控制
我们知道ret2syscall是必须控制rax为我们想要的函数的系统调用号,在SROP的题目中一般有以下三种控制rax的方式:
1、题目直接给了mov rax, 0xf;(0xf是64位的sigreturn系统调用号,32位是0x77)
2、题目有其他间接控制rax的gadget比如mov rax,***;
3、没有直接与rax控制相关的gadget
前两种都能比较容易控制rax为我们想要的值。对于第三种,我们控制rax的手法就是利用read的返回值。
通常我们的攻击方法是先将栈地址转移到我们能明确知道地址的位置比如bss+0x500,或者先通过write syscall,rdx控制得大一点泄露出栈上的脏数据,进而泄露栈地址。
首先就是往我们一开始能控制的栈写东西,也就是题目给的栈溢出read,这一次写用的是SROP,也就是sigreturn syscall,这样可以在栈上的frame里控制rsp为目标写入地址,rip控制为syscall,rax控制为read(也就是0),其他rdi,rsi,rdx分别控制一下,就可以实现在将目标地址作为栈顶写入gadget。同时我们可以在程序开始之初指定"/bin/sh\x00"的地址,比如说控制成new_stack+0x200这样,那么在新的栈上控制frame进行SROP,执行execve_syscall的时候就可以指定rdi为new_stack+0x200,这样就顺利将binsh的地址传入了,但比较妙的是这时候"/bin/sh\x00"这几个字符还没出现在new_stack+0x200这个地址上,我们在newstack写入SROP的时候,最终将payload长度控制成0x200,再加上"/bin/sh\x00"就可以做到将binsh写到预设的binsh应该出现的地址。然后就getshell了。
cnss summer的那道SROP是比较模板的好题,等他们summer camp结束了我再把wp放这。
如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !