2020 ciscn比赛WP,慢慢学习吧。感觉对很多题还是不熟,对常见的堆利用做得太慢,知道漏洞了但是想很久才能知道其利用方法。说明还是对堆理解不够,以后也渐渐的学着去看 glibc 的源码吧,感觉理解更深刻。
Unsorted Bin Attack
Unsorted Bin Attack被利用的前提是控制 Unsorted Bin Chunk 的bk 指针。
Unsorted Bin Attack 可以达到的效果是实现修改任意地址为一个较大的数值
来源
- 当一个较大的 chunk 被分割成两半后,如果剩下的部分大于 MINSIZE,就会被放到 Unsorted bin中;
- 释放一个不属于 fast bin的 chunk,并且该 chunk 不和 top chunk 紧邻时,该 chunk 会被首先放到 unsorted bin中。
- 当进行 malloc_consolidate时,可能会把合并后的 chunk 放到 unsorted bin中,如果不是 top chunk 近邻的话。
基本使用情况
1, Unsorted Bin在使用的过程中,采用的遍历顺序是 FIFO,即插入的时候插入到 unsorted bin 的头部,取出的时候从链表尾获取
- 在程序 malloc时,如果在fastbin,small bin中找不到对应大小的 chunk,就会尝试从 unsorted bin 中寻找 chunk。如果取出来的 chunk大小刚好满足,就会直接返回给用户,否则就会把这些 chunk 插入到对应的 bin 中。
原理
在 malloc.c 中 _int_malloc 代码有:当将一个 unsorted bin 取出的时候,会将 bck->fd 的位置写入 本 unsorted bin 的位置。
1 | /* remove from unsorted list */ |
即,如果我们控制了 bk 的值,就能将 unsorted_chunks (av) 写到任意地址。
hhb note_three
house of orange知识补充
house of orange 的攻击方法,可以直接参考wiki :https://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/house_of_orange-zh/。
这里我只补充,为什么修改了top chunk的fakesize 为0xb0,而申请0x90的chunk,就会将 此时的top chunk放入 unsorted bin中。按照house of orange原理,我们将 topchunk 的size改小后,只要申请一个 大于此时top chunk的size的块,_int_malloc就会执行 将topchunk放入到 unsorted bin中,并将我们申请的块放到新分配的topchunk。
看 libc的源码,我们可以看到 _int_malloc 在分配块时,有7个步骤:
- 从 fastbin 中查找是否有合适的块;
- 从 small bin中查找;
- 从large bin中查找,将fast bin合并到 unsortedbin中。然后从 small bin 和 large bin中分配。
- 从 Unsortedbin 中查找;
- 从 top chunk分配,并更新top chunk的值;
- 如果top chunk不够,则将fastbin 进行合并,再分配。
- 将 当前 top chunk放入unsortedbin 后,再执行 sysmalloc系统中分配。
而在 sysmalloc中,如果再次分配 top chunk。其在将当前top chunk放入 unsortedbin时,会执行如下操作。会先判断当前top chunk的old_size是否大于MINSIZE,如果大于就将当前 top chunk分成两块,一块为fencepost大小为MINSIZE,另一块大小为 old_size-MINSIZE并且执行 _int_free放入 unsortedbin中。
所以,这里改topchunk 的 fakesize为 0xb0,最终申请的chunk 大小为 0xa0,加上 0x20 的 fencepost,所以此时的 topchunk 是不够的。满足将 现在 top chunk放入 unsorted bin的条件。
漏洞分析
漏洞点也是在 edit() 函数,可以实现堆溢出。没有 free 函数。
这道题,需要先利用 house of orange,在 bss 上构造一个伪造的 usnorted bin chunk。然后分配该 fake chunk,然后通过修改该 fake chunk 可以修改 note_list 数组,实现任意地址修改。然后先修改 aoti_got 为 printf_got 泄露libc 地址,在修改为 system 地址 getshell。
难点在于,如何 在 bss 上伪造一个chunk 并分配。当我们将 top chunk 放到 unsorted bin中后,我们可以先申请一块小的chunk。在通过堆溢出修改该chunk 的下一块空闲的unsorted bin,将该chunk 的bk 指针设为 note_list-0x10,然后再申请该chunk。则此时 note_list 的值被修改为 main_arena+88。main_arena+88 表示 top chunk,我们修改main_arena+88 的值为 一个fake_top_chunk,这个值我现在有点没搞懂是否有条件,但目前还没要求。设置 main_aerna+90 last_remainder 为 0,这样可以直接进入分配 unsorted bin,绕过 last remainder分配。然后设置 main_aerna+98 为 我们伪造的fake chunk 的头指针,这里就是unsortde bin 的 fd 和bk指针。
我们伪造的 fake chunk 地址为 0x602130,因为这个地址 我们刚好可以在这里 伪造 chunk的头部,和修改到 0x6021c0 的值。十分巧妙。
后面就是常规的修改 atoi_got 为printf_plt ,先泄露libc地址。然后这里修改完之后,有个注意点是 以后执行到 atoi 函数返回的其实是你输入的字符数,所以我们也把 0x6021d0 给覆盖为 atoi_got,是因为后面 printf 最小都会返回 1,只能edit chunk1。
EXP
1 | from pwn import * |
nofree
上面做了 hhb 的 note_three ,那么这道题就真的一摸一样了。尝试一下其他做法吧。
漏洞分析
漏洞点,在edit函数里 输入新的content时,是按照原来的size 读入的。但是原有的 chunk是最开始通过strdup 函数申请的,其大小是与输入的大小一致。所以,我们在 edit时就存在 堆溢出漏洞。
然后这道题 还是先利用 house of orange 的思想,将 top chunk 改小。不过这次我们直接将 top chunk放入 fast bin中。然后修改 fast bin 的 fd 指针 指向我们的 fake chunk ,实现分配堆块到 bss 上。
还有这里是直接修改的 strdup 的值。
EXP
1 | from pwn import * |
maj
程序分析
这道题中间加了很多混淆,然后大概跑了一下,发现和程序主题逻辑没有任何关系,也就不用管。
然后程序漏洞在 delete() 函数中,free 堆块指针后 并没有将 堆块指针清空和 将size 置为0。也就是存在 UAF 漏洞。
然后程序开了 Canary、NX 和 Full RELRO,也就是我们不能通过覆盖 Got表地址来 getshell。
然后程序中没有输出的地方,也就是我们得想办法泄露 libc 地址。
delete 函数存在 UAF漏洞,释放堆块后,未将堆块指针置为 NULL;
漏洞分析
这道题的思路,应该是利用UAF漏洞在stdout结构体上伪造一个堆块,然后修改stdout结构体,泄露libc地址。
随后修改 malloc_hook 为 one_gadget 地址来 getshell。
EXP
1 | from pwn import * |
Easy-box
程序总体和 上一题类似,再次不再多述。
wow
程序分析
该题目,属于VM Pwn类型,后续会做一个专题学习一下 VM Pwn,先挖个坑。
利用分析
EXP
- 本文作者: A1ex
- 本文链接: http://yoursite.com/2020/08/21/ciscn-2020/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!