LCTF2017 2ez4u

之前一直听说的很经典的一个题目,最近才补了它。
做这道题目确实需要比较深的heap分配的功底,尤其是对大的chunk,large chunk,unsorted bin chunk。

具体来看看这个题目,这个题目利用到了一个新的方式 应当称之为Larger bin dup,但也同样有非预期解法。

vulnerability

题目建立了如下的数据结构,

在.bss段上的apple管理结构apples大小为0x10:

漏洞比较明显,delete函数在删除apple后,仅仅将其is_exist flag字段置为0


然而在四种操作 add, delete, edit, show中,只有add与delete是根据在.bss段上apples结构中的is_exist这个flag字段判断的,例如在add函数中:

在show与edit函数中,是根据apples结构中apple* 指针是否为NULL判断的,例如show函数中:

进而在apple[i]被delete后,还可以进行show与edit,实质上一个Use after free。

method1

题目中使用的输入函数会在任意字符串后加入"\0",没有直接泄露的机会,在数据结构上,apple chunk的前0x18byte都是color,value,number等数据,无法完整打印出libc或者heap地址。

所以,可以使用 large bin来泄露地址,顺便进行漏洞利用了。

1.泄露heap
Large bin 有fd_nextsizebk_nextsize指针中包含有heap地址,bk_nextsize在chunk的第0x18个字节,所以可用来泄露heap地址。

2.泄露libc地址
伪造larger bin,伪造large bin就是large bin dup的主要过程,当malloc在large bin中寻找合适的victim时,会根据bk_nextsize选择下一个large bin。

我们正好能修改的是bk_nextsize指针的值,如果将其指向一个伪造好的heap地址,当然前提是该heap地址需要能够Bypass Unlink的检查,这其中不只是fd,bk的检查,还有fd_nextsize与bk_nextsize的检查,当然这两个check基本一样,就可以将地址分配到伪造的fake chunk的位置。

泄露地址的思想是,分配到一个存在的chunk中,free 掉这个chunk成为unsorted bin chunk之后,分配小chunk将main_arena+0x58的地址推到伪造的large chunk的content内容中,之后show直接泄露。

  1. Getshell
    这个过程尝试了很多不同的姿势
    <1> 直接利用fastbin attack写__malloc_hook,但是因为前0x18个byte不能自由可控,无法顺利写__malloc_hook
    <2> 采用fastbin attack写_IO_2_1_stdout,本来以为可行,因为距离足够,但是在尝试的过程中,由于前0x18byte写入的内容有限制,发现其破坏了_IO_FILE结构的_mode使其由0xffffffff被overwrite为0xffffff00,不能触发vtable调用。

最后可以通过overwirite topchunk,也就是wp的解法了。

写topchunk到__free_hook-0xb58 ,继续分配写__free_hook为system,Getshell即可。
这个过程中,还有问题….

  • 写topchunk到__free_hook-0xb58后,需要分配大的chunk,在保证小于分配数量的情况下,写到__free_hook,而larger bin的链表结构被我们破坏了,所以需要修复,所以我将伪造的chunk分配到修改bk_nextsize的chunk之上,以便recover结构,确保之后的分配不会错误。
  • 将topchunk从__free_hook-0xb58分配到__free_hook的过程中,不能分配大小>0x400,因为分配large bin会触发malloc consolidate,而我们的fastbin 是有问题的,malloc consolidate肯定会出错。
  • hack __free_hook 之后,我们需要free 一个"/bin/sh"的chunk,而由于前8byte不可控,只能再通过伪造的large bin覆盖一波。
  • exp也不是完全能够成功的,必须保证heap地址是由0x56开头,0x55会在__libc_malloc crash。

method2

官方wp这个Overwrite Topchunk的方式

之前在Overwrite chunk,限制在heap必须以0x56开头,0x55会在__libc_malloc中crash
官方wp中,直接在

fastbinY 中利用Use after free在main_arena中写入了一个0x60,用做之后的跳板,这样就保证了100%的成功率,基本思想就是这样,官方wp的整体思路也是比较清晰的2333。

method3

实际上当发现题目中存在Use after free后,其实根本用不到Large bin attack,利用好edit与show即可,通过unsorted bin attack与 fastbin attack即可。

  1. 通过use after free直接能够打印出main_arena的地址,其实根本用不到larger bin dup
  2. 通过edit构造unsorted bin先将main_arena的地址布置在__free_hook之前,再fastbin attack将__free_hook修改成system,该过程需要简单的堆排步。
  3. unsorted bin attack 之后 unsorted bin 被破坏,不能够再继续通过unsorted bin分配,可以先利用fastbin attack在FastbinY上预留好地址,直接add拿到该fastbin并写入即可。
  4. 提前利用edit在某个apple的chunk开始写入"/bin/sh",触发system("/bin/sh")

method4

在method3的基础上,method3在unsorted bin后unsorted bin损坏之后无能为力,method4中采用的方式是直接将unsorted bin attack与 fastbin attack 利用的 chunk 覆盖为一个chunk。因为fastbin的分配总是优先与unsorted bin,进而之后还可以add。

Scenario最后通过写__malloc_hook为one_gadget,但是栈不满足条件,通过__realloc_hook修一下栈即可。

发表评论

电子邮件地址不会被公开。