unlink

  • 以jarvis oj 的guestbook2, level6, level6_x64和hitcon2014-stkof三个作为对比来讲讲思路

level6_x64 and guestbook2

  • 以从64位的为例

  • 按照堆题的出题习惯, 照例有四个有用的选项和一个初始化

    • init
    • list
    • new
    • edit
    • delete
  • 对比各个函数,不难看出这是一个嵌套的数据结构, 因为它整体偏移一个节点的时候都是以0x18为基数的,但它在此之前有两个8字节的单元不包含在内.

  • 所以数据结构就是这样

  • 直接来分析漏洞处, 经典的Double free和UAF, 配合起来很舒服.其中myread是一个将字符串转换为数字的函数,他其中有调用了一个单个读入的函数

  • 同样是最终调用了单个读入的函数, 上一个read函数后将末尾的值置为0, 而在new功能函数中,调用了fill函数,而fill函数中又调用了read函数,但是这次没有把末尾置为0.所以这是一个可以尝试利用的信息泄露(leak)点.

  • 于是乎,这里整理两种相似但又有所区别的漏洞利用方法.

    此处借鉴两位师傅的博客进行学习的, 详细内容看链接:

https://github.com/bash-c/pwn_repo/blob/master/jarvisOJ_level6_x64/exp.py

https://aluvion.github.io/2019/05/09/%E5%A0%86%E5%85%A5%E9%97%A8-JarvisOJ-Level6-x64/

  • 相同点1:leak heapbase address 先创建5个small chunk,这是为了unsorted bin做准备。然后先释放第四个chunk,在释放第二个chunk,这是为了将第二个的fd指针指向第四个,具体原因翻机制。。。接着两者获得heapbase的方法, 都是通过edit修改第一个chunk的size, 增大content来覆盖第二个chunk的head.这时调用list函数, 判断我们content因为之前读入时没有设置末尾为0,所以接下去泄露,即把第二个chunk的fd的内容打印出来,即第三个chunk的位置, 然后减去之前分配的空间即得堆地址.
  • 相同点2:unlink 在原chunk中伪造一个fake chunk, 即有如下的对应关系 格式: (原) -> (现)
    • fd位置处 -> prev_size
    • bk位置处 -> size
    • fd + 0x10 -> FD(chunk0addr-0x8*3)
    • bk + 0x10 -> BK(chunk0addr-0x8*2)
    • 原chunk可用大小 - 0x8 *4
    • 下一个chunk的prev_size -> 值减0x10,因为伪造少了0x10嘛
    • 下一个chunk的size -> 具体而定,但最后一位为0
  • 相同点3:漏洞最终的利用方式还是通过将全局变量中指向chunk1的指针改为指向atoi的指针,因为只要有输入,就会调用该函数处理输入.
  • 不同点:leak libc address. 第一种方法采用的是通过刚才的unlink操作,原先的chunk0addr = &chunk0addr的值减去三个单元.所以可以从现在的chunk0addr开始往后覆盖,只将原先chunk0的content的值改为atoi的got值,然后泄露减去symbols值即可.而第二种方法,更为直接,它采用了和leak heapbase类似的方法,但这次多覆盖了个fd,于是会把bk的值泄露出来,因为此时chunk1的bk指向的是main_arena+88 可以调试查看,然后减去__malloc_hook的symbols,减去88,再减去0x10或0x20.
  • 不同点各有利弊, 第一种比较方便准确, 但是有条件限制,如有全局指针啊什么的, 第二种虽然粗暴但是通用性好,应该是都能用的.

level6

https://github.com/bash-c/pwn_repo/blob/master/jarvisOJ_level6/exp.py

https://aluvion.github.io/2019/05/09/%E5%A0%86%E5%85%A5%E9%97%A8-JarvisOJ-Level6-x64/

  • 第一种方法就是改了个偏移量,改了个通用函数是strtol.
  • 第二种方法在泄露libc地址的时候,减去的是memalign_hook_libc的值,再减48(偏移值),再减去0x10或0x20.这里heap和libc的及地址可以一起leak出来,因为fd和bk都为4字节,所以64位机泄露一个8字节单元时将两者一起泄露.同时改了通用函数是free,这也意味着在某个chunk处(这里用的是chunk1)的content得填/bin/sh\x00,然后最后要delete 它才能调用system(‘/bin/sh\x00’)

hitcon2014-stkof

待补充…因为我exp没调通…